port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
[*.cs]
dotnet_diagnostic.IDE0019.severity = none
dotnet_diagnostic.IDE0038.severity = none
dotnet_diagnostic.IDE0044.severity = none
dotnet_diagnostic.IDE0052.severity = none
dotnet_diagnostic.IDE0058.severity = none
dotnet_diagnostic.IDE0062.severity = none
dotnet_diagnostic.IDE0090.severity = none

View File

@@ -0,0 +1,23 @@
<UserControl x:Class="NodeNetwork.Toolkit.BreadcrumbBar.BreadcrumbBarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<ListView x:Name="list" SelectionMode="Single">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Path Data="M 0,0 L 2.5,2.5 L 0,5" Margin="0,2,6,0" StrokeThickness="2" Stroke="#555555" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Name}" TextAlignment="Center" VerticalAlignment="Stretch"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</UserControl>

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Controls;
using NodeNetwork.Utilities;
using ReactiveUI;
using ReactiveUI.Legacy;
namespace NodeNetwork.Toolkit.BreadcrumbBar
{
public partial class BreadcrumbBarView : UserControl, IViewFor<BreadcrumbBarViewModel>
{
#region ViewModel
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register(nameof(ViewModel), typeof(BreadcrumbBarViewModel), typeof(BreadcrumbBarView), new PropertyMetadata(null));
public BreadcrumbBarViewModel ViewModel
{
get => (BreadcrumbBarViewModel)GetValue(ViewModelProperty);
set => SetValue(ViewModelProperty, value);
}
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (BreadcrumbBarViewModel)value;
}
#endregion
public BreadcrumbBarView()
{
InitializeComponent();
this.WhenActivated(d =>
{
this.BindList(ViewModel, vm => vm.ActivePath, v => v.list.ItemsSource).DisposeWith(d);
this.WhenAnyValue(v => v.list.SelectedItem)
.Where(i => i != null)
.Cast<BreadcrumbViewModel>()
.Do(_ => list.UnselectAll())
.InvokeCommand(this, v => v.ViewModel.SelectCrumb).DisposeWith(d);
});
}
}
}

View File

@@ -0,0 +1,76 @@
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using DynamicData;
using ReactiveUI;
namespace NodeNetwork.Toolkit.BreadcrumbBar
{
/// <summary>
/// Viewmodel for a single element of the BreadcrumbBar.
/// </summary>
public class BreadcrumbViewModel : ReactiveObject
{
#region Name
/// <summary>
/// Displayed name of the crumb.
/// </summary>
public string Name
{
get => _name;
set => this.RaiseAndSetIfChanged(ref _name, value);
}
private string _name = "";
#endregion
}
/// <summary>
/// ViewModel for the BreadcrumbBar.
/// This UI element displays a path as a list of path elements (crumbs), allowing navigation by selection of path elements.
/// </summary>
public class BreadcrumbBarViewModel : ReactiveObject
{
static BreadcrumbBarViewModel()
{
NNViewRegistrar.AddRegistration(() => new BreadcrumbBarView(), typeof(IViewFor<BreadcrumbBarViewModel>));
}
/// <summary>
/// The path that is currently displayed in the bar.
/// Add or remove elements to modify the path.
/// </summary>
public ISourceList<BreadcrumbViewModel> ActivePath { get; } = new SourceList<BreadcrumbViewModel>();
#region ActiveElement
/// <summary>
/// The deepest element of the currect path. (Last element of ActivePath)
/// </summary>
public BreadcrumbViewModel ActiveItem => _activeItem.Value;
private readonly ObservableAsPropertyHelper<BreadcrumbViewModel> _activeItem;
#endregion
/// <summary>
/// Navigate to the subpath represented by the selected crumb which is passed as a parameter.
/// Only this crumb and its ancestors are kept, the rest of the path is removed.
/// </summary>
public ReactiveCommand<BreadcrumbViewModel, Unit> SelectCrumb { get; }
public BreadcrumbBarViewModel()
{
SelectCrumb = ReactiveCommand.Create((BreadcrumbViewModel crumb) =>
{
ActivePath.Edit(l =>
{
int index = l.IndexOf(crumb);
for (int i = l.Count - 1; i > index; i--)
{
l.RemoveAt(i);
}
});
});
ActivePath.Connect().Select(_ => ActivePath.Count > 0 ? ActivePath.Items.ElementAt(ActivePath.Count - 1) : null)
.ToProperty(this, vm => vm.ActiveItem, out _activeItem);
}
}
}

View File

@@ -0,0 +1,249 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Text;
using System.Windows;
using DynamicData;
using NodeNetwork.ViewModels;
using ReactiveUI;
namespace NodeNetwork.Toolkit.ContextMenu
{
/// <summary>
/// A viewmodel for a context menu that allows users to add nodes to a network.
/// </summary>
public class AddNodeContextMenuViewModel : SearchableContextMenuViewModel
{
static AddNodeContextMenuViewModel()
{
NNViewRegistrar.AddRegistration(() => new SearchableContextMenuView(), typeof(IViewFor<AddNodeContextMenuViewModel>));
}
#region Network
/// <summary>
/// The network to which the nodes are to be added.
/// </summary>
public NetworkViewModel Network
{
get => _network;
set => this.RaiseAndSetIfChanged(ref _network, value);
}
private NetworkViewModel _network;
#endregion
/// <summary>
/// The format that is used to create labels for the menu entries based on the node name.
/// E.g. "Add {0}"
/// </summary>
public string LabelFormat { get; }
/// <summary>
/// When adding a node to the network,
/// this function is used to determine the position at which it is placed.
/// </summary>
public Func<NodeViewModel, Point> NodePositionFunc { get; set; } = (node) => new Point();
/// <summary>
/// A callback that is called after a node is added to the network through this menu.
/// </summary>
public Action<NodeViewModel> OnNodeAdded { get; set; } = node => { };
/// <summary>
/// An interaction that is used to open contextmenu views given a SearchableContextMenuViewModel.
/// Used in ShowAddNodeForPendingConnectionMenu to display this menu, and a menu for choosing an endpoint.
/// </summary>
public Interaction<SearchableContextMenuViewModel, Unit> OpenContextMenu { get; } = new Interaction<SearchableContextMenuViewModel, Unit>();
private ReactiveCommand<NodeTemplate, Unit> CreateNode { get; }
public AddNodeContextMenuViewModel(string labelFormat = "{0}")
{
LabelFormat = labelFormat;
CreateNode = ReactiveCommand.Create<NodeTemplate, Unit>((template) =>
{
var nodeInstance = template.Factory();
Network.Nodes.Add(nodeInstance);
nodeInstance.Position = NodePositionFunc(nodeInstance);
OnNodeAdded(nodeInstance);
return Unit.Default;
});
}
/// <summary>
/// Adds a new node type to the list.
/// Every time a node is added to a network from this list, the factory function in the template
/// will be called to create a new instance of the viewmodel type.
/// </summary>
/// <param name="template">The template with the node type to add.</param>
public void AddNodeType(NodeTemplate template)
{
Commands.Add(new LabeledCommand
{
Label = string.Format(LabelFormat, template.Instance.Name),
Command = CreateNode,
CommandParameter = template
});
}
public void AddNodeTypes(IEnumerable<NodeTemplate> templates)
{
foreach (var nodeTemplate in templates)
{
AddNodeType(nodeTemplate);
}
}
private void ShowOnlyConnectableNodes(PendingConnectionViewModel testCon)
{
foreach (var cmd in Commands.Items)
{
var curNodeTemplate = (NodeTemplate)cmd.CommandParameter;
bool hasValidEndpoint =
testCon.InputIsLocked ?
GetConnectableOutputs(curNodeTemplate.Instance, testCon).Any() :
GetConnectableInputs(curNodeTemplate.Instance, testCon).Any();
cmd.Visible = hasValidEndpoint;
}
}
public void ShowAddNodeForPendingConnectionMenu(PendingConnectionViewModel pendingCon)
{
var testCon = new PendingConnectionViewModel(pendingCon.Parent) // Copy used to test which inputs/outputs will work with the pending connection
{
Input = pendingCon.Input,
InputIsLocked = pendingCon.InputIsLocked,
Output = pendingCon.Output,
OutputIsLocked = pendingCon.OutputIsLocked
};
ShowOnlyConnectableNodes(testCon);
// After a node type is chosen, pick an endpoint
OnNodeAdded = node =>
{
if (testCon.InputIsLocked)
{
var outputs = GetConnectableOutputs(node, testCon).ToList();
if (outputs.Count == 1)
{
// If only 1 output matches, select this one
Network.Connections.Add(Network.ConnectionFactory(pendingCon.Input, outputs[0]));
Network.RemovePendingConnection();
}
else
{
// Open a menu to let the user choose the desired output to connect to
var chooseEndpointVM = new SearchableContextMenuViewModel();
var cmd = ReactiveCommand.Create<NodeOutputViewModel, Unit>((o) =>
{
Network.Connections.Add(Network.ConnectionFactory(pendingCon.Input, o));
Network.RemovePendingConnection();
return Unit.Default;
});
foreach (var output in outputs)
{
chooseEndpointVM.Commands.Add(new LabeledCommand
{
Command = cmd,
CommandParameter = output,
Label = output.Name
});
}
OpenContextMenu.Handle(chooseEndpointVM).Subscribe();
}
}
else
{
var inputs = GetConnectableInputs(node, testCon).ToList();
if (inputs.Count == 1)
{
Network.Connections.Add(Network.ConnectionFactory(inputs[0], pendingCon.Output));
Network.RemovePendingConnection();
}
else
{
var chooseEndpointVM = new SearchableContextMenuViewModel();
var cmd = ReactiveCommand.Create<NodeInputViewModel, Unit>((i) =>
{
Network.Connections.Add(Network.ConnectionFactory(i, pendingCon.Output));
Network.RemovePendingConnection();
return Unit.Default;
});
foreach (var input in inputs)
{
chooseEndpointVM.Commands.Add(new LabeledCommand
{
Command = cmd,
CommandParameter = input,
Label = input.Name
});
}
OpenContextMenu.Handle(chooseEndpointVM).Subscribe();
}
}
};
OpenContextMenu.Handle(this).Subscribe();
}
/// <summary>
/// Given a set of node templates, return those which have an endpoint
/// that could be connected to the specified pending connection.
/// </summary>
public static IEnumerable<NodeTemplate> GetConnectableNodes(IEnumerable<NodeTemplate> candidateNodeTemplates, PendingConnectionViewModel testCon)
{
foreach (var curNode in candidateNodeTemplates)
{
bool hasValidEndpoint =
testCon.InputIsLocked ?
GetConnectableOutputs(curNode.Instance, testCon).Any() :
GetConnectableInputs(curNode.Instance, testCon).Any();
if (hasValidEndpoint)
{
yield return curNode;
}
}
}
/// <summary>
/// Given a node viewmodel, return the outputs which could be connected to the pending connection.
/// Assumes testCon.Input is set.
/// </summary>
public static IEnumerable<NodeOutputViewModel> GetConnectableOutputs(NodeViewModel node, PendingConnectionViewModel testCon)
{
var validator = testCon.Input.ConnectionValidator;
foreach (var curOutput in node.Outputs.Items)
{
testCon.Output = curOutput;
if (curOutput.MaxConnections > 0 && validator(testCon).IsValid)
{
yield return curOutput;
}
}
}
/// <summary>
/// Given a node viewmodel, return the inputs which could be connected to the pending connection.
/// Assumes testCon.Output is set.
/// </summary>
public static IEnumerable<NodeInputViewModel> GetConnectableInputs(NodeViewModel node, PendingConnectionViewModel testCon)
{
foreach (var curInput in node.Inputs.Items)
{
var validator = curInput.ConnectionValidator;
testCon.Input = curInput;
if (curInput.MaxConnections > 0 && validator(testCon).IsValid)
{
yield return curInput;
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
<ContextMenu x:Class="NodeNetwork.Toolkit.ContextMenu.SearchableContextMenuView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:NodeNetwork.Toolkit.ContextMenu"
xmlns:viewModels="clr-namespace:NodeNetwork.ViewModels;assembly=NodeNetwork"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" x:Name="self">
<ContextMenu.Resources>
<Style TargetType="{x:Type MenuItem}">
<Style.Setters>
<Setter Property="Command" Value="{Binding Command}"/>
<Setter Property="CommandParameter" Value="{Binding CommandParameter}"/>
</Style.Setters>
</Style>
<DataTemplate DataType="{x:Type local:LabeledCommand}">
<TextBlock><Run Text="{Binding Label}"/></TextBlock>
</DataTemplate>
</ContextMenu.Resources>
<ContextMenu.ItemsSource>
<CompositeCollection>
<MenuItem x:Name="SearchMenuItem" StaysOpenOnClick="True">
<MenuItem.Header>
<TextBox x:Name="SearchTextBox" MinWidth="150"></TextBox>
</MenuItem.Header>
</MenuItem>
<CollectionContainer x:Name="CollectionContainer"/>
<Separator/>
<CollectionContainer x:Name="ContainerBelowSearch"/>
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>

View File

@@ -0,0 +1,134 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DynamicData;
using NodeNetwork.Utilities;
using ReactiveUI;
namespace NodeNetwork.Toolkit.ContextMenu
{
public partial class SearchableContextMenuView : IViewFor<SearchableContextMenuViewModel>
{
#region ViewModel
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(nameof(ViewModel),
typeof(SearchableContextMenuViewModel), typeof(SearchableContextMenuView), new PropertyMetadata(null));
public SearchableContextMenuViewModel ViewModel
{
get => (SearchableContextMenuViewModel)GetValue(ViewModelProperty);
set => SetValue(ViewModelProperty, value);
}
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (SearchableContextMenuViewModel)value;
}
#endregion
#region ChildrenBelowSearch
public static readonly DependencyProperty ChildrenBelowSearchProperty =
DependencyProperty.Register(nameof(ChildrenBelowSearch), typeof(IEnumerable), typeof(SearchableContextMenuView), new PropertyMetadata(new object[0]));
public IEnumerable ChildrenBelowSearch
{
get => (IEnumerable)GetValue(ChildrenBelowSearchProperty);
set => SetValue(ChildrenBelowSearchProperty, value);
}
#endregion
#region ReferencePointElement
public static readonly DependencyProperty ReferencePointElementProperty =
DependencyProperty.Register(nameof(ReferencePointElement), typeof(IInputElement), typeof(SearchableContextMenuView), new PropertyMetadata(null));
public IInputElement ReferencePointElement
{
get => (IInputElement)GetValue(ReferencePointElementProperty);
set => SetValue(ReferencePointElementProperty, value);
}
#endregion
#region OpenPoint
public static readonly DependencyProperty OpenPointProperty =
DependencyProperty.Register(nameof(OpenPoint), typeof(Point), typeof(SearchableContextMenuView), new PropertyMetadata(new Point()));
public Point OpenPoint
{
get => (Point)GetValue(OpenPointProperty);
private set => SetValue(OpenPointProperty, value);
}
#endregion
public SearchableContextMenuView()
{
InitializeComponent();
this.Bind(ViewModel, vm => vm.SearchQuery, v => v.SearchTextBox.Text);
this.BindList(ViewModel, vm => vm.VisibleCommands, v => v.CollectionContainer.Collection);
Binding myBinding = new Binding(nameof(ChildrenBelowSearch)) { Source = this };
BindingOperations.SetBinding(ContainerBelowSearch, CollectionContainer.CollectionProperty, myBinding);
this.Opened += (sender, args) =>
{
SearchTextBox.Focus();
if (ReferencePointElement != null)
{
OpenPoint = Mouse.GetPosition(ReferencePointElement);
}
};
// This var is needed to ensure both key down and key up of arrow keys happened in the textbox,
// otherwise moving into the textbox will immediately move out again.
bool arrowWasPressedInTextBox = false;
this.SearchTextBox.PreviewKeyDown += (sender, args) =>
{
if (args.Key == Key.Enter || args.Key == Key.Return)
{
if (ViewModel.VisibleCommands.Count > 0)
{
var firstEntry = ViewModel.VisibleCommands.Items.First();
firstEntry.Command.Execute(firstEntry.CommandParameter);
this.IsOpen = false;
}
}
else if (args.Key == Key.Escape && SearchTextBox.Text.Length > 0)
{
SearchTextBox.Text = "";
args.Handled = true;
}
else if (args.Key == Key.Up || args.Key == Key.Down)
{
arrowWasPressedInTextBox = true;
}
};
this.SearchTextBox.PreviewKeyUp += (sender, args) =>
{
if (arrowWasPressedInTextBox && (args.Key == Key.Up || args.Key == Key.Down))
{
arrowWasPressedInTextBox = false;
var dir = args.Key == Key.Up ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next;
var traversalRequest = new TraversalRequest(dir);
var focusedElem = Keyboard.FocusedElement as FrameworkElement;
focusedElem?.MoveFocus(traversalRequest);
}
};
this.SearchMenuItem.GotKeyboardFocus += (sender, args) => { SearchTextBox.Focus(); };
}
}
}

View File

@@ -0,0 +1,126 @@
using DynamicData;
using ReactiveUI;
using System;
using System.Linq;
using System.Reactive.Linq;
using System.Windows.Input;
namespace NodeNetwork.Toolkit.ContextMenu
{
/// <summary>
/// A data type containing a command, parameter and display properties.
/// </summary>
public class LabeledCommand : ReactiveObject
{
#region Label
/// <summary>
/// The label that is displayed in the menu
/// </summary>
public string Label
{
get => _label;
set => this.RaiseAndSetIfChanged(ref _label, value);
}
private string _label = "";
#endregion
#region Visible
/// <summary>
/// Should the command be displayed in the menu?
/// </summary>
public bool Visible
{
get => _visible;
set => this.RaiseAndSetIfChanged(ref _visible, value);
}
private bool _visible = true;
#endregion
#region Command
/// <summary>
/// The command to be executed.
/// </summary>
public ICommand Command
{
get => _command;
set => this.RaiseAndSetIfChanged(ref _command, value);
}
private ICommand _command = null;
#endregion
#region CommandParameter
/// <summary>
/// The parameter to be passed to the command on execution.
/// </summary>
public object CommandParameter
{
get => _commandParameter;
set => this.RaiseAndSetIfChanged(ref _commandParameter, value);
}
private object _commandParameter = null;
#endregion
}
/// <summary>
/// A viewmodel for a context menu in which the entries can be filtered by the user based on a searchquery.
/// </summary>
public class SearchableContextMenuViewModel : ReactiveObject
{
static SearchableContextMenuViewModel()
{
NNViewRegistrar.AddRegistration(() => new SearchableContextMenuView(), typeof(IViewFor<SearchableContextMenuViewModel>));
}
/// <summary>
/// List of all the available commands in the menu.
/// </summary>
public ISourceList<LabeledCommand> Commands { get; } = new SourceList<LabeledCommand>();
/// <summary>
/// List of commands that are actually visible in the menu.
/// This list is based on Commands and SearchQuery.
/// </summary>
public IObservableList<LabeledCommand> VisibleCommands { get; }
#region SearchQuery
/// <summary>
/// The current search string that is used to filter Nodes into VisibleNodes.
/// </summary>
public string SearchQuery
{
get => _searchQuery;
set => this.RaiseAndSetIfChanged(ref _searchQuery, value);
}
private string _searchQuery = "";
#endregion
#region MaxItemsDisplayed
/// <summary>
/// Only the first MaxItemsDisplayed items from Commands that match the query are displayed.
/// </summary>
public int MaxItemsDisplayed
{
get => _maxItemsDisplayed;
set => this.RaiseAndSetIfChanged(ref _maxItemsDisplayed, value);
}
private int _maxItemsDisplayed = int.MaxValue;
#endregion
public SearchableContextMenuViewModel()
{
var onQueryChanged =
this.WhenAnyValue(vm => vm.SearchQuery, vm => vm.MaxItemsDisplayed)
.Throttle(TimeSpan.FromMilliseconds(70), RxApp.MainThreadScheduler)
.Publish();
onQueryChanged.Connect();
VisibleCommands = Commands.Connect()
.AutoRefreshOnObservable(_ => onQueryChanged)
.AutoRefresh(cmd => cmd.Label)
.AutoRefresh(cmd => cmd.Visible)
.Filter(cmd => cmd.Visible && (cmd.Label ?? "").ToUpper().Contains(SearchQuery?.ToUpper() ?? ""))
.Top(MaxItemsDisplayed)
.AsObservableList();
}
}
}

View File

@@ -0,0 +1,8 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]

View File

@@ -0,0 +1,356 @@
using System.Collections.Generic;
using System.Linq;
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit
{
/// <summary>
/// This class is a collection of various graph algoritms.
/// </summary>
public class GraphAlgorithms
{
/*
* Algorithm:
* 1. Pick next ready node from the nodes-to-check list, set as current
*
* a. Mark current node as busy
* b. For each input of the current node, find the connected node
* c. Check connected node state
* -> if ready
* => set connected node as current and goto a
* -> if busy
* => recursion found!
* => mark all busy nodes as broken!
* => mark all nodes connected to outputs of broken nodes as broken
* => goto 1
* d. Mark current node as ready
*
* 2. Goto 1
*/
private enum NodeState
{
Ready,
Busy,
Error
}
/// <summary>
/// Searches for loops in a network.
/// A loop is a connection sequence that starts and ends at the same node.
/// </summary>
/// <param name="network">the network to search for loops.</param>
/// <returns>an enumeration of connections involved in loops</returns>
public static IEnumerable<ConnectionViewModel> FindLoops(NetworkViewModel network)
{
Stack<NodeViewModel> nodesToCheck = new Stack<NodeViewModel>(network.Nodes.Items);
Dictionary<NodeViewModel, NodeState> nodeStates = new Dictionary<NodeViewModel, NodeState>(nodesToCheck.Count);
while (nodesToCheck.Count > 0)
{
NodeViewModel currentNode = nodesToCheck.Peek();
NodeState state;
if (!nodeStates.TryGetValue(currentNode, out state))
{
state = NodeState.Ready;
}
if (state == NodeState.Error)
{
nodesToCheck.Pop();
continue;
}
ConnectionViewModel recursiveConnection = FindLoops(nodeStates, currentNode);
if (recursiveConnection != null)
{
yield return recursiveConnection;
}
nodesToCheck.Pop();
}
}
private static ConnectionViewModel FindLoops(Dictionary<NodeViewModel, NodeState> nodeStates, NodeViewModel node)
{
nodeStates[node] = NodeState.Busy;
//Get the nodes connected to the inputs of node and check their state
//If they are Ready, check them recursively.
//If they are Busy, we found recursion.
//If they are Error, the node was already found to be part of a loop and so we ignore it.
List<ConnectionViewModel> nodesToCheck = new List<ConnectionViewModel>();
foreach (NodeInputViewModel input in node.Inputs.Items)
{
foreach (ConnectionViewModel con in input.Connections.Items)
{
NodeViewModel connectedNode = con.Output.Parent;
if (!nodeStates.TryGetValue(connectedNode, out var connectedNodeState))
{
connectedNodeState = NodeState.Ready;
}
if (connectedNodeState == NodeState.Ready)
{
nodesToCheck.Add(con);
}
else if (connectedNodeState == NodeState.Busy)
{
//Found recursion!
List<NodeViewModel> keys = new List<NodeViewModel>(nodeStates.Keys);
foreach (NodeViewModel cur in keys)
{
if (nodeStates[cur] == NodeState.Busy)
{
nodeStates[cur] = NodeState.Error;
}
}
return con;
}
else if (connectedNodeState == NodeState.Error)
{
//connected node is already marked with error state, no further action required
}
}
}
foreach (ConnectionViewModel con in nodesToCheck)
{
NodeViewModel currentNode = con.Output.Parent;
ConnectionViewModel result = FindLoops(nodeStates, currentNode);
if (result != null)
{
return result;
}
}
nodeStates[node] = NodeState.Ready;
return null;
}
/// <summary>
/// Returns the nodes connected to the starting node, then the nodes connected to those nodes, ... and so on.
/// If the subgraph that contains the starting nodes has a loop, then this function will keep producing the values in the loop.
/// A call to FindLoops is recommended before using this function
/// </summary>
/// <param name="startingNode">The node from which to branch out</param>
/// <param name="includeInputs">Include nodes connected through node inputs?</param>
/// <param name="includeOutputs">Include nodes connected through node outputs?</param>
/// <param name="includeSelf">Include the starting node? (will be first)</param>
/// <returns>An enumeration of the nodes connected to the starting node.</returns>
public static IEnumerable<NodeViewModel> GetConnectedNodesTunneling(NodeViewModel startingNode, bool includeInputs = true, bool includeOutputs = false, bool includeSelf = false)
{
if (includeSelf)
{
yield return startingNode;
}
if (includeInputs)
{
IEnumerable<NodeViewModel> inputNodes = startingNode.Inputs.Items.SelectMany(i => i.Connections.Items).Select(c => c.Output.Parent);
foreach (NodeViewModel nodeVM in inputNodes)
{
foreach (NodeViewModel subNodeVM in GetConnectedNodesTunneling(nodeVM, includeInputs, includeOutputs, true))
{
if (subNodeVM != startingNode)
{
yield return subNodeVM;
}
}
}
}
if (includeOutputs)
{
IEnumerable<NodeViewModel> outputNodes = startingNode.Outputs.Items.SelectMany(i => i.Connections.Items).Select(c => c.Input.Parent);
foreach (NodeViewModel nodeVM in outputNodes)
{
foreach (NodeViewModel subNodeVM in GetConnectedNodesTunneling(nodeVM, includeInputs, includeOutputs, true))
{
if (subNodeVM != startingNode)
{
yield return subNodeVM;
}
}
}
}
}
/// <summary>
/// Similar to GetConnectedNodesTunneling, but returns the outermost nodes first.
/// If the subgraph that contains the starting nodes has a loop, then this function will never return.
/// A call to FindLoops is recommended before using this function
/// </summary>
public static IEnumerable<NodeViewModel> GetConnectedNodesBubbling(NodeViewModel startingNode, bool includeInputs = true, bool includeOutputs = false, bool includeSelf = false)
{
return GetConnectedNodesTunneling(startingNode, includeInputs, includeOutputs, includeSelf).Reverse();
}
/// <summary>
/// Returns the starting nodes in the network.
/// Starting nodes are nodes that do not have inputs connected to an output.
/// </summary>
/// <param name="network">The network to find starting nodes in</param>
/// <returns>An enumerable of starting nodes</returns>
public static IEnumerable<NodeViewModel> FindStartingNodes(NetworkViewModel network)
{
return FindStartingNodes(network.Nodes.Items);
}
/// <summary>
/// Returns the starting nodes in the node group.
/// Starting nodes are nodes that do not have inputs connected to an output of a node in the group.
/// </summary>
public static IEnumerable<NodeViewModel> FindStartingNodes(IEnumerable<NodeViewModel> nodeGroup)
{
Queue<NodeViewModel> todo = new Queue<NodeViewModel>(nodeGroup);
HashSet<NodeViewModel> nodes = new HashSet<NodeViewModel>(todo);
while (todo.Count > 0)
{
NodeViewModel cur = todo.Dequeue();
bool hasInputConnection = false;
foreach (NodeInputViewModel input in cur.Inputs.Items)
{
if (input.Connections.Items.Any(c => nodes.Contains(c.Output.Parent)))
{
hasInputConnection = true;
break;
}
}
if (!hasInputConnection)
{
yield return cur;
}
}
}
/// <summary>
/// Takes the provided set of nodes and returns the nodes are connected to the source node, directly or indirectly.
/// This method uses breadth-first search and keeps track of visited nodes, so it can handle networks with loops.
/// </summary>
/// <param name="sourceNode">The node from which the search for connected nodes starts</param>
/// <param name="nodes">
/// The nodes to look for when searching.
/// If this set contains the sourcenode, the first item returned will be the source node.
/// </param>
/// <returns>An enumeration of connected nodes</returns>
public static IEnumerable<NodeViewModel> FindConnectedNodes(NodeViewModel sourceNode, IEnumerable<NodeViewModel> nodes)
{
HashSet<NodeViewModel> nodesSet = new HashSet<NodeViewModel>(nodes);
HashSet<NodeViewModel> visitedNodes = new HashSet<NodeViewModel>();
Queue<NodeViewModel> nodeQueue = new Queue<NodeViewModel>();
nodeQueue.Enqueue(sourceNode);
while (nodeQueue.Count > 0)
{
NodeViewModel node = nodeQueue.Dequeue();
if (nodesSet.Remove(node))
{
yield return node;
if (nodesSet.Count == 0)
{
yield break;
}
}
foreach (NodeInputViewModel input in node.Inputs.Items)
{
foreach (NodeViewModel connectedNode in input.Connections.Items.Select(c => c.Output.Parent))
{
if (visitedNodes.Add(connectedNode))
{
nodeQueue.Enqueue(connectedNode);
}
}
}
foreach (NodeOutputViewModel output in node.Outputs.Items)
{
foreach (NodeViewModel connectedNode in output.Connections.Items.Select(c => c.Input.Parent))
{
if (visitedNodes.Add(connectedNode))
{
nodeQueue.Enqueue(connectedNode);
}
}
}
}
}
/// <summary>
/// Takes the provided set of nodes and groups these nodes in sets that are connected, directly or indirectly.
/// Because this method uses FindConnectedNodes, it is capable of handling networks with loops.
/// </summary>
/// <param name="nodes">the nodes to group into sets</param>
public static IEnumerable<IEnumerable<NodeViewModel>> FindSubGraphs(IEnumerable<NodeViewModel> nodes)
{
HashSet<NodeViewModel> nodesSet = new HashSet<NodeViewModel>(nodes);
while (nodesSet.Count > 0)
{
NodeViewModel curNode = nodesSet.First();
List<NodeViewModel> subGraphMembers = new List<NodeViewModel>(FindConnectedNodes(curNode, nodesSet));
foreach (NodeViewModel subGraphMember in subGraphMembers)
{
nodesSet.Remove(subGraphMember);
}
yield return subGraphMembers;
}
}
/// <summary>
/// Returns true if the given set of nodes form continuous subgraphs.
/// The given set of nodes is split into subgraphs based on the connections between the nodes.
/// If for each subgraph it is true that all nodes of the subgraph are in the provided set, then true is returned.
/// Otherwise false is returned.
/// Because this method uses FindSubGraphs, it is capable of handling networks with loops.
/// </summary>
public static bool IsContinuousSubGraphSet(HashSet<NodeViewModel> nodesInSubGraphSet)
{
return FindSubGraphs(FindStartingNodes(nodesInSubGraphSet))
.All(subGraph => IsContinuousSubGroup(nodesInSubGraphSet, subGraph));
}
public static bool IsContinuousSubGraphSet(IEnumerable<NodeViewModel> nodesInSubGraphSet)
=> IsContinuousSubGraphSet(new HashSet<NodeViewModel>(nodesInSubGraphSet));
private static bool IsContinuousSubGroup(HashSet<NodeViewModel> groupNodesSet, IEnumerable<NodeViewModel> subGraphStartingNodes)
{
Queue<NodeViewModel> queue = new Queue<NodeViewModel>(subGraphStartingNodes);
HashSet<NodeViewModel> visitedNodes = new HashSet<NodeViewModel>(queue);
//Transitions from inside to outside to inside the group are not allowed in a continuous group.
//Since we start from the starting nodes of the current subgroup, which are inside,
//we only need to check for a transitions from outside to inside.
while (queue.Count > 0)
{
NodeViewModel cur = queue.Dequeue();
foreach (NodeOutputViewModel output in cur.Outputs.Items)
{
foreach (ConnectionViewModel con in output.Connections.Items)
{
NodeViewModel connectedNode = con.Input.Parent;
if (groupNodesSet.Contains(connectedNode) && !groupNodesSet.Contains(cur))
{
//Found transision from outside to inside
return false;
}
if (!visitedNodes.Add(connectedNode))
{
continue;
}
queue.Enqueue(connectedNode);
}
}
}
return true;
}
}
}

View File

@@ -0,0 +1,39 @@
<UserControl x:Class="NodeNetwork.Toolkit.Group.AddEndpointDropPanel.AddEndpointDropPanelView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" x:Name="Self">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</UserControl.Resources>
<Grid Width="Auto" Height="40"
Visibility="{Binding IsDropZoneVisible, Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Grid.Background).(SolidColorBrush.Color)" To="#44FFFFFF" Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Grid.Background).(SolidColorBrush.Color)" To="Transparent" Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Rectangle Stroke="#fff" StrokeThickness="2" StrokeDashArray="4 4" SnapsToDevicePixels="True"/>
<TextBlock Text="{Binding DropHintText, ElementName=Self}" VerticalAlignment="Center" TextAlignment="Center" FontSize="14" Margin="15,5,15,5"/>
</Grid>
</UserControl>

View File

@@ -0,0 +1,54 @@
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Controls;
using ReactiveUI;
namespace NodeNetwork.Toolkit.Group.AddEndpointDropPanel
{
public partial class AddEndpointDropPanelView : IViewFor<AddEndpointDropPanelViewModel>
{
#region ViewModel
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(nameof(ViewModel),
typeof(AddEndpointDropPanelViewModel), typeof(AddEndpointDropPanelView), new PropertyMetadata(null));
public AddEndpointDropPanelViewModel ViewModel
{
get => (AddEndpointDropPanelViewModel)GetValue(ViewModelProperty);
set => SetValue(ViewModelProperty, value);
}
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (AddEndpointDropPanelViewModel)value;
}
#endregion
#region DropHintText
public static readonly DependencyProperty DropHintTextProperty = DependencyProperty.Register(nameof(DropHintText),
typeof(string), typeof(AddEndpointDropPanelView), new PropertyMetadata(null));
public string DropHintText
{
get => (string)GetValue(DropHintTextProperty);
set => SetValue(DropHintTextProperty, value);
}
#endregion
public AddEndpointDropPanelView()
{
InitializeComponent();
DropHintText = "Drop here to create new entry";
this.WhenActivated(d =>
{
this.Events().MouseLeftButtonUp
.Select(_ => Unit.Default)
.InvokeCommand(this, v => v.ViewModel.AddEndpointFromPendingConnection)
.DisposeWith(d);
});
}
}
}

View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reactive;
using System.Reactive.Linq;
using System.Text;
using DynamicData;
using NodeNetwork.ViewModels;
using ReactiveUI;
namespace NodeNetwork.Toolkit.Group.AddEndpointDropPanel
{
public class AddEndpointDropPanelViewModel : ReactiveObject
{
static AddEndpointDropPanelViewModel()
{
NNViewRegistrar.AddRegistration(() => new AddEndpointDropPanelView(), typeof(IViewFor<AddEndpointDropPanelViewModel>));
}
/// <summary>
/// Take the pending connection from the super- or subnetwork, whichever is non-null,
/// and add endpoints to NodeGroupIOBinding that match this connection.
/// </summary>
public ReactiveCommand<Unit, Unit> AddEndpointFromPendingConnection { get; }
#region IsDropZoneVisible
public bool IsDropZoneVisible => _isDropZoneVisible.Value;
private readonly ObservableAsPropertyHelper<bool> _isDropZoneVisible;
#endregion
#region NodeGroupIOBinding
public NodeGroupIOBinding NodeGroupIOBinding
{
get => _nodeGroupIoBinding;
set => this.RaiseAndSetIfChanged(ref _nodeGroupIoBinding, value);
}
private NodeGroupIOBinding _nodeGroupIoBinding;
#endregion
private readonly bool isOnSubnetEntrance;
private readonly bool isOnSubnetExit;
public AddEndpointDropPanelViewModel(bool isOnSubnetEntrance = false, bool isOnSubnetExit = false)
{
this.isOnSubnetEntrance = isOnSubnetEntrance;
this.isOnSubnetExit = isOnSubnetExit;
bool isOnSubnet = isOnSubnetEntrance || isOnSubnetExit;
AddEndpointFromPendingConnection = ReactiveCommand.Create(() =>
{
var network = isOnSubnet ? NodeGroupIOBinding.SubNetwork : NodeGroupIOBinding.SuperNetwork;
var pendingConn = network.PendingConnection;
NodeInputViewModel input = null;
NodeOutputViewModel output = null;
if (!CanCreateEndpointFromPendingConnection(pendingConn))
{
return;
}
if (pendingConn.Input != null)
{
input = pendingConn.Input;
if (isOnSubnet)
{
output = NodeGroupIOBinding.AddNewSubnetInlet(pendingConn.Input);
}
else
{
output = NodeGroupIOBinding.AddNewGroupNodeOutput(pendingConn.Input);
}
}
else if (pendingConn.Output != null)
{
if (isOnSubnet)
{
input = NodeGroupIOBinding.AddNewSubnetOutlet(pendingConn.Output);
}
else
{
input = NodeGroupIOBinding.AddNewGroupNodeInput(pendingConn.Output);
}
output = pendingConn.Output;
}
network.Connections.Add(network.ConnectionFactory(input, output));
});
if (isOnSubnet)
{
this.WhenAnyValue(vm => vm.NodeGroupIOBinding.SubNetwork.PendingConnection)
.Select(CanCreateEndpointFromPendingConnection)
.ToProperty(this, vm => vm.IsDropZoneVisible, out _isDropZoneVisible);
}
else
{
this.WhenAnyValue(vm => vm.NodeGroupIOBinding.SuperNetwork.PendingConnection)
.Select(CanCreateEndpointFromPendingConnection)
.ToProperty(this, vm => vm.IsDropZoneVisible, out _isDropZoneVisible);
}
}
private bool CanCreateEndpointFromPendingConnection(PendingConnectionViewModel conn)
{
if (conn == null)
{
return false;
}
var sourceNode = conn.Input != null ? conn.Input.Parent : conn.Output.Parent;
return sourceNode != NodeGroupIOBinding.GroupNode
&& !(isOnSubnetEntrance && sourceNode == NodeGroupIOBinding.EntranceNode)
&& !(isOnSubnetExit && sourceNode == NodeGroupIOBinding.ExitNode);
}
}
}

View File

@@ -0,0 +1,91 @@
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit.Group
{
/// <summary>
/// Facilitates connections between nodes outside and inside a group.
/// This is performed by having inputs on the group node (in the supernet) that map to outputs on (mostly) the EntranceNode in the subnet.
/// Likewise, outputs of the group node map to inputs on (mostly) the ExitNode in the subnet.
/// </summary>
public abstract class NodeGroupIOBinding
{
/// <summary>
/// Node in the parent network that represents the group.
/// </summary>
public NodeViewModel GroupNode { get; }
/// <summary>
/// Inlet node in the subnet.
/// Although this generally contains only outputs, this may contain inputs if their orientation is flipped.
/// </summary>
public NodeViewModel EntranceNode { get; }
/// <summary>
/// Outlet node in the subnet.
/// Although this generally contains only outputs, this may contain inputs if their orientation is flipped.
/// </summary>
public NodeViewModel ExitNode { get; }
/// <summary>
/// Parent network that contains the GroupNode.
/// </summary>
public NetworkViewModel SuperNetwork => GroupNode.Parent;
/// <summary>
/// Child network, contained in SuperNetwork, that contains the group member nodes (like the EntranceNode and ExitNode).
/// </summary>
public NetworkViewModel SubNetwork => ExitNode.Parent;
public NodeGroupIOBinding(NodeViewModel groupNode, NodeViewModel entranceNode, NodeViewModel exitNode)
{
GroupNode = groupNode;
EntranceNode = entranceNode;
ExitNode = exitNode;
}
/// <summary>
/// Given the output in the subnet, return the corresponding input on the groupnode in the supernet.
/// </summary>
public abstract NodeInputViewModel GetGroupNodeInput(NodeOutputViewModel subnetInlet);
/// <summary>
/// Given the input on the group node in the supernet, return the corresponding output in the subnet.
/// </summary>
public abstract NodeOutputViewModel GetSubnetInlet(NodeInputViewModel entranceInput);
/// <summary>
/// Given the output on the group node in the supernet, return the corresponding input in the subnet.
/// </summary>
public abstract NodeInputViewModel GetSubnetOutlet(NodeOutputViewModel groupNodeOutput);
/// <summary>
/// Given the input in the subnet, return the corresponding output on the groupnode in the supernet.
/// </summary>
public abstract NodeOutputViewModel GetGroupNodeOutput(NodeInputViewModel subnetOutlet);
/// <summary>
/// Create and add a new input to the group node, along with a corresponding output in the subnet (e.g. on the entrance node).
/// </summary>
/// <param name="candidateOutput">Output viewmodel that should match the new input on the group node.</param>
/// <returns></returns>
public abstract NodeInputViewModel AddNewGroupNodeInput(NodeOutputViewModel candidateOutput);
/// <summary>
/// Create and add a new input to the group node, along with a corresponding output in the subnet (e.g. on the entrance node).
/// </summary>
/// <param name="candidateInput">Input viewmodel that should match the new output that is added to the subnet.</param>
public abstract NodeOutputViewModel AddNewSubnetInlet(NodeInputViewModel candidateInput);
/// <summary>
/// Create and add a new output to the group node, along with a corresponding input in the subnet (e.g. on the exit node).
/// </summary>
/// <param name="candidateInput">Input viewmodel that should match the new output on the group node.</param>
public abstract NodeOutputViewModel AddNewGroupNodeOutput(NodeInputViewModel candidateInput);
/// <summary>
/// Create and add a new output to the group node, along with a corresponding input in the subnet (e.g. on the exit node).
/// </summary>
/// <param name="candidateOutput">Output viewmodel that should match the new input that is added to the subnet.</param>
public abstract NodeInputViewModel AddNewSubnetOutlet(NodeOutputViewModel candidateOutput);
}
}

View File

@@ -0,0 +1,269 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using DynamicData;
using DynamicData.Alias;
using NodeNetwork.Utilities;
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit.Group
{
/// <summary>
/// Used to provide nesting of networks by grouping nodes.
/// </summary>
public class NodeGrouper
{
/// <summary>
/// Constructs a new node that represents a group of nodes.
/// The parameter is the subnetwork (constructed with SubNetworkFactory) that contains the group member nodes.
/// </summary>
public Func<NetworkViewModel, NodeViewModel> GroupNodeFactory { get; set; } = subnet => new NodeViewModel();
/// <summary>
/// Constructs a viewmodel for the subnetwork that will contain the group member nodes.
/// </summary>
public Func<NetworkViewModel, NetworkViewModel> SubNetworkFactory { get; set; } = parentNet => new NetworkViewModel();
/// <summary>
/// Constructs the node in the subnet that provides access to (mostly) inputs to the group
/// </summary>
public Func<NodeViewModel> EntranceNodeFactory { get; set; } = () => new NodeViewModel();
/// <summary>
/// Constructs the node in the subnet that provides access to (mostly) outputs of the group
/// </summary>
public Func<NodeViewModel> ExitNodeFactory { get; set; } = () => new NodeViewModel();
/// <summary>
/// Constructs a NodeGroupIOBinding from a group, entrance and exit node.
/// </summary>
public Func<NodeViewModel, NodeViewModel, NodeViewModel, NodeGroupIOBinding> IOBindingFactory { get; set; }
private bool CheckPropertiesValid() =>
GroupNodeFactory != null && SubNetworkFactory != null && EntranceNodeFactory != null && ExitNodeFactory != null && IOBindingFactory != null;
/// <summary>
/// Move the specified set of nodes to a new subnetwork, create a new group node that contains this subnet,
/// restore inter- and intra-network connections.
/// </summary>
/// <param name="network">The parent network</param>
/// <param name="nodesToGroup">The nodes to group</param>
/// <returns>Returns the NodeGroupIOBinding that was constructed for this group using the IOBindingFactory.</returns>
public NodeGroupIOBinding MergeIntoGroup(NetworkViewModel network, IEnumerable<NodeViewModel> nodesToGroup)
{
if (!CheckPropertiesValid())
{
throw new InvalidOperationException("All properties must be set before usage");
}
else if (network == null)
{
throw new ArgumentNullException(nameof(network));
}
else if (nodesToGroup == null)
{
throw new ArgumentNullException(nameof(nodesToGroup));
}
var groupNodesSet = nodesToGroup is HashSet<NodeViewModel> set
? set
: new HashSet<NodeViewModel>(nodesToGroup);
// Check if nodesToGroup can be combined into a single group
if (groupNodesSet.Count == 0)//[FT] allowed for now || !GraphAlgorithms.IsContinuousSubGraphSet(groupNodesSet))
{
return null;
}
// Create new empty group
var subnet = SubNetworkFactory(network);
var groupNode = GroupNodeFactory(subnet);
network.Nodes.Add(groupNode);
var groupEntranceNode = EntranceNodeFactory();
var groupExitNode = ExitNodeFactory();
subnet.Nodes.AddRange(new []{groupEntranceNode, groupExitNode});
// Map from input on a group member node to group node input
var groupNodeInputs = new Dictionary<NodeInputViewModel, NodeInputViewModel>();
// Map from output on a group member node to group node output
var groupNodeOutputs = new Dictionary<NodeOutputViewModel, NodeOutputViewModel>();
// Move the new nodes to appropriate positions
groupNode.Position = new Point(
groupNodesSet.Average(n => n.Position.X),
groupNodesSet.Average(n => n.Position.Y)
);
double yCoord = groupNodesSet.Average(n => n.Position.Y);
groupEntranceNode.Position = new Point(
groupNodesSet.Min(n => n.Position.X) - 100,
yCoord
);
groupExitNode.Position = new Point(
groupNodesSet.Max(n => n.Position.X) + 100,
yCoord
);
// Setup binding between entrance/exit inputs and outputs
var ioBinding = IOBindingFactory(groupNode, groupEntranceNode, groupExitNode);
// Calculate set of connections to replace
var subnetConnections = new List<ConnectionViewModel>();
var borderInputConnections = new List<ConnectionViewModel>();
var borderOutputConnections = new List<ConnectionViewModel>();
foreach (var con in network.Connections.Items)
{
bool inputIsInSubnet = groupNodesSet.Contains(con.Input.Parent);
bool outputIsInSubnet = groupNodesSet.Contains(con.Output.Parent);
if (inputIsInSubnet && outputIsInSubnet)
{
subnetConnections.Add(con);
}
else if (inputIsInSubnet)
{
borderInputConnections.Add(con);
}
else if (outputIsInSubnet)
{
borderOutputConnections.Add(con);
}
}
// Construct inputs/outputs into/out of the group
foreach (var borderInCon in borderInputConnections)
{
if (!groupNodeInputs.ContainsKey(borderInCon.Input))
{
groupNodeInputs[borderInCon.Input] = ioBinding.AddNewGroupNodeInput(borderInCon.Output);
}
}
foreach (var borderOutCon in borderOutputConnections)
{
if (!groupNodeOutputs.ContainsKey(borderOutCon.Output))
{
groupNodeOutputs[borderOutCon.Output] = ioBinding.AddNewGroupNodeOutput(borderOutCon.Input);
}
}
// Transfer nodes and inner connections to subnet
network.Connections.Edit(l =>
{
l.RemoveMany(subnetConnections);
l.RemoveMany(borderInputConnections);
l.RemoveMany(borderOutputConnections);
});
network.Nodes.RemoveMany(groupNodesSet);
subnet.Nodes.AddRange(groupNodesSet);
subnet.Connections.AddRange(subnetConnections.Select(con => subnet.ConnectionFactory(con.Input, con.Output)));
// Restore connections in/out of group
network.Connections.AddRange(Enumerable.Concat(
borderInputConnections.Select(con => network.ConnectionFactory(groupNodeInputs[con.Input], con.Output)),
borderOutputConnections.Select(con => network.ConnectionFactory(con.Input, groupNodeOutputs[con.Output]))
));
subnet.Connections.AddRange(Enumerable.Concat(
borderInputConnections.Select(con => subnet.ConnectionFactory(con.Input, ioBinding.GetSubnetInlet(groupNodeInputs[con.Input]))),
borderOutputConnections.Select(con => subnet.ConnectionFactory(ioBinding.GetSubnetOutlet(groupNodeOutputs[con.Output]), con.Output))
));
return ioBinding;
}
/// <summary>
/// Reverses the grouping performed by MergeIntoGroup.
/// Group members get moved back into the parent network and the group node is removed.
/// </summary>
/// <param name="nodeGroupInfo">The NodeGroupIOBinding of the group to dissolve.</param>
public void Ungroup(NodeGroupIOBinding nodeGroupInfo)
{
if (!CheckPropertiesValid())
{
throw new InvalidOperationException("All properties must be set before usage");
}
else if (nodeGroupInfo == null)
{
throw new ArgumentNullException(nameof(nodeGroupInfo));
}
var supernet = nodeGroupInfo.SuperNetwork;
var subnet = nodeGroupInfo.SubNetwork;
// Calculate set of subnet connections to replace
var borderInputConnections = new List<Tuple<NodeOutputViewModel, NodeInputViewModel[]>>();
var borderOutputConnections = new List<Tuple<NodeInputViewModel, NodeOutputViewModel[]>>();
var subnetConnections = new List<ConnectionViewModel>();
foreach (var conn in subnet.Connections.Items)
{
if (conn.Input.Parent == nodeGroupInfo.EntranceNode || conn.Input.Parent == nodeGroupInfo.ExitNode)
{
var inputs = nodeGroupInfo.GetGroupNodeOutput(conn.Input).Connections.Items.Select(c => c.Input).ToArray();
if (inputs.Length > 0)
{
borderInputConnections.Add(Tuple.Create(conn.Output, inputs));
}
}
else if (conn.Output.Parent == nodeGroupInfo.EntranceNode || conn.Output.Parent == nodeGroupInfo.ExitNode)
{
var outputs = nodeGroupInfo.GetGroupNodeInput(conn.Output).Connections.Items.Select(c => c.Output).ToArray();
if (outputs.Length > 0)
{
borderOutputConnections.Add(Tuple.Create(conn.Input, outputs));
}
}
else
{
subnetConnections.Add(conn);
}
}
// Calculate set of nodes to move
var groupMemberNodes = subnet.Nodes.Items.Where(node => node != nodeGroupInfo.EntranceNode && node != nodeGroupInfo.ExitNode).ToArray();
// Calculate center of nodes
var minX = groupMemberNodes.Min(n => n.Position.X);
var minY = groupMemberNodes.Min(n => n.Position.Y);
var maxX = groupMemberNodes.Max(n => n.Position.X);
var maxY = groupMemberNodes.Max(n => n.Position.Y);
var center = new Vector(minX + (maxX - minX)/2, minY + (maxY - minY)/2);
// Remove connections and nodes from subnet
subnet.Connections.Clear();
subnet.Nodes.Clear();
// Remove groupnode and connections from supernet
var groupNodePos = new Vector(nodeGroupInfo.GroupNode.Position.X, nodeGroupInfo.GroupNode.Position.Y);
supernet.Nodes.Remove(nodeGroupInfo.GroupNode);
// Add nodes to supernet and move them to correct position
supernet.Nodes.AddRange(groupMemberNodes);
foreach (var node in groupMemberNodes)
{
node.Position = node.Position - center + groupNodePos;
}
// Add connections to supernet
supernet.Connections.AddRange(subnetConnections);
foreach (var connTuple in borderInputConnections)
{
var output = connTuple.Item1;
var inputs = connTuple.Item2;
var connections = inputs.Select(input => supernet.ConnectionFactory(input, output));
supernet.Connections.AddRange(connections);
}
foreach (var connTuple in borderOutputConnections)
{
var outputs = connTuple.Item2;
var input = connTuple.Item1;
var connections = outputs.Select(output => supernet.ConnectionFactory(input, output));
supernet.Connections.AddRange(connections);
}
}
}
}

View File

@@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using DynamicData;
using NodeNetwork.Toolkit.ValueNode;
using NodeNetwork.ViewModels;
using ReactiveUI;
namespace NodeNetwork.Toolkit.Group
{
/// <summary>
/// Basic reference implementation of NodeGroupIOBinding for ValueInputViewModels and ValueOutputViewModels.
/// </summary>
public class ValueNodeGroupIOBinding : NodeGroupIOBinding
{
private readonly IDictionary<NodeOutputViewModel, NodeInputViewModel> _outputInputMapping = new Dictionary<NodeOutputViewModel, NodeInputViewModel>();
public ValueNodeGroupIOBinding(NodeViewModel groupNode, NodeViewModel entranceNode, NodeViewModel exitNode)
: base(groupNode, entranceNode, exitNode)
{
// For each input on the group node, create an output in the subnet
groupNode.Inputs.Connect()
.Filter(input => input.PortPosition == PortPosition.Left)
.Transform(i =>
{
// Dynamic is applied here so that late binding is used to find the most specific
// CreateCompatibleOutput variant for this specific input.
NodeOutputViewModel result = CreateCompatibleOutput((dynamic)i);
BindOutputToInput((dynamic)result, (dynamic)i);
return result;
}).PopulateInto(entranceNode.Outputs);
groupNode.Inputs.Connect()
.Filter(input => input.PortPosition == PortPosition.Right)
.Transform(i =>
{
NodeOutputViewModel result = CreateCompatibleOutput((dynamic) i);
BindOutputToInput((dynamic) result, (dynamic) i);
return result;
}).PopulateInto(exitNode.Outputs);
groupNode.Inputs.Connect().OnItemRemoved(input =>
_outputInputMapping.Remove(
_outputInputMapping.First(kvp => kvp.Value == input)
)
);
// For each output on the group node, create an input in the subnet
groupNode.Outputs.Connect()
.Filter(input => input.PortPosition == PortPosition.Right)
.Transform(o =>
{
NodeInputViewModel result = CreateCompatibleInput((dynamic)o);
BindOutputToInput((dynamic)o, (dynamic)result);
return result;
}).PopulateInto(exitNode.Inputs);
groupNode.Outputs.Connect()
.Filter(input => input.PortPosition == PortPosition.Left)
.Transform(o =>
{
NodeInputViewModel result = CreateCompatibleInput((dynamic)o);
BindOutputToInput((dynamic)o, (dynamic)result);
return result;
}).PopulateInto(entranceNode.Inputs);
groupNode.Outputs.Connect().OnItemRemoved(output => _outputInputMapping.Remove(output));
}
protected virtual void BindEndpointProperties(NodeOutputViewModel output, NodeInputViewModel input)
{
input.WhenAnyValue(vm => vm.Name).BindTo(output, vm => vm.Name);
output.WhenAnyValue(vm => vm.Name).BindTo(input, vm => vm.Name);
input.WhenAnyValue(vm => vm.SortIndex).BindTo(output, vm => vm.SortIndex);
output.WhenAnyValue(vm => vm.SortIndex).BindTo(input, vm => vm.SortIndex);
input.WhenAnyValue(vm => vm.Icon).BindTo(output, vm => vm.Icon);
output.WhenAnyValue(vm => vm.Icon).BindTo(input, vm => vm.Icon);
}
protected virtual void BindOutputToInput<T>(ValueNodeOutputViewModel<T> output, ValueNodeInputViewModel<T> input)
{
BindEndpointProperties(output, input);
output.Value = input.ValueChanged;
_outputInputMapping.Add(output, input);
}
protected virtual void BindOutputToInput<T>(ValueNodeOutputViewModel<IObservableList<T>> output, ValueListNodeInputViewModel<T> input)
{
BindEndpointProperties(output, input);
output.Value = Observable.Return(input.Values);
_outputInputMapping.Add(output, input);
}
#region Endpoint Create
public virtual ValueNodeOutputViewModel<T> CreateCompatibleOutput<T>(ValueNodeInputViewModel<T> input)
{
return new ValueNodeOutputViewModel<T>()
{
Name = input.Name,
Icon = input.Icon
};
}
public virtual ValueNodeOutputViewModel<IObservableList<T>> CreateCompatibleOutput<T>(ValueListNodeInputViewModel<T> input)
{
return new ValueNodeOutputViewModel<IObservableList<T>>();
}
public virtual ValueNodeInputViewModel<T> CreateCompatibleInput<T>(ValueNodeOutputViewModel<T> output)
{
return new ValueNodeInputViewModel<T>()
{
Name = output.Name,
Icon = output.Icon
};
}
public virtual ValueListNodeInputViewModel<T> CreateCompatibleInput<T>(ValueNodeOutputViewModel<IObservableList<T>> output)
{
return new ValueListNodeInputViewModel<T>()
{
Name = output.Name,
Icon = output.Icon
};
}
#endregion
#region Endpoint Add
public override NodeInputViewModel AddNewGroupNodeInput(NodeOutputViewModel candidateOutput)
{
NodeInputViewModel input = CreateCompatibleInput((dynamic)candidateOutput);
input.Name = candidateOutput.Name;
GroupNode.Inputs.Add(input);
// Append to bottom of list
input.SortIndex = GroupNode.Inputs.Items.Select(i => i.SortIndex).DefaultIfEmpty(-1).Max() + 1;
return input;
}
public override NodeOutputViewModel AddNewSubnetInlet(NodeInputViewModel candidateInput)
{
NodeInputViewModel input = AddNewGroupNodeInput(CreateCompatibleOutput((dynamic)candidateInput));
return GetSubnetInlet(input);
}
public override NodeInputViewModel AddNewSubnetOutlet(NodeOutputViewModel candidateOutput)
{
NodeOutputViewModel output = AddNewGroupNodeOutput(CreateCompatibleInput((dynamic)candidateOutput));
return GetSubnetOutlet(output);
}
public override NodeOutputViewModel AddNewGroupNodeOutput(NodeInputViewModel candidateInput)
{
NodeOutputViewModel output = CreateCompatibleOutput((dynamic)candidateInput);
output.Name = candidateInput.Name;
GroupNode.Outputs.Add(output);
// Append to bottom of list
output.SortIndex = GroupNode.Outputs.Items.Select(o => o.SortIndex).DefaultIfEmpty(-1).Max() + 1;
return output;
}
#endregion
#region Endpoint Getters
public override NodeInputViewModel GetGroupNodeInput(NodeOutputViewModel entranceOutput)
{
return _outputInputMapping[entranceOutput];
}
public override NodeOutputViewModel GetSubnetInlet(NodeInputViewModel entranceInput)
{
return _outputInputMapping.Single(p => p.Value == entranceInput).Key;
}
public override NodeInputViewModel GetSubnetOutlet(NodeOutputViewModel exitOutput)
{
return _outputInputMapping[exitOutput];
}
public override NodeOutputViewModel GetGroupNodeOutput(NodeInputViewModel exitInput)
{
return _outputInputMapping.Single(p => p.Value == exitInput).Key;
}
#endregion
/// <summary>
/// Remove an endpoint, which can be from group node, entrance node or exit node.
/// Also removes the corresponding endpoint in the other network.
/// </summary>
/// <param name="endpoint">Input or output to be removed.</param>
public virtual void DeleteEndpoint(Endpoint endpoint)
{
// Because the subnet entrance and exit are derived from the groupnode,
// endpoints should be deleted from the groupnode only.
bool isOnGroupNode = GroupNode == endpoint.Parent;
if (endpoint is NodeInputViewModel input)
{
if (isOnGroupNode)
{
GroupNode.Inputs.Remove(input);
}
else
{
var groupOutput = GetGroupNodeOutput(input);
GroupNode.Outputs.Remove(groupOutput);
}
}
else if(endpoint is NodeOutputViewModel output)
{
if (isOnGroupNode)
{
GroupNode.Outputs.Remove(output);
}
else
{
var groupInput = GetGroupNodeInput(output);
GroupNode.Inputs.Remove(groupInput);
}
}
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit.Layout.ForceDirected
{
public class Configuration
{
/// <summary>
/// The network whose nodes are to be repositioned.
/// </summary>
public NetworkViewModel Network { get; set; }
/// <summary>
/// A time modifier that is used to speed up, or slow down, time during the simulation.
/// A greater time modifier speeds up the physics simulation, at the cost of accuracy and stability.
/// </summary>
public float TimeModifier { get; set; } = 3.5f;
/// <summary>
/// Number of updates per iteration.
/// Increasing this number increases the accuracy of the physics simulation at the cost of performance.
/// </summary>
public int UpdatesPerIteration { get; set; } = 1;
/// <summary>
/// How strongly should nodes push eachother away?
/// A greater NodeRepulsionForce increases the distance between nodes.
/// </summary>
public float NodeRepulsionForce { get; set; } = 100;
/// <summary>
/// A function that maps each connection onto the equilibrium distance of its corresponding spring.
/// A greater equilibrium distance increases the distance between the two connected endpoints.
/// </summary>
public Func<ConnectionViewModel, double> EquilibriumDistance { get; set; } = conn => 100;
/// <summary>
/// A function that maps each connection onto the springiness/stiffness constant of its corresponding spring.
/// (c.f. Hooke's law)
/// </summary>
public Func<ConnectionViewModel, double> SpringConstant { get; set; } = conn => 1;
/// <summary>
/// A function that maps each connection onto the strength of its row force.
/// Since inputs/outputs are on the left/right of a node, networks tend to be layed out horizontally.
/// The row force is added onto the endpoints of the connection to make the nodes end up in a more horizontal layout.
/// </summary>
public Func<ConnectionViewModel, double> RowForce { get; set; } = conn => 100;
/// <summary>
/// A function that maps each node onto its mass in the physics simulation.
/// Greater mass makes the node harder to move.
/// </summary>
public Func<NodeViewModel, float> NodeMass { get; set; } = node => 10;
/// <summary>
/// The friction coefficient is used to control friction forces in the simulation.
/// Greater friction makes the simulation converge faster, as it slows nodes down when
/// they are swinging around. If the friction is too high, the nodes will stop moving before
/// they reach their optimal position or might not even move at all.
/// </summary>
public Func<NodeViewModel, float> FrictionCoefficient { get; set; } = node => 2.5f;
/// <summary>
/// A predicate function that specifies whether or not a node is fixed.
/// Fixed nodes do not get moved in the simulation.
/// </summary>
public Func<NodeViewModel, bool> IsFixedNode { get; set; } = node => false;
}
}

View File

@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit.Layout.ForceDirected
{
internal class Engine
{
internal void ApplyRandomShift(NetworkViewModel network)
{
Random random = new Random();
foreach (var node in network.Nodes.Items)
{
node.Position = node.Position + new Vector(random.NextDouble(), random.NextDouble());
}
}
internal void Update(int deltaTMillis, IState state, Configuration config)
{
// Calculate forces
int nodeCount = config.Network.Nodes.Count;
IList<(NodeViewModel, Vector)> nodeForces = new List<(NodeViewModel, Vector)>(nodeCount);
foreach (var node in config.Network.Nodes.Items)
{
if (!config.IsFixedNode(node))
{
nodeForces.Add((node, CalculateNodeForce(node, state, config)));
}
}
// Apply forces
foreach (var (node, force) in nodeForces)
{
Vector speed = state.GetNodeSpeed(node);
Vector pos = state.GetNodePosition(node);
double deltaT = deltaTMillis / 1000.0;
state.SetNodePosition(node, pos + ((speed * deltaT) + (force * deltaT * deltaT / 2)));
state.SetNodeSpeed(node, speed + ((force / config.NodeMass(node)) * deltaT));
}
}
private Vector CalculateNodeForce(NodeViewModel node, IState state, Configuration config)
{
Vector force = new Vector();
// Calculate total force on node from endpoints
if (node.Inputs.Count > 0 || node.Outputs.Count > 0)
{
force += node.Inputs.Items.Cast<Endpoint>().Concat(node.Outputs.Items)
.Select(e => CalculateEndpointForce(e, state, config))
.Aggregate((v1, v2) => v1 + v2);
}
// Apply node repulsion force so nodes don't overlap
var nodeCenter = state.GetNodePosition(node) + (new Vector(node.Size.Width, node.Size.Height) / 2.0);
foreach (var otherNode in config.Network.Nodes.Items)
{
if (node == otherNode)
{
continue;
}
var otherNodeCenter = state.GetNodePosition(otherNode) + (new Vector(otherNode.Size.Width, otherNode.Size.Height) / 2.0);
var thisToOther = otherNodeCenter - nodeCenter;
var dist = thisToOther.Length;
thisToOther.Normalize();
var repulsionX = thisToOther.X * (-1 * ((node.Size.Width + otherNode.Size.Width) / 2) / dist);
var repulsionY = thisToOther.Y * (-1 * ((node.Size.Height + otherNode.Size.Height) / 2) / dist);
force += new Vector(repulsionX, repulsionY) * config.NodeRepulsionForce;
}
// Apply friction to make the movement converge to a stable state.
float gravity = 9.8f;
float normalForce = gravity * config.NodeMass(node);
float kineticFriction = normalForce * config.FrictionCoefficient(node);
Vector frictionVector = new Vector();
var nodeSpeed = state.GetNodeSpeed(node);
if (nodeSpeed.Length > 0)
{
frictionVector = new Vector(nodeSpeed.X, nodeSpeed.Y);
frictionVector.Normalize();
frictionVector *= -1.0 * kineticFriction;
}
force += frictionVector;
return force;
}
private Vector CalculateEndpointForce(Endpoint endpoint, IState state, Configuration config)
{
var pos = state.GetEndpointPosition(endpoint);
Vector force = new Vector();
foreach (var conn in endpoint.Connections.Items)
{
var otherSide = conn.Input == endpoint ? (Endpoint)conn.Output : conn.Input;
var otherSidePos = state.GetEndpointPosition(otherSide);
var dist = (otherSidePos - pos).Length;
var angle = Math.Acos((otherSidePos.X - pos.X) / dist);
if (otherSidePos.Y < pos.Y)
{
angle *= -1.0;
}
// Put a spring between connected endpoints.
var hookForce = (dist - config.EquilibriumDistance(conn)) * config.SpringConstant(conn);
force += new Vector(Math.Cos(angle), Math.Sin(angle)) * hookForce;
// Try to 'straighten' out the graph horizontally.
var isLeftSide = endpoint.PortPosition == PortPosition.Left;
var rowForce = (isLeftSide ? 1 : -1) * config.RowForce(conn);
force.X += rowForce;
}
return force;
}
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit.Layout.ForceDirected
{
/// <summary>
/// Reposition the nodes in a network using a physics-based approach.
/// The nodes are interpreted as point masses, and the connections are represented
/// by springs. This system, along with a few additional forces such as friction and a
/// horizontal force, is then simulated to calculate the new position of the nodes.
/// </summary>
public class ForceDirectedLayouter
{
/// <summary>
/// Layout the nodes in the network.
/// </summary>
/// <param name="config">The configuration to use.</param>
/// <param name="maxIterations">The maximum amount of iterations after which the physics simulation ends.</param>
public void Layout(Configuration config, int maxIterations)
{
var engine = new Engine();
var state = new BufferedState();
// Move each node so no two nodes have the exact same position.
engine.ApplyRandomShift(config.Network);
int deltaT = (int)Math.Ceiling(10.0 / (double)config.UpdatesPerIteration);
for (int i = 0; i < maxIterations * config.UpdatesPerIteration; i++)
{
engine.Update(deltaT, state, config);
}
foreach (var newNodePosition in state.NodePositions)
{
newNodePosition.Key.Position = new Point(newNodePosition.Value.X, newNodePosition.Value.Y);
}
}
/// <summary>
/// Layout the nodes in the network, updating the user interface at each iteration.
/// This method, contrary to Layout(), lets users see the simulation as it happens.
/// The cancellation token should be used to end the simulation.
/// </summary>
/// <param name="config">The configuration to use.</param>
/// <param name="token">A cancellation token to end the layout process.</param>
/// <returns>The async task</returns>
public async Task LayoutAsync(Configuration config, CancellationToken token)
{
var engine = new Engine();
var state = new LiveState();
// Move each node so no two nodes have the exact same position.
engine.ApplyRandomShift(config.Network);
DateTime start = DateTime.Now;
TimeSpan t = TimeSpan.Zero;
do
{
// Current real time
var newT = DateTime.Now - start;
var deltaT = newT - t;
// Current modified time
//int virtT = (int)(t.Milliseconds * Settings.TimeModifier);
int virtDeltaT = (int)(deltaT.Milliseconds * config.TimeModifier);
int virtDeltaTPerUpdate = virtDeltaT / config.UpdatesPerIteration;
for (int i = 0; i < config.UpdatesPerIteration; i++)
{
// Modified time in this update step
engine.Update(virtDeltaTPerUpdate, state, config);
}
t = newT;
await Task.Delay(14, token);
} while (!token.IsCancellationRequested);
}
}
}

View File

@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit.Layout.ForceDirected
{
internal interface IState
{
Vector GetNodePosition(NodeViewModel node);
void SetNodePosition(NodeViewModel node, Vector pos);
Vector GetEndpointPosition(Endpoint endpoint);
Vector GetNodeSpeed(NodeViewModel node);
void SetNodeSpeed(NodeViewModel node, Vector speed);
}
internal class BufferedState : IState
{
private readonly Dictionary<NodeViewModel, Vector> _nodePositions = new Dictionary<NodeViewModel, Vector>();
private readonly Dictionary<Endpoint, Vector> _endpointRelativePositions = new Dictionary<Endpoint, Vector>();
public IEnumerable<KeyValuePair<NodeViewModel, Vector>> NodePositions => _nodePositions;
private readonly Dictionary<NodeViewModel, Vector> _nodeSpeeds = new Dictionary<NodeViewModel, Vector>();
public Vector GetNodePosition(NodeViewModel node)
{
if (!_nodePositions.TryGetValue(node, out Vector result))
{
result = new Vector(node.Position.X, node.Position.Y);
}
return result;
}
public void SetNodePosition(NodeViewModel node, Vector pos)
{
_nodePositions[node] = pos;
}
public Vector GetEndpointPosition(Endpoint endpoint)
{
if (!_endpointRelativePositions.TryGetValue(endpoint, out Vector result))
{
result = new Vector(endpoint.Port.CenterPoint.X, endpoint.Port.CenterPoint.Y) - GetNodePosition(endpoint.Parent);
_endpointRelativePositions[endpoint] = result;
}
return result + GetNodePosition(endpoint.Parent);
}
public Vector GetNodeSpeed(NodeViewModel node)
{
if (!_nodeSpeeds.TryGetValue(node, out Vector result))
{
result = new Vector(0, 0);
}
return result;
}
public void SetNodeSpeed(NodeViewModel node, Vector speed)
{
_nodeSpeeds[node] = speed;
}
}
internal class LiveState : IState
{
private readonly Dictionary<NodeViewModel, Vector> _nodeSpeeds = new Dictionary<NodeViewModel, Vector>();
public Vector GetNodePosition(NodeViewModel node)
{
return new Vector(node.Position.X, node.Position.Y);
}
public void SetNodePosition(NodeViewModel node, Vector pos)
{
node.Position = new Point(pos.X, pos.Y);
}
public Vector GetEndpointPosition(Endpoint endpoint)
{
return new Vector(endpoint.Port.CenterPoint.X, endpoint.Port.CenterPoint.Y);
}
public Vector GetNodeSpeed(NodeViewModel node)
{
if (!_nodeSpeeds.TryGetValue(node, out Vector result))
{
result = new Vector(0, 0);
}
return result;
}
public void SetNodeSpeed(NodeViewModel node, Vector speed)
{
_nodeSpeeds[node] = speed;
}
}
}

View File

@@ -0,0 +1,107 @@
<UserControl x:Class="NodeNetwork.Toolkit.NodeList.NodeListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:NodeNetwork.Views.Controls;assembly=NodeNetwork"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="320"
Background="{DynamicResource BackgroundColor}"
x:Name="self">
<UserControl.Resources>
<DataTemplate x:Key="tilesTemplate">
<Grid>
<controls:ViewModelViewHostNoAnimations VerticalAlignment="Top" Margin="0, 5, 0, 5" ViewModel="{Binding}" KeyboardNavigation.TabNavigation="None">
<controls:ViewModelViewHostNoAnimations.LayoutTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
</controls:ViewModelViewHostNoAnimations.LayoutTransform>
</controls:ViewModelViewHostNoAnimations>
<Grid Background="#01000000" MouseMove="OnNodeMouseMove" Cursor="Hand"/>
<!-- Overlay absorbs mouse events -->
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="tilesItemsPanelTemplate">
<WrapPanel />
</ItemsPanelTemplate>
<ControlTemplate x:Key="tilesItemsControlTemplate">
<ItemsPresenter HorizontalAlignment="Stretch"/>
</ControlTemplate>
<DataTemplate x:Key="listTemplate">
<Grid HorizontalAlignment="Stretch" Margin="0, 0, 0, 0" MouseMove="OnNodeMouseMove">
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="{Binding ListEntryBackgroundBrush, ElementName=self}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding ListEntryBackgroundMouseOverBrush, ElementName=self}"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Margin="10,5,5,5"><Run Text="{Binding Name}"/></TextBlock>
<Viewbox Stretch="Uniform" Width="10" Height="20" HorizontalAlignment="Right" Margin="5" Cursor="SizeAll">
<Canvas Width="12.5" Height="30" Background="#01ffffff">
<Rectangle Canvas.Left="0" Canvas.Top="0" Width="4" Height="4" Fill="{Binding ListEntryHandleBrush, ElementName=self}" StrokeThickness="0" />
<Rectangle Canvas.Left="7.5" Canvas.Top="0" Width="4" Height="4" Fill="{Binding ListEntryHandleBrush, ElementName=self}" StrokeThickness="0" />
<Rectangle Canvas.Left="0" Canvas.Top="7.5" Width="4" Height="4" Fill="{Binding ListEntryHandleBrush, ElementName=self}" StrokeThickness="0" />
<Rectangle Canvas.Left="7.5" Canvas.Top="7.5" Width="4" Height="4" Fill="{Binding ListEntryHandleBrush, ElementName=self}" StrokeThickness="0" />
<Rectangle Canvas.Left="0" Canvas.Top="15" Width="4" Height="4" Fill="{Binding ListEntryHandleBrush, ElementName=self}" StrokeThickness="0" />
<Rectangle Canvas.Left="7.5" Canvas.Top="15" Width="4" Height="4" Fill="{Binding ListEntryHandleBrush, ElementName=self}" StrokeThickness="0" />
<Rectangle Canvas.Left="0" Canvas.Top="22.5" Width="4" Height="4" Fill="{Binding ListEntryHandleBrush, ElementName=self}" StrokeThickness="0" />
<Rectangle Canvas.Left="7.5" Canvas.Top="22.5" Width="4" Height="4" Fill="{Binding ListEntryHandleBrush, ElementName=self}" StrokeThickness="0" />
</Canvas>
</Viewbox>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="listItemsPanelTemplate">
<StackPanel HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
<ControlTemplate x:Key="listItemsControlTemplate">
<ItemsPresenter HorizontalAlignment="Stretch"/>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid Row="0">
<TextBlock x:Name="titleLabel" Margin="10, 0, 0, 0" Padding="0, 10, 0, 10" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="18" FontFamily="Segoe UI Semilight" Text="Test"/>
<ComboBox x:Name="viewComboBox" Margin="0,0,10,0" VerticalAlignment="Center" HorizontalAlignment="Right" Width="65" Height="20" />
</Grid>
<Grid Row="1" x:Name="searchBoxGrid" Margin="25,7,25,0" MaxWidth="300" VerticalAlignment="Top">
<TextBox x:Name="searchBox" TextWrapping="Wrap"/>
<TextBlock Margin="5, 0, 0, 0" x:Name="emptySearchBoxMessage" Text="Search..." IsHitTestVisible="False" Foreground="LightGray"/>
</Grid>
<Grid Row="2" Margin="10,10,10,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<ScrollViewer>
<ItemsControl x:Name="elementsList" IsTabStop="False">
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander Header="{Binding Name}" IsExpanded="True">
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
</ScrollViewer>
<TextBlock x:Name="emptyMessage" Text="No matching nodes found" HorizontalAlignment="Center" VerticalAlignment="Top"/>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,166 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using DynamicData;
using NodeNetwork.Utilities;
using NodeNetwork.ViewModels;
using ReactiveUI;
namespace NodeNetwork.Toolkit.NodeList
{
public partial class NodeListView : IViewFor<NodeListViewModel>
{
#region ViewModel
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(nameof(ViewModel),
typeof(NodeListViewModel), typeof(NodeListView), new PropertyMetadata(null));
public NodeListViewModel ViewModel
{
get => (NodeListViewModel)GetValue(ViewModelProperty);
set => SetValue(ViewModelProperty, value);
}
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (NodeListViewModel)value;
}
#endregion
#region Show/Hide properties
public static readonly DependencyProperty ShowSearchProperty =
DependencyProperty.Register(nameof(ShowSearch), typeof(bool), typeof(NodeListView), new PropertyMetadata(true));
public static readonly DependencyProperty ShowDisplayModeSelectorProperty =
DependencyProperty.Register(nameof(ShowDisplayModeSelector), typeof(bool), typeof(NodeListView), new PropertyMetadata(true));
public static readonly DependencyProperty ShowTitleProperty =
DependencyProperty.Register(nameof(ShowTitle), typeof(bool), typeof(NodeListView), new PropertyMetadata(true));
public bool ShowSearch
{
get { return (bool)GetValue(ShowSearchProperty); }
set { SetValue(ShowSearchProperty, value); }
}
public bool ShowDisplayModeSelector
{
get { return (bool)GetValue(ShowDisplayModeSelectorProperty); }
set { SetValue(ShowDisplayModeSelectorProperty, value); }
}
public bool ShowTitle
{
get { return (bool)GetValue(ShowTitleProperty); }
set { SetValue(ShowTitleProperty, value); }
}
#endregion
#region Colors
public static readonly DependencyProperty ListEntryBackgroundBrushProperty =
DependencyProperty.Register(nameof(ListEntryBackgroundBrush), typeof(Brush), typeof(NodeListView), new PropertyMetadata(new SolidColorBrush(Colors.White)));
public Brush ListEntryBackgroundBrush
{
get { return (Brush)GetValue(ListEntryBackgroundBrushProperty); }
set { SetValue(ListEntryBackgroundBrushProperty, value); }
}
public static readonly DependencyProperty ListEntryBackgroundMouseOverBrushProperty =
DependencyProperty.Register(nameof(ListEntryBackgroundMouseOverBrush), typeof(Brush), typeof(NodeListView), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(0xf7, 0xf7, 0xf7))));
public Brush ListEntryBackgroundMouseOverBrush
{
get { return (Brush)GetValue(ListEntryBackgroundMouseOverBrushProperty); }
set { SetValue(ListEntryBackgroundMouseOverBrushProperty, value); }
}
public static readonly DependencyProperty ListEntryHandleBrushProperty =
DependencyProperty.Register(nameof(ListEntryHandleBrush), typeof(Brush), typeof(NodeListView), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(0x99, 0x99, 0x99))));
public Brush ListEntryHandleBrush
{
get { return (Brush)GetValue(ListEntryHandleBrushProperty); }
set { SetValue(ListEntryHandleBrushProperty, value); }
}
#endregion
public CollectionViewSource CVS { get; } = new CollectionViewSource();
public NodeListView()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(this)) { return; }
viewComboBox.ItemsSource = Enum.GetValues(typeof(NodeListViewModel.DisplayMode)).Cast<NodeListViewModel.DisplayMode>();
this.WhenActivated(d =>
{
this.Bind(ViewModel, vm => vm.Display, v => v.viewComboBox.SelectedItem).DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.Display, v => v.elementsList.ItemTemplate,
displayMode => displayMode == NodeListViewModel.DisplayMode.Tiles
? Resources["tilesTemplate"]
: Resources["listTemplate"])
.DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.Display, v => v.elementsList.ItemsPanel,
displayMode => displayMode == NodeListViewModel.DisplayMode.Tiles
? Resources["tilesItemsPanelTemplate"]
: Resources["listItemsPanelTemplate"])
.DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.Display, v => v.elementsList.Template,
displayMode => displayMode == NodeListViewModel.DisplayMode.Tiles
? Resources["tilesItemsControlTemplate"]
: Resources["listItemsControlTemplate"])
.DisposeWith(d);
this.Bind(ViewModel, vm => vm.SearchQuery, v => v.searchBox.Text).DisposeWith(d);
this.WhenAnyValue(v => v.ViewModel.VisibleNodes).Switch().Bind(out var bindableList).Subscribe().DisposeWith(d);
CVS.Source = bindableList;
elementsList.ItemsSource = CVS.View;
this.WhenAnyObservable(v => v.ViewModel.VisibleNodes.CountChanged)
.Select(count => count == 0)
.BindTo(this, v => v.emptyMessage.Visibility).DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.Title, v => v.titleLabel.Text).DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.EmptyLabel, v => v.emptyMessage.Text).DisposeWith(d);
this.WhenAnyValue(v => v.searchBox.IsFocused, v => v.searchBox.Text)
.Select(t => !t.Item1 && string.IsNullOrWhiteSpace(t.Item2))
.BindTo(this, v => v.emptySearchBoxMessage.Visibility)
.DisposeWith(d);
this.WhenAnyValue(v => v.ShowSearch)
.BindTo(this, v => v.searchBoxGrid.Visibility).DisposeWith(d);
this.WhenAnyValue(v => v.ShowDisplayModeSelector)
.BindTo(this, v => v.viewComboBox.Visibility).DisposeWith(d);
this.WhenAnyValue(v => v.ShowTitle)
.BindTo(this, v => v.titleLabel.Visibility).DisposeWith(d);
});
}
private void OnNodeMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
NodeViewModel nodeVM = ((FrameworkElement)sender).DataContext as NodeViewModel;
if (nodeVM == null)
{
return;
}
var nodeFactory = ViewModel.NodeTemplates.Items.First(t => t.Instance == nodeVM).Factory;
NodeViewModel newNodeVM = nodeFactory();
DragDrop.DoDragDrop(this, new DataObject("nodeVM", newNodeVM), DragDropEffects.Copy);
}
}
}
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using DynamicData;
using NodeNetwork.ViewModels;
using ReactiveUI;
namespace NodeNetwork.Toolkit.NodeList
{
/// <summary>
/// A viewmodel for a UI List component that contains NodeViewModels
/// and can be used to let the user add new nodes to a network.
/// </summary>
public class NodeListViewModel : ReactiveObject
{
static NodeListViewModel()
{
NNViewRegistrar.AddRegistration(() => new NodeListView(), typeof(IViewFor<NodeListViewModel>));
}
/// <summary>
/// The formatting mode of the list.
/// </summary>
public enum DisplayMode
{
/// <summary>
/// The nodes are displayed graphically in a grid.
/// </summary>
Tiles,
/// <summary>
/// The node names are displayed as text in a list.
/// </summary>
List
}
#region Title
/// <summary>
/// The string that is displayed at the top of the list
/// </summary>
public string Title
{
get => _title;
set => this.RaiseAndSetIfChanged(ref _title, value);
}
private string _title;
#endregion
#region EmptyLabel
/// <summary>
/// The string that is displayed when VisibleNodes is empty.
/// </summary>
public string EmptyLabel
{
get => _emptyLabel;
set => this.RaiseAndSetIfChanged(ref _emptyLabel, value);
}
private string _emptyLabel = "";
#endregion
#region DisplayMode
/// <summary>
/// The way the list of available nodes is formatted.
/// </summary>
public DisplayMode Display
{
get => _display;
set => this.RaiseAndSetIfChanged(ref _display, value);
}
private DisplayMode _display;
#endregion
#region NodeTemplates
/// <summary>
/// List of all the available nodes in the list.
/// </summary>
public ISourceList<NodeTemplate> NodeTemplates { get; } = new SourceList<NodeTemplate>();
#endregion
#region VisibleNodes
/// <summary>
/// List of nodes that are actually visible in the list.
/// This list is based on Nodes and SearchQuery.
/// </summary>
public IObservableList<NodeViewModel> VisibleNodes { get; }
#endregion
#region SearchQuery
/// <summary>
/// The current search string that is used to filter Nodes into VisibleNodes.
/// </summary>
public string SearchQuery
{
get => _searchQuery;
set => this.RaiseAndSetIfChanged(ref _searchQuery, value);
}
private string _searchQuery = "";
#endregion
public NodeListViewModel()
{
Title = "Add node";
EmptyLabel = "No matching nodes found.";
Display = DisplayMode.Tiles;
var onQueryChanged = this.WhenAnyValue(vm => vm.SearchQuery)
.Throttle(TimeSpan.FromMilliseconds(200), RxApp.MainThreadScheduler)
.Publish();
onQueryChanged.Connect();
VisibleNodes = NodeTemplates.Connect()
.AutoRefreshOnObservable(_ => onQueryChanged)
.Transform(t => t.Instance)
.AutoRefresh(node => node.Name)
.Filter(n => (n.Name ?? "").ToUpper().Contains(SearchQuery?.ToUpper() ?? ""))
.AsObservableList();
}
/// <summary>
/// Adds a new node type to the list.
/// Every time a node is added to a network from this list, the factory function will be called to create a new instance of the viewmodel type.
/// </summary>
/// <typeparam name="T">The subtype of NodeViewModel to add to the list.</typeparam>
/// <param name="factory">The factory function to create a new instance of T</param>
public void AddNodeType<T>(Func<T> factory) where T : NodeViewModel
{
NodeTemplates.Add(new NodeTemplate(factory));
}
}
}

View File

@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0-windows7.0;net48</TargetFrameworks>
<OutputType>Library</OutputType>
<RootNamespace>NodeNetwork.Toolkit</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWPF>true</UseWPF>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>6.0.0</Version>
<Authors>Wouter De Keersmaecker</Authors>
<PackageTags>wpf reactiveui node network editor node-editor graph</PackageTags>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<RepositoryUrl>https://www.github.com/wouterdek/nodenetwork</RepositoryUrl>
<RepositoryType>Github</RepositoryType>
<IncludeSymbols>true</IncludeSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DocumentationFile>bin\Release\NodeNetworkToolkit.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<None Include=".editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NodeNetwork\NodeNetwork.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ReactiveUI" Version="13.2.18" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Include="System.Drawing.Primitives" Version="4.3.0" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,27 @@
using System;
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit
{
/// <summary>
/// Used in systems that need an example of a type of node as well as a way to create more instances of the same type.
/// </summary>
public class NodeTemplate
{
/// <summary>
/// Factory function to create a new instance of the same type of node as Instance
/// </summary>
public Func<NodeViewModel> Factory { get; }
/// <summary>
/// Example instance of the type of node created by Factory
/// </summary>
public NodeViewModel Instance { get; }
public NodeTemplate(Func<NodeViewModel> factory)
{
Factory = factory;
Instance = factory();
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NodeNetworkToolkit")]
[assembly: AssemblyDescription("A helper library for NodeNetwork with additional, commonly used helper components")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NodeNetwork")]
[assembly: AssemblyCopyright("Copyright (c) Wouter De Keersmaecker")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("391d0670-646f-4633-9e86-e9a966f61953")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: AssemblyFileVersion("6.0.0.0")]

View File

@@ -0,0 +1,26 @@
namespace NodeNetwork.Toolkit.ValueNode
{
/// <summary>
/// Action that should be taken based on the validation result
/// </summary>
public enum ValidationAction
{
/// <summary>
/// Don't run the validation. (LatestValidation is not updated)
/// </summary>
DontValidate,
/// <summary>
/// Run the validation, but ignore the result and assume the network is valid.
/// </summary>
IgnoreValidation,
/// <summary>
/// Run the validation and if the network is invalid then wait until it is valid.
/// </summary>
WaitForValid,
/// <summary>
/// Run the validation and if the network is invalid then make default(T) the current value.
/// </summary>
PushDefaultValue
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Reactive;
using System.Reactive.Linq;
using NodeNetwork.ViewModels;
using NodeNetwork.Views;
using ReactiveUI;
namespace NodeNetwork.Toolkit.ValueNode
{
/// <summary>
/// An editor for ValueNodeInputViewModel or ValueNodeOutputViewModel.
/// For inputs, this class can provide values when no connection is present.
/// For outputs, this class can provide a way to configure the value produced by the output.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ValueEditorViewModel<T> : NodeEndpointEditorViewModel
{
static ValueEditorViewModel()
{
NNViewRegistrar.AddRegistration(() => new NodeEndpointEditorView(), typeof(IViewFor<ValueEditorViewModel<T>>));
}
#region Value
/// <summary>
/// The value currently set in the editor.
/// </summary>
public T Value
{
get => _value;
set => this.RaiseAndSetIfChanged(ref _value, value);
}
private T _value;
#endregion
#region ValueChanged
/// <summary>
/// Observable that produces an object when the value changes.
/// </summary>
public IObservable<T> ValueChanged { get; }
#endregion
public ValueEditorViewModel()
{
ValueChanged = this.WhenAnyValue(vm => vm.Value);
}
}
}

View File

@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
using DynamicData;
using DynamicData.Alias;
using DynamicData.Kernel;
using NodeNetwork.ViewModels;
using NodeNetwork.Views;
using ReactiveUI;
namespace NodeNetwork.Toolkit.ValueNode
{
/// <summary>
/// A node input that keeps a list of the latest values produced by all of the connected ValueNodeOutputViewModels.
/// This input can take multiple connections, ValueNodeInputViewModel cannot.
/// </summary>
/// <typeparam name="T">The type of object this input can receive</typeparam>
public class ValueListNodeInputViewModel<T> : NodeInputViewModel
{
static ValueListNodeInputViewModel()
{
NNViewRegistrar.AddRegistration(() => new NodeInputView(), typeof(IViewFor<ValueListNodeInputViewModel<T>>));
}
/// <summary>
/// The current values of the outputs connected to this input
/// </summary>
public IObservableList<T> Values { get; }
public ValueListNodeInputViewModel()
{
MaxConnections = Int32.MaxValue;
ConnectionValidator = pending => new ConnectionValidationResult(
pending.Output is ValueNodeOutputViewModel<T> ||
pending.Output is ValueNodeOutputViewModel<IObservableList<T>>,
null
);
var valuesFromSingles = Connections.Connect(c => c.Output is ValueNodeOutputViewModel<T>)
.Transform(c => (ValueNodeOutputViewModel<T>)c.Output)
//Note: this line used to be
//.AutoRefresh(output => output.CurrentValue)
//which ignored changes where CurrentValue didn't change.
//This caused problems when the value object isn't replaced, but one of its properties changes.
.AutoRefreshOnObservable(output => output.Value)
// Null values are not allowed, so filter before transform
.Filter(output => output.CurrentValue != null)
.Transform(output => output.CurrentValue, true)
// Any 'replace' changes that don't change the value should be refresh changes
// This prevents issues where a value is updated, but it doesn't propagate through the network
// because the connections didn't change.
.Select(changes =>
{
if (changes.TotalChanges == changes.Replaced + changes.Refreshes)
{
bool allRefresh = true;
var newChanges = new ChangeSet<T>();
foreach (var change in changes)
{
if (change.Reason == ListChangeReason.Replace)
{
if (change.Type == ChangeType.Item)
{
if (change.Item.Previous != change.Item.Current)
{
allRefresh = false;
break;
}
newChanges.Add(new Change<T>(ListChangeReason.Refresh, change.Item.Current, change.Item.Previous, change.Item.CurrentIndex, change.Item.PreviousIndex));
}
else
{
throw new Exception("Does this ever occur?");
}
}
else
{
newChanges.Add(change);
}
}
if (allRefresh) return newChanges;
}
return changes;
});
var valuesFromLists = Connections.Connect(c => c.Output is ValueNodeOutputViewModel<IObservableList<T>>)
// Grab list of values from output, using switch to handle when the list object is replaced
.Transform(c => ((ValueNodeOutputViewModel<IObservableList<T>>) c.Output).Value.Switch())
// Materialize this changeset stream into a list (needed to make sure the next step is done dynamically)
.AsObservableList()
// Take the union of all values from all lists. This is done dynamically, so adding/removing new lists works as expected.
.Or();
Values = valuesFromSingles.Or(valuesFromLists).AsObservableList();
}
}
}

View File

@@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reactive.Threading.Tasks;
using System.Threading;
using NodeNetwork.ViewModels;
using NodeNetwork.Views;
using ReactiveUI;
namespace NodeNetwork.Toolkit.ValueNode
{
/// <summary>
/// A node input that keeps track of the latest value produced by either the connected ValueNodeOutputViewModel,
/// or the ValueEditorViewModel in the Editor property.
/// </summary>
/// <typeparam name="T">The type of object this input can receive</typeparam>
public class ValueNodeInputViewModel<T> : ValueNodeInputViewModelBase
{
static ValueNodeInputViewModel()
{
NNViewRegistrar.AddRegistration(() => new NodeInputView(), typeof(IViewFor<ValueNodeInputViewModel<T>>));
}
#region Value
/// <summary>
/// The value currently associated with this input.
/// If the input is not connected, the value is taken from ValueEditorViewModel.Value in the Editor property.
/// If the input is connected, the value is taken from ValueNodeOutputViewModel.LatestValue unless the network is not traversable.
/// Note that this value may be equal to default(T) if there is an error somewhere.
/// </summary>
public T Value => _value.Value;
private readonly ObservableAsPropertyHelper<T> _value;
#endregion
#region ValueChanged
/// <summary>
/// An observable that fires when the input value changes.
/// This may be because of a connection change, editor value change, network validation change, ...
/// </summary>
public IObservable<T> ValueChanged { get; }
public override IObservable<Unit> UnitValueChanged { get; }
#endregion
/// <summary>
/// Constructs a new ValueNodeInputViewModel with the specified ValidationActions.
/// The default values are carefully chosen and should probably not be changed unless you know what you are doing.
/// </summary>
/// <param name="connectionChangedValidationAction">The validation behaviour when the connection of this input changes.</param>
/// <param name="connectedValueChangedValidationAction">The validation behaviour when the value of this input changes.</param>
public ValueNodeInputViewModel(
ValidationAction connectionChangedValidationAction = ValidationAction.PushDefaultValue,
ValidationAction connectedValueChangedValidationAction = ValidationAction.IgnoreValidation
)
{
MaxConnections = 1;
ConnectionValidator = pending => new ConnectionValidationResult(pending.Output is ValueNodeOutputViewModel<T>, null);
var connectedValues = GenerateConnectedValuesBinding(connectionChangedValidationAction, connectedValueChangedValidationAction);
var localValues = this.WhenAnyValue(vm => vm.Editor)
.Select(e =>
{
if (e == null)
{
return Observable.Return(default(T));
}
else if (!(e is ValueEditorViewModel<T>))
{
throw new Exception($"The endpoint editor is not a subclass of ValueEditorViewModel<{typeof(T).Name}>");
}
else
{
return ((ValueEditorViewModel<T>)e).ValueChanged;
}
})
.Switch();
var valueChanged = Observable.CombineLatest(connectedValues, localValues,
(connectedValue, localValue) => Connections.Count == 0 ? localValue : connectedValue
).Publish();
valueChanged.Connect();
valueChanged.ToProperty(this, vm => vm.Value, out _value);
ValueChanged = Observable
.Defer(() => Observable.Return(Value))
.Concat(valueChanged);
UnitValueChanged = ValueChanged
.Select(_ => Unit.Default)
.StartWith(Unit.Default);
}
private IObservable<T> GenerateConnectedValuesBinding(ValidationAction connectionChangedValidationAction, ValidationAction connectedValueChangedValidationAction)
{
var onConnectionChanged = this.Connections.Connect().Select(_ => Unit.Default).StartWith(Unit.Default)
.Select(_ => Connections.Count == 0 ? null : Connections.Items.First());
//On connection change
IObservable<IObservable<T>> connectionObservables;
if (connectionChangedValidationAction != ValidationAction.DontValidate)
{
//Either run network validation
IObservable<NetworkValidationResult> postValidation = onConnectionChanged
.SelectMany(con => Parent?.Parent?.UpdateValidation.Execute() ?? Observable.Return(new NetworkValidationResult(true, true, null)));
if (connectionChangedValidationAction == ValidationAction.WaitForValid)
{
//And wait until the validation is successful
postValidation = postValidation.SelectMany(validation =>
validation.NetworkIsTraversable
? Observable.Return(validation)
: Parent.Parent.Validation.FirstAsync(val => val.NetworkIsTraversable));
}
if (connectionChangedValidationAction == ValidationAction.PushDefaultValue)
{
//Or push a single default(T) if the validation fails
connectionObservables = postValidation.Select(validation =>
{
if (Connections.Count == 0)
{
return Observable.Return(default(T));
}
else if(validation.NetworkIsTraversable)
{
IObservable<T> connectedObservable =
((ValueNodeOutputViewModel<T>) Connections.Items.First().Output).Value;
if (connectedObservable == null)
{
throw new Exception($"The value observable for output '{Connections.Items.First().Output.Name}' is null.");
}
return connectedObservable;
}
else
{
return Observable.Return(default(T));
}
});
}
else
{
//Grab the values observable from the connected output
connectionObservables = postValidation
.Select(_ =>
{
if (Connections.Count == 0)
{
return Observable.Return(default(T));
}
else
{
IObservable<T> connectedObservable =
((ValueNodeOutputViewModel<T>)Connections.Items.First().Output).Value;
if (connectedObservable == null)
{
throw new Exception($"The value observable for output '{Connections.Items.First().Output.Name}' is null.");
}
return connectedObservable;
}
});
}
}
else
{
//Or just grab the values observable from the connected output
connectionObservables = onConnectionChanged.Select(con =>
{
if (con == null)
{
return Observable.Return(default(T));
}
else
{
IObservable<T> connectedObservable =
((ValueNodeOutputViewModel<T>)con.Output).Value;
if (connectedObservable == null)
{
throw new Exception($"The value observable for output '{Connections.Items.First().Output.Name}' is null.");
}
return connectedObservable;
}
});
}
IObservable<T> connectedValues = connectionObservables.SelectMany(c => c);
//On connected output value change, either just push the value as is
if (connectedValueChangedValidationAction != ValidationAction.DontValidate)
{
//Or run a network validation
IObservable<NetworkValidationResult> postValidation = connectedValues.SelectMany(v =>
Parent?.Parent?.UpdateValidation.Execute() ?? Observable.Return(new NetworkValidationResult(true, true, null)));
if (connectedValueChangedValidationAction == ValidationAction.WaitForValid)
{
//And wait until the validation is successful
postValidation = postValidation.SelectMany(validation =>
validation.IsValid
? Observable.Return(validation)
: Parent.Parent.Validation.FirstAsync(val => val.IsValid));
}
connectedValues = postValidation.Select(validation =>
{
if (Connections.Count == 0
|| connectionChangedValidationAction == ValidationAction.PushDefaultValue && !validation.NetworkIsTraversable
|| connectedValueChangedValidationAction == ValidationAction.PushDefaultValue && !validation.IsValid)
{
//Push default(T) if the network isn't valid
return default;
}
//Or just ignore the validation and push the value as is
return ((ValueNodeOutputViewModel<T>) this.Connections.Items.First().Output).CurrentValue;
});
}
return connectedValues;
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Reactive;
using NodeNetwork.ViewModels;
namespace NodeNetwork.Toolkit.ValueNode
{
public abstract class ValueNodeInputViewModelBase : NodeInputViewModel
{
#region ValueChanged
/// <summary>
/// An observable that fires when the input value changes.
/// This may be because of a connection change, editor value change, network validation change, ...
/// </summary>
public abstract IObservable<Unit> UnitValueChanged { get; }
#endregion
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Reactive.Concurrency;
using NodeNetwork.ViewModels;
using NodeNetwork.Views;
using ReactiveUI;
namespace NodeNetwork.Toolkit.ValueNode
{
/// <summary>
/// A viewmodel for a node output that produces a value based on the inputs.
/// </summary>
/// <typeparam name="T">The type of object produced by this output.</typeparam>
public class ValueNodeOutputViewModel<T> : NodeOutputViewModel
{
static ValueNodeOutputViewModel()
{
NNViewRegistrar.AddRegistration(() => new NodeOutputView(), typeof(IViewFor<ValueNodeOutputViewModel<T>>));
}
#region Value
/// <summary>
/// Observable that produces the value every time it changes.
/// </summary>
public IObservable<T> Value
{
get => _value;
set => this.RaiseAndSetIfChanged(ref _value, value);
}
private IObservable<T> _value;
#endregion
#region CurrentValue
/// <summary>
/// The latest value produced by this output.
/// </summary>
public T CurrentValue => _currentValue.Value;
private readonly ObservableAsPropertyHelper<T> _currentValue;
#endregion
public ValueNodeOutputViewModel()
{
this.WhenAnyObservable(vm => vm.Value).ToProperty(this, vm => vm.CurrentValue, out _currentValue, false, Scheduler.Immediate);
}
}
}

Binary file not shown.

View File

@@ -0,0 +1,543 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v5.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v5.0": {
"NodeNetworkToolkit/6.0.0": {
"dependencies": {
"Microsoft.CSharp": "4.7.0",
"NodeNetwork": "6.0.0",
"ReactiveUI": "13.2.18",
"System.Buffers": "4.5.1",
"System.Collections.Immutable": "5.0.0",
"System.Data.DataSetExtensions": "4.5.0",
"System.Drawing.Primitives": "4.3.0",
"System.Memory": "4.5.4",
"System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
"System.Threading.Tasks.Extensions": "4.5.4",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"NodeNetworkToolkit.dll": {}
}
},
"DynamicData/7.1.1": {
"dependencies": {
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/DynamicData.dll": {
"assemblyVersion": "7.1.0.0",
"fileVersion": "7.1.1.11487"
}
}
},
"log4net/2.0.12": {
"dependencies": {
"System.Configuration.ConfigurationManager": "4.5.0"
},
"runtime": {
"lib/netstandard2.0/log4net.dll": {
"assemblyVersion": "2.0.12.0",
"fileVersion": "2.0.12.0"
}
}
},
"Microsoft.CSharp/4.7.0": {},
"Microsoft.NETCore.Platforms/2.0.0": {},
"Microsoft.NETCore.Targets/1.1.0": {},
"Pharmacist.Common/2.0.8": {
"dependencies": {
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/Pharmacist.Common.dll": {
"assemblyVersion": "2.0.0.0",
"fileVersion": "2.0.8.15338"
}
}
},
"ReactiveUI/13.2.18": {
"dependencies": {
"DynamicData": "7.1.1",
"Splat": "11.0.1",
"System.Reactive": "5.0.0",
"System.Runtime.Serialization.Primitives": "4.3.0"
},
"runtime": {
"lib/net5.0-windows7.0/ReactiveUI.dll": {
"assemblyVersion": "13.2.0.0",
"fileVersion": "13.2.18.42750"
}
}
},
"ReactiveUI.Events.WPF/13.2.18": {
"dependencies": {
"Pharmacist.Common": "2.0.8",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0-windows7.0/ReactiveUI.Events.WPF.dll": {
"assemblyVersion": "13.2.0.0",
"fileVersion": "13.2.18.42750"
}
}
},
"ReactiveUI.WPF/13.2.18": {
"dependencies": {
"ReactiveUI": "13.2.18",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0-windows7.0/ReactiveUI.Wpf.dll": {
"assemblyVersion": "13.2.0.0",
"fileVersion": "13.2.18.42750"
}
}
},
"Splat/11.0.1": {
"runtime": {
"lib/net5.0/Splat.dll": {
"assemblyVersion": "11.0.0.0",
"fileVersion": "11.0.1.61461"
}
}
},
"Splat.Drawing/11.0.1": {
"dependencies": {
"Splat": "11.0.1",
"System.Diagnostics.Contracts": "4.3.0",
"System.Drawing.Primitives": "4.3.0",
"System.Runtime.Serialization.Primitives": "4.3.0"
},
"runtime": {
"lib/net5.0-windows7.0/Splat.Drawing.dll": {
"assemblyVersion": "11.0.0.0",
"fileVersion": "11.0.1.61461"
}
}
},
"System.Buffers/4.5.1": {},
"System.Collections.Immutable/5.0.0": {},
"System.Configuration.ConfigurationManager/4.5.0": {
"dependencies": {
"System.Security.Cryptography.ProtectedData": "4.5.0",
"System.Security.Permissions": "4.5.0"
}
},
"System.Data.DataSetExtensions/4.5.0": {},
"System.Diagnostics.Contracts/4.3.0": {
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.Drawing.Primitives/4.3.0": {
"dependencies": {
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Globalization/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.IO/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Memory/4.5.4": {},
"System.Numerics.Vectors/4.5.0": {},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reflection/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Primitives/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Resources.ResourceManager/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Globalization": "4.3.0",
"System.Reflection": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.CompilerServices.Unsafe/5.0.0": {},
"System.Runtime.Extensions/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime.Serialization.Primitives/4.3.0": {
"dependencies": {
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Security.AccessControl/4.5.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"System.Security.Principal.Windows": "4.5.0"
}
},
"System.Security.Cryptography.ProtectedData/4.5.0": {},
"System.Security.Permissions/4.5.0": {
"dependencies": {
"System.Security.AccessControl": "4.5.0"
}
},
"System.Security.Principal.Windows/4.5.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0"
}
},
"System.Text.Encoding/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading.Tasks/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading.Tasks.Extensions/4.5.4": {},
"System.ValueTuple/4.5.0": {},
"NodeNetwork/6.0.0": {
"dependencies": {
"Microsoft.CSharp": "4.7.0",
"ReactiveUI": "13.2.18",
"ReactiveUI.Events.WPF": "13.2.18",
"ReactiveUI.WPF": "13.2.18",
"Splat.Drawing": "11.0.1",
"System.Buffers": "4.5.1",
"System.Collections.Immutable": "5.0.0",
"System.Data.DataSetExtensions": "4.5.0",
"System.Drawing.Primitives": "4.3.0",
"System.Memory": "4.5.4",
"System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
"System.Threading.Tasks.Extensions": "4.5.4",
"System.ValueTuple": "4.5.0",
"log4net": "2.0.12"
},
"runtime": {
"NodeNetwork.dll": {}
}
}
}
},
"libraries": {
"NodeNetworkToolkit/6.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"DynamicData/7.1.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Pc6J5bFnSxEa64PV2V67FMcLlDdpv6m+zTBKSnRN3aLon/WtWWy8kuDpHFbJlgXHtqc6Nxloj9ItuvDlvKC/8w==",
"path": "dynamicdata/7.1.1",
"hashPath": "dynamicdata.7.1.1.nupkg.sha512"
},
"log4net/2.0.12": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9P67BCftJ7KG+B7rNOM1A9KczUwyEDed6zbAddy5Cj/73xVkzi+rEAHeOgUnW5wDqy1JFlY8+oTP0m1PgJ03Tg==",
"path": "log4net/2.0.12",
"hashPath": "log4net.2.0.12.nupkg.sha512"
},
"Microsoft.CSharp/4.7.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
"path": "microsoft.csharp/4.7.0",
"hashPath": "microsoft.csharp.4.7.0.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/2.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-VdLJOCXhZaEMY7Hm2GKiULmn7IEPFE4XC5LPSfBVCUIA8YLZVh846gtfBJalsPQF2PlzdD7ecX7DZEulJ402ZQ==",
"path": "microsoft.netcore.platforms/2.0.0",
"hashPath": "microsoft.netcore.platforms.2.0.0.nupkg.sha512"
},
"Microsoft.NETCore.Targets/1.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==",
"path": "microsoft.netcore.targets/1.1.0",
"hashPath": "microsoft.netcore.targets.1.1.0.nupkg.sha512"
},
"Pharmacist.Common/2.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NNiYvv2oTd18ckJMBt8zatCBPj0KwbzbxMuxgu45m20VtqvkvR6AborbOhkhmJC70iaSv3uLvhTnFExIJGDnQA==",
"path": "pharmacist.common/2.0.8",
"hashPath": "pharmacist.common.2.0.8.nupkg.sha512"
},
"ReactiveUI/13.2.18": {
"type": "package",
"serviceable": true,
"sha512": "sha512-w457p8goRjJgbggK2whtgYO8U9SOT1JbMDyZOKceibWoZVuOGME4RfUc60/AsLVmfwlkI+9ve+xc2S696nJZuQ==",
"path": "reactiveui/13.2.18",
"hashPath": "reactiveui.13.2.18.nupkg.sha512"
},
"ReactiveUI.Events.WPF/13.2.18": {
"type": "package",
"serviceable": true,
"sha512": "sha512-m9mFgMdSWFAdlCEFOahD2bfDo+zV8BlLxOhTSVSEFbtiSC0loYHSbJDBZYu/nxTTYzjqHTN86PZ7T9NoRgfVGw==",
"path": "reactiveui.events.wpf/13.2.18",
"hashPath": "reactiveui.events.wpf.13.2.18.nupkg.sha512"
},
"ReactiveUI.WPF/13.2.18": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ALpQe9Y970v4d/RfFT/keb93POq1WEYwUq0bfvZchUiYG4j8GOcFe085x+D5bfwh2aCRz/hHNl+9fTFVnCRisw==",
"path": "reactiveui.wpf/13.2.18",
"hashPath": "reactiveui.wpf.13.2.18.nupkg.sha512"
},
"Splat/11.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-C1p+fZE+xgwKCqnf9Qsk0lrJYGiUplWpS2wp9/RR/YNHkjx7vBCRebau1Uej7ZXda71eJgZVBYzZq0/qsQOc3Q==",
"path": "splat/11.0.1",
"hashPath": "splat.11.0.1.nupkg.sha512"
},
"Splat.Drawing/11.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hSho9yLfiv2+QhWqZImg01lhZZzz/6qPP3r2AQQRRJdxIoqgcgw1VqBWYC5bT+4QzcX/hAcjtpmQXmYEg2KBZw==",
"path": "splat.drawing/11.0.1",
"hashPath": "splat.drawing.11.0.1.nupkg.sha512"
},
"System.Buffers/4.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==",
"path": "system.buffers/4.5.1",
"hashPath": "system.buffers.4.5.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Configuration.ConfigurationManager/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UIFvaFfuKhLr9u5tWMxmVoDPkFeD+Qv8gUuap4aZgVGYSYMdERck4OhLN/2gulAc0nYTEigWXSJNNWshrmxnng==",
"path": "system.configuration.configurationmanager/4.5.0",
"hashPath": "system.configuration.configurationmanager.4.5.0.nupkg.sha512"
},
"System.Data.DataSetExtensions/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-221clPs1445HkTBZPL+K9sDBdJRB8UN8rgjO3ztB0CQ26z//fmJXtlsr6whGatscsKGBrhJl5bwJuKSA8mwFOw==",
"path": "system.data.datasetextensions/4.5.0",
"hashPath": "system.data.datasetextensions.4.5.0.nupkg.sha512"
},
"System.Diagnostics.Contracts/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-eelRRbnm+OloiQvp9CXS0ixjNQldjjkHO4iIkR5XH2VIP8sUB/SIpa1TdUW6/+HDcQ+MlhP3pNa1u5SbzYuWGA==",
"path": "system.diagnostics.contracts/4.3.0",
"hashPath": "system.diagnostics.contracts.4.3.0.nupkg.sha512"
},
"System.Drawing.Primitives/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-1QU/c35gwdhvj77fkScXQQbjiVAqIL3fEYn/19NE0CV/ic5TN5PyWAft8HsrbRd4SBLEoErNCkWSzMDc0MmbRw==",
"path": "system.drawing.primitives/4.3.0",
"hashPath": "system.drawing.primitives.4.3.0.nupkg.sha512"
},
"System.Globalization/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==",
"path": "system.globalization/4.3.0",
"hashPath": "system.globalization.4.3.0.nupkg.sha512"
},
"System.IO/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
"path": "system.io/4.3.0",
"hashPath": "system.io.4.3.0.nupkg.sha512"
},
"System.Memory/4.5.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
"path": "system.memory/4.5.4",
"hashPath": "system.memory.4.5.4.nupkg.sha512"
},
"System.Numerics.Vectors/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==",
"path": "system.numerics.vectors/4.5.0",
"hashPath": "system.numerics.vectors.4.5.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.Reflection/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
"path": "system.reflection/4.3.0",
"hashPath": "system.reflection.4.3.0.nupkg.sha512"
},
"System.Reflection.Primitives/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
"path": "system.reflection.primitives/4.3.0",
"hashPath": "system.reflection.primitives.4.3.0.nupkg.sha512"
},
"System.Resources.ResourceManager/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==",
"path": "system.resources.resourcemanager/4.3.0",
"hashPath": "system.resources.resourcemanager.4.3.0.nupkg.sha512"
},
"System.Runtime/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
"path": "system.runtime/4.3.0",
"hashPath": "system.runtime.4.3.0.nupkg.sha512"
},
"System.Runtime.CompilerServices.Unsafe/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA==",
"path": "system.runtime.compilerservices.unsafe/5.0.0",
"hashPath": "system.runtime.compilerservices.unsafe.5.0.0.nupkg.sha512"
},
"System.Runtime.Extensions/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==",
"path": "system.runtime.extensions/4.3.0",
"hashPath": "system.runtime.extensions.4.3.0.nupkg.sha512"
},
"System.Runtime.Serialization.Primitives/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==",
"path": "system.runtime.serialization.primitives/4.3.0",
"hashPath": "system.runtime.serialization.primitives.4.3.0.nupkg.sha512"
},
"System.Security.AccessControl/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vW8Eoq0TMyz5vAG/6ce483x/CP83fgm4SJe5P8Tb1tZaobcvPrbMEL7rhH1DRdrYbbb6F0vq3OlzmK0Pkwks5A==",
"path": "system.security.accesscontrol/4.5.0",
"hashPath": "system.security.accesscontrol.4.5.0.nupkg.sha512"
},
"System.Security.Cryptography.ProtectedData/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wLBKzFnDCxP12VL9ANydSYhk59fC4cvOr9ypYQLPnAj48NQIhqnjdD2yhP8yEKyBJEjERWS9DisKL7rX5eU25Q==",
"path": "system.security.cryptography.protecteddata/4.5.0",
"hashPath": "system.security.cryptography.protecteddata.4.5.0.nupkg.sha512"
},
"System.Security.Permissions/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9gdyuARhUR7H+p5CjyUB/zPk7/Xut3wUSP8NJQB6iZr8L3XUXTMdoLeVAg9N4rqF8oIpE7MpdqHdDHQ7XgJe0g==",
"path": "system.security.permissions/4.5.0",
"hashPath": "system.security.permissions.4.5.0.nupkg.sha512"
},
"System.Security.Principal.Windows/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-U77HfRXlZlOeIXd//Yoj6Jnk8AXlbeisf1oq1os+hxOGVnuG+lGSfGqTwTZBoORFF6j/0q7HXIl8cqwQ9aUGqQ==",
"path": "system.security.principal.windows/4.5.0",
"hashPath": "system.security.principal.windows.4.5.0.nupkg.sha512"
},
"System.Text.Encoding/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
"path": "system.text.encoding/4.3.0",
"hashPath": "system.text.encoding.4.3.0.nupkg.sha512"
},
"System.Threading.Tasks/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
"path": "system.threading.tasks/4.3.0",
"hashPath": "system.threading.tasks.4.3.0.nupkg.sha512"
},
"System.Threading.Tasks.Extensions/4.5.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
"path": "system.threading.tasks.extensions/4.5.4",
"hashPath": "system.threading.tasks.extensions.4.5.4.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"NodeNetwork/6.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View File

@@ -0,0 +1,543 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v7.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v7.0": {
"NodeNetworkToolkit/6.0.0": {
"dependencies": {
"Microsoft.CSharp": "4.7.0",
"NodeNetwork": "6.0.0",
"ReactiveUI": "13.2.18",
"System.Buffers": "4.5.1",
"System.Collections.Immutable": "5.0.0",
"System.Data.DataSetExtensions": "4.5.0",
"System.Drawing.Primitives": "4.3.0",
"System.Memory": "4.5.4",
"System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
"System.Threading.Tasks.Extensions": "4.5.4",
"System.ValueTuple": "4.5.0"
},
"runtime": {
"NodeNetworkToolkit.dll": {}
}
},
"DynamicData/7.1.1": {
"dependencies": {
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/DynamicData.dll": {
"assemblyVersion": "7.1.0.0",
"fileVersion": "7.1.1.11487"
}
}
},
"log4net/2.0.12": {
"dependencies": {
"System.Configuration.ConfigurationManager": "4.5.0"
},
"runtime": {
"lib/netstandard2.0/log4net.dll": {
"assemblyVersion": "2.0.12.0",
"fileVersion": "2.0.12.0"
}
}
},
"Microsoft.CSharp/4.7.0": {},
"Microsoft.NETCore.Platforms/2.0.0": {},
"Microsoft.NETCore.Targets/1.1.0": {},
"Pharmacist.Common/2.0.8": {
"dependencies": {
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0/Pharmacist.Common.dll": {
"assemblyVersion": "2.0.0.0",
"fileVersion": "2.0.8.15338"
}
}
},
"ReactiveUI/13.2.18": {
"dependencies": {
"DynamicData": "7.1.1",
"Splat": "11.0.1",
"System.Reactive": "5.0.0",
"System.Runtime.Serialization.Primitives": "4.3.0"
},
"runtime": {
"lib/net5.0-windows7.0/ReactiveUI.dll": {
"assemblyVersion": "13.2.0.0",
"fileVersion": "13.2.18.42750"
}
}
},
"ReactiveUI.Events.WPF/13.2.18": {
"dependencies": {
"Pharmacist.Common": "2.0.8",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0-windows7.0/ReactiveUI.Events.WPF.dll": {
"assemblyVersion": "13.2.0.0",
"fileVersion": "13.2.18.42750"
}
}
},
"ReactiveUI.WPF/13.2.18": {
"dependencies": {
"ReactiveUI": "13.2.18",
"System.Reactive": "5.0.0"
},
"runtime": {
"lib/net5.0-windows7.0/ReactiveUI.Wpf.dll": {
"assemblyVersion": "13.2.0.0",
"fileVersion": "13.2.18.42750"
}
}
},
"Splat/11.0.1": {
"runtime": {
"lib/net5.0/Splat.dll": {
"assemblyVersion": "11.0.0.0",
"fileVersion": "11.0.1.61461"
}
}
},
"Splat.Drawing/11.0.1": {
"dependencies": {
"Splat": "11.0.1",
"System.Diagnostics.Contracts": "4.3.0",
"System.Drawing.Primitives": "4.3.0",
"System.Runtime.Serialization.Primitives": "4.3.0"
},
"runtime": {
"lib/net5.0-windows7.0/Splat.Drawing.dll": {
"assemblyVersion": "11.0.0.0",
"fileVersion": "11.0.1.61461"
}
}
},
"System.Buffers/4.5.1": {},
"System.Collections.Immutable/5.0.0": {},
"System.Configuration.ConfigurationManager/4.5.0": {
"dependencies": {
"System.Security.Cryptography.ProtectedData": "4.5.0",
"System.Security.Permissions": "4.5.0"
}
},
"System.Data.DataSetExtensions/4.5.0": {},
"System.Diagnostics.Contracts/4.3.0": {
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.Drawing.Primitives/4.3.0": {
"dependencies": {
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Globalization/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.IO/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Memory/4.5.4": {},
"System.Numerics.Vectors/4.5.0": {},
"System.Reactive/5.0.0": {
"runtime": {
"lib/net5.0/System.Reactive.dll": {
"assemblyVersion": "5.0.0.0",
"fileVersion": "5.0.0.1"
}
}
},
"System.Reflection/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Primitives/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Resources.ResourceManager/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Globalization": "4.3.0",
"System.Reflection": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.CompilerServices.Unsafe/5.0.0": {},
"System.Runtime.Extensions/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime.Serialization.Primitives/4.3.0": {
"dependencies": {
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Security.AccessControl/4.5.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"System.Security.Principal.Windows": "4.5.0"
}
},
"System.Security.Cryptography.ProtectedData/4.5.0": {},
"System.Security.Permissions/4.5.0": {
"dependencies": {
"System.Security.AccessControl": "4.5.0"
}
},
"System.Security.Principal.Windows/4.5.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0"
}
},
"System.Text.Encoding/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading.Tasks/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "2.0.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading.Tasks.Extensions/4.5.4": {},
"System.ValueTuple/4.5.0": {},
"NodeNetwork/6.0.0": {
"dependencies": {
"Microsoft.CSharp": "4.7.0",
"ReactiveUI": "13.2.18",
"ReactiveUI.Events.WPF": "13.2.18",
"ReactiveUI.WPF": "13.2.18",
"Splat.Drawing": "11.0.1",
"System.Buffers": "4.5.1",
"System.Collections.Immutable": "5.0.0",
"System.Data.DataSetExtensions": "4.5.0",
"System.Drawing.Primitives": "4.3.0",
"System.Memory": "4.5.4",
"System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
"System.Threading.Tasks.Extensions": "4.5.4",
"System.ValueTuple": "4.5.0",
"log4net": "2.0.12"
},
"runtime": {
"NodeNetwork.dll": {}
}
}
}
},
"libraries": {
"NodeNetworkToolkit/6.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"DynamicData/7.1.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Pc6J5bFnSxEa64PV2V67FMcLlDdpv6m+zTBKSnRN3aLon/WtWWy8kuDpHFbJlgXHtqc6Nxloj9ItuvDlvKC/8w==",
"path": "dynamicdata/7.1.1",
"hashPath": "dynamicdata.7.1.1.nupkg.sha512"
},
"log4net/2.0.12": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9P67BCftJ7KG+B7rNOM1A9KczUwyEDed6zbAddy5Cj/73xVkzi+rEAHeOgUnW5wDqy1JFlY8+oTP0m1PgJ03Tg==",
"path": "log4net/2.0.12",
"hashPath": "log4net.2.0.12.nupkg.sha512"
},
"Microsoft.CSharp/4.7.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
"path": "microsoft.csharp/4.7.0",
"hashPath": "microsoft.csharp.4.7.0.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/2.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-VdLJOCXhZaEMY7Hm2GKiULmn7IEPFE4XC5LPSfBVCUIA8YLZVh846gtfBJalsPQF2PlzdD7ecX7DZEulJ402ZQ==",
"path": "microsoft.netcore.platforms/2.0.0",
"hashPath": "microsoft.netcore.platforms.2.0.0.nupkg.sha512"
},
"Microsoft.NETCore.Targets/1.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==",
"path": "microsoft.netcore.targets/1.1.0",
"hashPath": "microsoft.netcore.targets.1.1.0.nupkg.sha512"
},
"Pharmacist.Common/2.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NNiYvv2oTd18ckJMBt8zatCBPj0KwbzbxMuxgu45m20VtqvkvR6AborbOhkhmJC70iaSv3uLvhTnFExIJGDnQA==",
"path": "pharmacist.common/2.0.8",
"hashPath": "pharmacist.common.2.0.8.nupkg.sha512"
},
"ReactiveUI/13.2.18": {
"type": "package",
"serviceable": true,
"sha512": "sha512-w457p8goRjJgbggK2whtgYO8U9SOT1JbMDyZOKceibWoZVuOGME4RfUc60/AsLVmfwlkI+9ve+xc2S696nJZuQ==",
"path": "reactiveui/13.2.18",
"hashPath": "reactiveui.13.2.18.nupkg.sha512"
},
"ReactiveUI.Events.WPF/13.2.18": {
"type": "package",
"serviceable": true,
"sha512": "sha512-m9mFgMdSWFAdlCEFOahD2bfDo+zV8BlLxOhTSVSEFbtiSC0loYHSbJDBZYu/nxTTYzjqHTN86PZ7T9NoRgfVGw==",
"path": "reactiveui.events.wpf/13.2.18",
"hashPath": "reactiveui.events.wpf.13.2.18.nupkg.sha512"
},
"ReactiveUI.WPF/13.2.18": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ALpQe9Y970v4d/RfFT/keb93POq1WEYwUq0bfvZchUiYG4j8GOcFe085x+D5bfwh2aCRz/hHNl+9fTFVnCRisw==",
"path": "reactiveui.wpf/13.2.18",
"hashPath": "reactiveui.wpf.13.2.18.nupkg.sha512"
},
"Splat/11.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-C1p+fZE+xgwKCqnf9Qsk0lrJYGiUplWpS2wp9/RR/YNHkjx7vBCRebau1Uej7ZXda71eJgZVBYzZq0/qsQOc3Q==",
"path": "splat/11.0.1",
"hashPath": "splat.11.0.1.nupkg.sha512"
},
"Splat.Drawing/11.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hSho9yLfiv2+QhWqZImg01lhZZzz/6qPP3r2AQQRRJdxIoqgcgw1VqBWYC5bT+4QzcX/hAcjtpmQXmYEg2KBZw==",
"path": "splat.drawing/11.0.1",
"hashPath": "splat.drawing.11.0.1.nupkg.sha512"
},
"System.Buffers/4.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==",
"path": "system.buffers/4.5.1",
"hashPath": "system.buffers.4.5.1.nupkg.sha512"
},
"System.Collections.Immutable/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==",
"path": "system.collections.immutable/5.0.0",
"hashPath": "system.collections.immutable.5.0.0.nupkg.sha512"
},
"System.Configuration.ConfigurationManager/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UIFvaFfuKhLr9u5tWMxmVoDPkFeD+Qv8gUuap4aZgVGYSYMdERck4OhLN/2gulAc0nYTEigWXSJNNWshrmxnng==",
"path": "system.configuration.configurationmanager/4.5.0",
"hashPath": "system.configuration.configurationmanager.4.5.0.nupkg.sha512"
},
"System.Data.DataSetExtensions/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-221clPs1445HkTBZPL+K9sDBdJRB8UN8rgjO3ztB0CQ26z//fmJXtlsr6whGatscsKGBrhJl5bwJuKSA8mwFOw==",
"path": "system.data.datasetextensions/4.5.0",
"hashPath": "system.data.datasetextensions.4.5.0.nupkg.sha512"
},
"System.Diagnostics.Contracts/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-eelRRbnm+OloiQvp9CXS0ixjNQldjjkHO4iIkR5XH2VIP8sUB/SIpa1TdUW6/+HDcQ+MlhP3pNa1u5SbzYuWGA==",
"path": "system.diagnostics.contracts/4.3.0",
"hashPath": "system.diagnostics.contracts.4.3.0.nupkg.sha512"
},
"System.Drawing.Primitives/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-1QU/c35gwdhvj77fkScXQQbjiVAqIL3fEYn/19NE0CV/ic5TN5PyWAft8HsrbRd4SBLEoErNCkWSzMDc0MmbRw==",
"path": "system.drawing.primitives/4.3.0",
"hashPath": "system.drawing.primitives.4.3.0.nupkg.sha512"
},
"System.Globalization/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==",
"path": "system.globalization/4.3.0",
"hashPath": "system.globalization.4.3.0.nupkg.sha512"
},
"System.IO/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
"path": "system.io/4.3.0",
"hashPath": "system.io.4.3.0.nupkg.sha512"
},
"System.Memory/4.5.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
"path": "system.memory/4.5.4",
"hashPath": "system.memory.4.5.4.nupkg.sha512"
},
"System.Numerics.Vectors/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==",
"path": "system.numerics.vectors/4.5.0",
"hashPath": "system.numerics.vectors.4.5.0.nupkg.sha512"
},
"System.Reactive/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"path": "system.reactive/5.0.0",
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
},
"System.Reflection/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
"path": "system.reflection/4.3.0",
"hashPath": "system.reflection.4.3.0.nupkg.sha512"
},
"System.Reflection.Primitives/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
"path": "system.reflection.primitives/4.3.0",
"hashPath": "system.reflection.primitives.4.3.0.nupkg.sha512"
},
"System.Resources.ResourceManager/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==",
"path": "system.resources.resourcemanager/4.3.0",
"hashPath": "system.resources.resourcemanager.4.3.0.nupkg.sha512"
},
"System.Runtime/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
"path": "system.runtime/4.3.0",
"hashPath": "system.runtime.4.3.0.nupkg.sha512"
},
"System.Runtime.CompilerServices.Unsafe/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA==",
"path": "system.runtime.compilerservices.unsafe/5.0.0",
"hashPath": "system.runtime.compilerservices.unsafe.5.0.0.nupkg.sha512"
},
"System.Runtime.Extensions/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==",
"path": "system.runtime.extensions/4.3.0",
"hashPath": "system.runtime.extensions.4.3.0.nupkg.sha512"
},
"System.Runtime.Serialization.Primitives/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==",
"path": "system.runtime.serialization.primitives/4.3.0",
"hashPath": "system.runtime.serialization.primitives.4.3.0.nupkg.sha512"
},
"System.Security.AccessControl/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vW8Eoq0TMyz5vAG/6ce483x/CP83fgm4SJe5P8Tb1tZaobcvPrbMEL7rhH1DRdrYbbb6F0vq3OlzmK0Pkwks5A==",
"path": "system.security.accesscontrol/4.5.0",
"hashPath": "system.security.accesscontrol.4.5.0.nupkg.sha512"
},
"System.Security.Cryptography.ProtectedData/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wLBKzFnDCxP12VL9ANydSYhk59fC4cvOr9ypYQLPnAj48NQIhqnjdD2yhP8yEKyBJEjERWS9DisKL7rX5eU25Q==",
"path": "system.security.cryptography.protecteddata/4.5.0",
"hashPath": "system.security.cryptography.protecteddata.4.5.0.nupkg.sha512"
},
"System.Security.Permissions/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9gdyuARhUR7H+p5CjyUB/zPk7/Xut3wUSP8NJQB6iZr8L3XUXTMdoLeVAg9N4rqF8oIpE7MpdqHdDHQ7XgJe0g==",
"path": "system.security.permissions/4.5.0",
"hashPath": "system.security.permissions.4.5.0.nupkg.sha512"
},
"System.Security.Principal.Windows/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-U77HfRXlZlOeIXd//Yoj6Jnk8AXlbeisf1oq1os+hxOGVnuG+lGSfGqTwTZBoORFF6j/0q7HXIl8cqwQ9aUGqQ==",
"path": "system.security.principal.windows/4.5.0",
"hashPath": "system.security.principal.windows.4.5.0.nupkg.sha512"
},
"System.Text.Encoding/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
"path": "system.text.encoding/4.3.0",
"hashPath": "system.text.encoding.4.3.0.nupkg.sha512"
},
"System.Threading.Tasks/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
"path": "system.threading.tasks/4.3.0",
"hashPath": "system.threading.tasks.4.3.0.nupkg.sha512"
},
"System.Threading.Tasks.Extensions/4.5.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
"path": "system.threading.tasks.extensions/4.5.4",
"hashPath": "system.threading.tasks.extensions.4.5.4.nupkg.sha512"
},
"System.ValueTuple/4.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==",
"path": "system.valuetuple/4.5.0",
"hashPath": "system.valuetuple.4.5.0.nupkg.sha512"
},
"NodeNetwork/6.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>NodeNetworkToolkit</id>
<version>6.0.0</version>
<authors>Wouter De Keersmaecker</authors>
<license type="expression">Apache-2.0</license>
<licenseUrl>https://licenses.nuget.org/Apache-2.0</licenseUrl>
<description>Package Description</description>
<tags>wpf reactiveui node network editor node-editor graph</tags>
<repository type="Github" url="https://www.github.com/wouterdek/nodenetwork" />
<dependencies>
<group targetFramework=".NETFramework4.8">
<dependency id="NodeNetwork" version="6.0.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.CSharp" version="4.7.0" exclude="Build,Analyzers" />
<dependency id="ReactiveUI" version="13.2.18" exclude="Build,Analyzers" />
<dependency id="System.Buffers" version="4.5.1" exclude="Build,Analyzers" />
<dependency id="System.Collections.Immutable" version="5.0.0" exclude="Build,Analyzers" />
<dependency id="System.Data.DataSetExtensions" version="4.5.0" exclude="Build,Analyzers" />
<dependency id="System.Drawing.Primitives" version="4.3.0" exclude="Build,Analyzers" />
<dependency id="System.Memory" version="4.5.4" exclude="Build,Analyzers" />
<dependency id="System.Numerics.Vectors" version="4.5.0" exclude="Build,Analyzers" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" exclude="Build,Analyzers" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4" exclude="Build,Analyzers" />
<dependency id="System.ValueTuple" version="4.5.0" exclude="Build,Analyzers" />
</group>
<group targetFramework="net7.0-windows7.0">
<dependency id="NodeNetwork" version="6.0.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.CSharp" version="4.7.0" exclude="Build,Analyzers" />
<dependency id="ReactiveUI" version="13.2.18" exclude="Build,Analyzers" />
<dependency id="System.Buffers" version="4.5.1" exclude="Build,Analyzers" />
<dependency id="System.Collections.Immutable" version="5.0.0" exclude="Build,Analyzers" />
<dependency id="System.Data.DataSetExtensions" version="4.5.0" exclude="Build,Analyzers" />
<dependency id="System.Drawing.Primitives" version="4.3.0" exclude="Build,Analyzers" />
<dependency id="System.Memory" version="4.5.4" exclude="Build,Analyzers" />
<dependency id="System.Numerics.Vectors" version="4.5.0" exclude="Build,Analyzers" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" exclude="Build,Analyzers" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4" exclude="Build,Analyzers" />
<dependency id="System.ValueTuple" version="4.5.0" exclude="Build,Analyzers" />
</group>
</dependencies>
<frameworkReferences>
<group targetFramework="net7.0-windows7.0">
<frameworkReference name="Microsoft.WindowsDesktop.App.WPF" />
</group>
<group targetFramework=".NETFramework4.8" />
</frameworkReferences>
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.Drawing.Primitives" targetFramework=".NETFramework4.8" />
</frameworkAssemblies>
</metadata>
<files>
<file src="E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\NodeNetworkToolkit.dll" target="lib\net48\NodeNetworkToolkit.dll" />
<file src="E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net7.0-windows7.0\NodeNetworkToolkit.dll" target="lib\net7.0-windows7.0\NodeNetworkToolkit.dll" />
</files>
</package>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>NodeNetworkToolkit</id>
<version>6.0.0</version>
<authors>Wouter De Keersmaecker</authors>
<license type="expression">Apache-2.0</license>
<licenseUrl>https://licenses.nuget.org/Apache-2.0</licenseUrl>
<description>Package Description</description>
<tags>wpf reactiveui node network editor node-editor graph</tags>
<repository type="Github" url="https://www.github.com/wouterdek/nodenetwork" />
<dependencies>
<group targetFramework=".NETFramework4.8">
<dependency id="NodeNetwork" version="6.0.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.CSharp" version="4.7.0" exclude="Build,Analyzers" />
<dependency id="ReactiveUI" version="13.2.18" exclude="Build,Analyzers" />
<dependency id="System.Buffers" version="4.5.1" exclude="Build,Analyzers" />
<dependency id="System.Collections.Immutable" version="5.0.0" exclude="Build,Analyzers" />
<dependency id="System.Data.DataSetExtensions" version="4.5.0" exclude="Build,Analyzers" />
<dependency id="System.Drawing.Primitives" version="4.3.0" exclude="Build,Analyzers" />
<dependency id="System.Memory" version="4.5.4" exclude="Build,Analyzers" />
<dependency id="System.Numerics.Vectors" version="4.5.0" exclude="Build,Analyzers" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" exclude="Build,Analyzers" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4" exclude="Build,Analyzers" />
<dependency id="System.ValueTuple" version="4.5.0" exclude="Build,Analyzers" />
</group>
<group targetFramework="net7.0-windows7.0">
<dependency id="NodeNetwork" version="6.0.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.CSharp" version="4.7.0" exclude="Build,Analyzers" />
<dependency id="ReactiveUI" version="13.2.18" exclude="Build,Analyzers" />
<dependency id="System.Buffers" version="4.5.1" exclude="Build,Analyzers" />
<dependency id="System.Collections.Immutable" version="5.0.0" exclude="Build,Analyzers" />
<dependency id="System.Data.DataSetExtensions" version="4.5.0" exclude="Build,Analyzers" />
<dependency id="System.Drawing.Primitives" version="4.3.0" exclude="Build,Analyzers" />
<dependency id="System.Memory" version="4.5.4" exclude="Build,Analyzers" />
<dependency id="System.Numerics.Vectors" version="4.5.0" exclude="Build,Analyzers" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" exclude="Build,Analyzers" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4" exclude="Build,Analyzers" />
<dependency id="System.ValueTuple" version="4.5.0" exclude="Build,Analyzers" />
</group>
</dependencies>
<frameworkReferences>
<group targetFramework="net7.0-windows7.0">
<frameworkReference name="Microsoft.WindowsDesktop.App.WPF" />
</group>
<group targetFramework=".NETFramework4.8" />
</frameworkReferences>
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.Drawing.Primitives" targetFramework=".NETFramework4.8" />
</frameworkAssemblies>
</metadata>
<files>
<file src="E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\NodeNetworkToolkit.pdb" target="lib\net48\NodeNetworkToolkit.pdb" />
<file src="E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net7.0-windows7.0\NodeNetworkToolkit.pdb" target="lib\net7.0-windows7.0\NodeNetworkToolkit.pdb" />
<file src="E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\NodeNetworkToolkit.dll" target="lib\net48\NodeNetworkToolkit.dll" />
<file src="E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net7.0-windows7.0\NodeNetworkToolkit.dll" target="lib\net7.0-windows7.0\NodeNetworkToolkit.dll" />
</files>
</package>

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]

View File

@@ -0,0 +1,89 @@
#pragma checksum "..\..\..\..\BreadcrumbBar\BreadcrumbBarView.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "8E255DB6093D94A718E821B78E34ED873EE35DC3"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace NodeNetwork.Toolkit.BreadcrumbBar {
/// <summary>
/// BreadcrumbBarView
/// </summary>
public partial class BreadcrumbBarView : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector {
#line 8 "..\..\..\..\BreadcrumbBar\BreadcrumbBarView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.ListView list;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/NodeNetworkToolkit;component/breadcrumbbar/breadcrumbbarview.xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\BreadcrumbBar\BreadcrumbBarView.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.list = ((System.Windows.Controls.ListView)(target));
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,89 @@
#pragma checksum "..\..\..\..\BreadcrumbBar\BreadcrumbBarView.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "8E255DB6093D94A718E821B78E34ED873EE35DC3"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace NodeNetwork.Toolkit.BreadcrumbBar {
/// <summary>
/// BreadcrumbBarView
/// </summary>
public partial class BreadcrumbBarView : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector {
#line 8 "..\..\..\..\BreadcrumbBar\BreadcrumbBarView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.ListView list;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/NodeNetworkToolkit;component/breadcrumbbar/breadcrumbbarview.xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\BreadcrumbBar\BreadcrumbBarView.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.list = ((System.Windows.Controls.ListView)(target));
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,135 @@
#pragma checksum "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "6AA246F30ABEA423818A4A835A95D99AA711C243"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using NodeNetwork.Toolkit.ContextMenu;
using NodeNetwork.ViewModels;
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace NodeNetwork.Toolkit.ContextMenu {
/// <summary>
/// SearchableContextMenuView
/// </summary>
public partial class SearchableContextMenuView : System.Windows.Controls.ContextMenu, System.Windows.Markup.IComponentConnector {
#line 9 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal NodeNetwork.Toolkit.ContextMenu.SearchableContextMenuView self;
#line default
#line hidden
#line 23 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.MenuItem SearchMenuItem;
#line default
#line hidden
#line 25 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBox SearchTextBox;
#line default
#line hidden
#line 28 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Data.CollectionContainer CollectionContainer;
#line default
#line hidden
#line 30 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Data.CollectionContainer ContainerBelowSearch;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/NodeNetworkToolkit;component/contextmenu/searchablecontextmenuview.xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.self = ((NodeNetwork.Toolkit.ContextMenu.SearchableContextMenuView)(target));
return;
case 2:
this.SearchMenuItem = ((System.Windows.Controls.MenuItem)(target));
return;
case 3:
this.SearchTextBox = ((System.Windows.Controls.TextBox)(target));
return;
case 4:
this.CollectionContainer = ((System.Windows.Data.CollectionContainer)(target));
return;
case 5:
this.ContainerBelowSearch = ((System.Windows.Data.CollectionContainer)(target));
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,135 @@
#pragma checksum "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "6AA246F30ABEA423818A4A835A95D99AA711C243"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using NodeNetwork.Toolkit.ContextMenu;
using NodeNetwork.ViewModels;
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace NodeNetwork.Toolkit.ContextMenu {
/// <summary>
/// SearchableContextMenuView
/// </summary>
public partial class SearchableContextMenuView : System.Windows.Controls.ContextMenu, System.Windows.Markup.IComponentConnector {
#line 9 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal NodeNetwork.Toolkit.ContextMenu.SearchableContextMenuView self;
#line default
#line hidden
#line 23 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.MenuItem SearchMenuItem;
#line default
#line hidden
#line 25 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBox SearchTextBox;
#line default
#line hidden
#line 28 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Data.CollectionContainer CollectionContainer;
#line default
#line hidden
#line 30 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Data.CollectionContainer ContainerBelowSearch;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/NodeNetworkToolkit;component/contextmenu/searchablecontextmenuview.xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\ContextMenu\SearchableContextMenuView.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.self = ((NodeNetwork.Toolkit.ContextMenu.SearchableContextMenuView)(target));
return;
case 2:
this.SearchMenuItem = ((System.Windows.Controls.MenuItem)(target));
return;
case 3:
this.SearchTextBox = ((System.Windows.Controls.TextBox)(target));
return;
case 4:
this.CollectionContainer = ((System.Windows.Data.CollectionContainer)(target));
return;
case 5:
this.ContainerBelowSearch = ((System.Windows.Data.CollectionContainer)(target));
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace XamlGeneratedNamespace {
/// <summary>
/// GeneratedInternalTypeHelper
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public sealed class GeneratedInternalTypeHelper : System.Windows.Markup.InternalTypeHelper {
/// <summary>
/// CreateInstance
/// </summary>
protected override object CreateInstance(System.Type type, System.Globalization.CultureInfo culture) {
return System.Activator.CreateInstance(type, ((System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic)
| (System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.CreateInstance)), null, null, culture);
}
/// <summary>
/// GetPropertyValue
/// </summary>
protected override object GetPropertyValue(System.Reflection.PropertyInfo propertyInfo, object target, System.Globalization.CultureInfo culture) {
return propertyInfo.GetValue(target, System.Reflection.BindingFlags.Default, null, null, culture);
}
/// <summary>
/// SetPropertyValue
/// </summary>
protected override void SetPropertyValue(System.Reflection.PropertyInfo propertyInfo, object target, object value, System.Globalization.CultureInfo culture) {
propertyInfo.SetValue(target, value, System.Reflection.BindingFlags.Default, null, null, culture);
}
/// <summary>
/// CreateDelegate
/// </summary>
protected override System.Delegate CreateDelegate(System.Type delegateType, object target, string handler) {
return ((System.Delegate)(target.GetType().InvokeMember("_CreateDelegate", (System.Reflection.BindingFlags.InvokeMethod
| (System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)), null, target, new object[] {
delegateType,
handler}, null)));
}
/// <summary>
/// AddEventHandler
/// </summary>
protected override void AddEventHandler(System.Reflection.EventInfo eventInfo, object target, System.Delegate handler) {
eventInfo.AddEventHandler(target, handler);
}
}
}

View File

@@ -0,0 +1,90 @@
#pragma checksum "..\..\..\..\..\Group\AddEndpointDropPanel\AddEndpointDropPanelView.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "4B843E318B237C6F5C72D4FF330303240DAA0C30"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace NodeNetwork.Toolkit.Group.AddEndpointDropPanel {
/// <summary>
/// AddEndpointDropPanelView
/// </summary>
public partial class AddEndpointDropPanelView : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector {
#line 7 "..\..\..\..\..\Group\AddEndpointDropPanel\AddEndpointDropPanelView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal NodeNetwork.Toolkit.Group.AddEndpointDropPanel.AddEndpointDropPanelView Self;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/NodeNetworkToolkit;component/group/addendpointdroppanel/addendpointdroppanelview" +
".xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\..\Group\AddEndpointDropPanel\AddEndpointDropPanelView.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.Self = ((NodeNetwork.Toolkit.Group.AddEndpointDropPanel.AddEndpointDropPanelView)(target));
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,90 @@
#pragma checksum "..\..\..\..\..\Group\AddEndpointDropPanel\AddEndpointDropPanelView.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "4B843E318B237C6F5C72D4FF330303240DAA0C30"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace NodeNetwork.Toolkit.Group.AddEndpointDropPanel {
/// <summary>
/// AddEndpointDropPanelView
/// </summary>
public partial class AddEndpointDropPanelView : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector {
#line 7 "..\..\..\..\..\Group\AddEndpointDropPanel\AddEndpointDropPanelView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal NodeNetwork.Toolkit.Group.AddEndpointDropPanel.AddEndpointDropPanelView Self;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/NodeNetworkToolkit;component/group/addendpointdroppanel/addendpointdroppanelview" +
".xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\..\Group\AddEndpointDropPanel\AddEndpointDropPanelView.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.Self = ((NodeNetwork.Toolkit.Group.AddEndpointDropPanel.AddEndpointDropPanelView)(target));
return;
}
this._contentLoaded = true;
}
}
}

View File

@@ -0,0 +1,195 @@
#pragma checksum "..\..\..\..\NodeList\NodeListView.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "FD95BDD952CF5756320B0793E330657997B32353"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using NodeNetwork.Views.Controls;
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace NodeNetwork.Toolkit.NodeList {
/// <summary>
/// NodeListView
/// </summary>
public partial class NodeListView : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector, System.Windows.Markup.IStyleConnector {
#line 10 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal NodeNetwork.Toolkit.NodeList.NodeListView self;
#line default
#line hidden
#line 72 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock titleLabel;
#line default
#line hidden
#line 73 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.ComboBox viewComboBox;
#line default
#line hidden
#line 76 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Grid searchBoxGrid;
#line default
#line hidden
#line 77 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBox searchBox;
#line default
#line hidden
#line 78 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock emptySearchBoxMessage;
#line default
#line hidden
#line 83 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.ItemsControl elementsList;
#line default
#line hidden
#line 104 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock emptyMessage;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/NodeNetworkToolkit;component/nodelist/nodelistview.xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\NodeList\NodeListView.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.self = ((NodeNetwork.Toolkit.NodeList.NodeListView)(target));
return;
case 4:
this.titleLabel = ((System.Windows.Controls.TextBlock)(target));
return;
case 5:
this.viewComboBox = ((System.Windows.Controls.ComboBox)(target));
return;
case 6:
this.searchBoxGrid = ((System.Windows.Controls.Grid)(target));
return;
case 7:
this.searchBox = ((System.Windows.Controls.TextBox)(target));
return;
case 8:
this.emptySearchBoxMessage = ((System.Windows.Controls.TextBlock)(target));
return;
case 9:
this.elementsList = ((System.Windows.Controls.ItemsControl)(target));
return;
case 10:
this.emptyMessage = ((System.Windows.Controls.TextBlock)(target));
return;
}
this._contentLoaded = true;
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
void System.Windows.Markup.IStyleConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 2:
#line 19 "..\..\..\..\NodeList\NodeListView.xaml"
((System.Windows.Controls.Grid)(target)).MouseMove += new System.Windows.Input.MouseEventHandler(this.OnNodeMouseMove);
#line default
#line hidden
break;
case 3:
#line 31 "..\..\..\..\NodeList\NodeListView.xaml"
((System.Windows.Controls.Grid)(target)).MouseMove += new System.Windows.Input.MouseEventHandler(this.OnNodeMouseMove);
#line default
#line hidden
break;
}
}
}
}

View File

@@ -0,0 +1,195 @@
#pragma checksum "..\..\..\..\NodeList\NodeListView.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "FD95BDD952CF5756320B0793E330657997B32353"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using NodeNetwork.Views.Controls;
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace NodeNetwork.Toolkit.NodeList {
/// <summary>
/// NodeListView
/// </summary>
public partial class NodeListView : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector, System.Windows.Markup.IStyleConnector {
#line 10 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal NodeNetwork.Toolkit.NodeList.NodeListView self;
#line default
#line hidden
#line 72 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock titleLabel;
#line default
#line hidden
#line 73 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.ComboBox viewComboBox;
#line default
#line hidden
#line 76 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Grid searchBoxGrid;
#line default
#line hidden
#line 77 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBox searchBox;
#line default
#line hidden
#line 78 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock emptySearchBoxMessage;
#line default
#line hidden
#line 83 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.ItemsControl elementsList;
#line default
#line hidden
#line 104 "..\..\..\..\NodeList\NodeListView.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock emptyMessage;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/NodeNetworkToolkit;component/nodelist/nodelistview.xaml", System.UriKind.Relative);
#line 1 "..\..\..\..\NodeList\NodeListView.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.self = ((NodeNetwork.Toolkit.NodeList.NodeListView)(target));
return;
case 4:
this.titleLabel = ((System.Windows.Controls.TextBlock)(target));
return;
case 5:
this.viewComboBox = ((System.Windows.Controls.ComboBox)(target));
return;
case 6:
this.searchBoxGrid = ((System.Windows.Controls.Grid)(target));
return;
case 7:
this.searchBox = ((System.Windows.Controls.TextBox)(target));
return;
case 8:
this.emptySearchBoxMessage = ((System.Windows.Controls.TextBlock)(target));
return;
case 9:
this.elementsList = ((System.Windows.Controls.ItemsControl)(target));
return;
case 10:
this.emptyMessage = ((System.Windows.Controls.TextBlock)(target));
return;
}
this._contentLoaded = true;
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
void System.Windows.Markup.IStyleConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 2:
#line 19 "..\..\..\..\NodeList\NodeListView.xaml"
((System.Windows.Controls.Grid)(target)).MouseMove += new System.Windows.Input.MouseEventHandler(this.OnNodeMouseMove);
#line default
#line hidden
break;
case 3:
#line 31 "..\..\..\..\NodeList\NodeListView.xaml"
((System.Windows.Controls.Grid)(target)).MouseMove += new System.Windows.Input.MouseEventHandler(this.OnNodeMouseMove);
#line default
#line hidden
break;
}
}
}
}

View File

@@ -0,0 +1,3 @@
is_global = true
build_property.RootNamespace = NodeNetwork.Toolkit
build_property.ProjectDir = E:\p4\bluflame\intromat\NodeNetworkToolkit\

View File

@@ -0,0 +1 @@
4d60b4fb02d3e818c76aed6fc26f7d85578917d1

View File

@@ -0,0 +1,38 @@
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\NodeNetworkToolkit.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\NodeNetworkToolkit.pdb
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\DynamicData.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\log4net.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\Pharmacist.Common.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\ReactiveUI.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\ReactiveUI.Events.WPF.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\ReactiveUI.Wpf.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\Splat.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\Splat.Drawing.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\System.Buffers.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\System.Collections.Immutable.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\System.Memory.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\System.Numerics.Vectors.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\System.Reactive.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\System.Runtime.CompilerServices.Unsafe.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\System.Threading.Tasks.Extensions.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\System.ValueTuple.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\NodeNetwork.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\bin\Debug\net48\NodeNetwork.pdb
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit.csproj.AssemblyReference.cache
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\BreadcrumbBar\BreadcrumbBarView.baml
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\Group\AddEndpointDropPanel\AddEndpointDropPanelView.baml
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeList\NodeListView.baml
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\BreadcrumbBar\BreadcrumbBarView.g.cs
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\ContextMenu\SearchableContextMenuView.g.cs
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\Group\AddEndpointDropPanel\AddEndpointDropPanelView.g.cs
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeList\NodeListView.g.cs
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\GeneratedInternalTypeHelper.g.cs
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit_MarkupCompile.cache
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit_MarkupCompile.lref
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\ContextMenu\SearchableContextMenuView.baml
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit.g.resources
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit.csproj.CoreCompileInputs.cache
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit.csproj.CopyComplete
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit.dll
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit.pdb
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\NodeNetworkToolkit.GeneratedMSBuildEditorConfig.editorconfig

View File

@@ -0,0 +1,20 @@
NodeNetworkToolkit
library
C#
.cs
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\
NodeNetwork.Toolkit
none
false
TRACE;DEBUG;NETFRAMEWORK;NET48;
4290141240
26-1670165176
44735160913
BreadcrumbBar\BreadcrumbBarView.xaml;ContextMenu\SearchableContextMenuView.xaml;Group\AddEndpointDropPanel\AddEndpointDropPanelView.xaml;NodeList\NodeListView.xaml;
False

View File

@@ -0,0 +1,20 @@
NodeNetworkToolkit
library
C#
.cs
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\
NodeNetwork.Toolkit
none
false
TRACE;DEBUG;NETFRAMEWORK;NET48;
4290141240
27-1943407535
44735160913
BreadcrumbBar\BreadcrumbBarView.xaml;ContextMenu\SearchableContextMenuView.xaml;Group\AddEndpointDropPanel\AddEndpointDropPanelView.xaml;NodeList\NodeListView.xaml;
False

View File

@@ -0,0 +1,4 @@
E:\p4\bluflame\intromat\NodeNetworkToolkit\obj\Debug\net48\GeneratedInternalTypeHelper.g.cs
FE:\p4\bluflame\intromat\NodeNetworkToolkit\ContextMenu\SearchableContextMenuView.xaml;;

View File

@@ -0,0 +1,3 @@
is_global = true
build_property.RootNamespace = NodeNetwork.Toolkit
build_property.ProjectDir = E:\p4\bluflame\intromat\NodeNetworkToolkit\

View File

@@ -0,0 +1,3 @@
is_global = true
build_property.RootNamespace = NodeNetwork.Toolkit
build_property.ProjectDir = E:\p4\bluflame\intromat\NodeNetworkToolkit\

View File

@@ -0,0 +1,3 @@
is_global = true
build_property.RootNamespace = NodeNetwork.Toolkit
build_property.ProjectDir = E:\p4\bluflame\intromat\NodeNetworkToolkit\

Some files were not shown because too many files have changed in this diff Show More