Archived
Private
Public Access
1
0

Initial commit

This commit is contained in:
2022-09-04 12:45:01 +02:00
commit f4a01d6a69
11601 changed files with 4206660 additions and 0 deletions

5
C#/DigiSim/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
bin/
obj/
/packages/
riderModule.iml
/_ReSharper.Caches/

13
C#/DigiSim/.idea/.idea.DigiSim/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/projectSettingsUpdater.xml
/contentModel.xml
/.idea.DigiSim.iml
/modules.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettings">
<enabledExtensions>
<entry key="MermaidLanguageExtension" value="false" />
<entry key="PlantUMLLanguageExtension" value="false" />
</enabledExtensions>
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="com.jetbrains.rider.android.RiderAndroidMiscFileCreationComponent">
<option name="ENSURE_MISC_FILE_EXISTS" value="true" />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

6
C#/DigiSim/App.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>

9
C#/DigiSim/App.xaml Normal file
View File

@@ -0,0 +1,9 @@
<Application x:Class="DigiSim.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DigiSim"
StartupUri="Window.xaml">
<Application.Resources>
</Application.Resources>
</Application>

6
C#/DigiSim/App.xaml.cs Normal file
View File

@@ -0,0 +1,6 @@
namespace DigiSim {
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App { }
}

View File

@@ -0,0 +1,100 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
namespace DigiSim {
[SuppressUnmanagedCodeSecurity]
public static class ConsoleManager
{
private const string Kernel32DllName = "kernel32.dll";
[DllImport(Kernel32DllName)]
private static extern bool AllocConsole();
[DllImport(Kernel32DllName)]
private static extern bool FreeConsole();
[DllImport(Kernel32DllName)]
private static extern IntPtr GetConsoleWindow();
[DllImport(Kernel32DllName)]
private static extern int GetConsoleOutputCP();
public static bool HasConsole
{
get { return GetConsoleWindow() != IntPtr.Zero; }
}
/// <summary>
/// Creates a new console instance if the process is not attached to a console already.
/// </summary>
public static void Show()
{
//#if DEBUG
if (!HasConsole)
{
AllocConsole();
InvalidateOutAndError();
}
//#endif
}
/// <summary>
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
/// </summary>
public static void Hide()
{
//#if DEBUG
if (HasConsole)
{
SetOutAndErrorNull();
FreeConsole();
}
//#endif
}
public static void Toggle()
{
if (HasConsole)
{
Hide();
}
else
{
Show();
}
}
static void InvalidateOutAndError()
{
Type type = typeof(System.Console);
System.Reflection.FieldInfo _out = type.GetField("_out",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
System.Reflection.FieldInfo _error = type.GetField("_error",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
Debug.Assert(_out != null);
Debug.Assert(_error != null);
Debug.Assert(_InitializeStdOutError != null);
_out.SetValue(null, null);
_error.SetValue(null, null);
_InitializeStdOutError.Invoke(null, new object[] { true });
}
static void SetOutAndErrorNull()
{
Console.SetOut(TextWriter.Null);
Console.SetError(TextWriter.Null);
}
}
}

100
C#/DigiSim/DigiSim.csproj Normal file
View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7D136E06-FE30-40BE-B400-F17F97C5B21C}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>DigiSim</RootNamespace>
<AssemblyName>DigiSim</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="Window.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="ConsoleManager.cs" />
<Compile Include="Logic\ButtonInput.cs" />
<Compile Include="Logic\Gates\AndGate.cs" />
<Compile Include="Logic\Gates\CustomGate.cs" />
<Compile Include="Logic\Gates\NandGate.cs" />
<Compile Include="Logic\Gates\NorGate.cs" />
<Compile Include="Logic\Gates\NotGate.cs" />
<Compile Include="Logic\Gates\OrGate.cs" />
<Compile Include="Logic\Gates\XnorGate.cs" />
<Compile Include="Logic\Gates\XorGate.cs" />
<Compile Include="Logic\Splitter.cs" />
<Compile Include="Logic\Gate.cs" />
<Compile Include="Logic\Input.cs" />
<Compile Include="Logic\Output.cs" />
<Compile Include="Logic\Wire.cs" />
<Compile Include="Window.xaml.cs">
<DependentUpon>Window.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

16
C#/DigiSim/DigiSim.sln Normal file
View File

@@ -0,0 +1,16 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigiSim", "DigiSim.csproj", "{7D136E06-FE30-40BE-B400-F17F97C5B21C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7D136E06-FE30-40BE-B400-F17F97C5B21C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D136E06-FE30-40BE-B400-F17F97C5B21C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D136E06-FE30-40BE-B400-F17F97C5B21C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D136E06-FE30-40BE-B400-F17F97C5B21C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,39 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class ButtonInput : Gate {
private bool _powered;
protected override void InternalSetup(Canvas canvas) {
Shape = new Ellipse();
SetOutputs(1);
SetInputs(0);
CreateConnections();
Shape.MouseLeftButtonDown += (sender, args) => {
if (IsAttached) return;
_powered = true;
Update(this);
};
Shape.MouseLeftButtonUp += (sender, args) => {
if (IsAttached) return;
_powered = false;
Update(this);
};
Text = "B";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = _powered;
Shape.Fill = _powered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
UpdateShapes();
UpdateConnectedGates(source);
}
public ButtonInput(double x, double y) : base(x, y, 20, 20) { }
}
}

308
C#/DigiSim/Logic/Gate.cs Normal file
View File

@@ -0,0 +1,308 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public abstract class Gate {
private TextBlock _textBlock;
private MouseEventHandler _onMove;
private MouseEventHandler _onLeave;
private MouseButtonEventHandler _onUp;
private MouseButtonEventHandler _onDown;
private MouseButtonEventHandler _onDelete;
protected bool IsAttached;
public Point Position { get; private set; }
public Size Size { get; protected set; }
protected Shape Shape { get; set; }
protected Tuple<Tuple<Shape, Shape>, Line>[] ConnectorLines { get; set; }
public Ellipse[] InputShapes { get; protected set; }
public Ellipse[] OutputShapes { get; protected set; }
public Wire[] ConnectedInputs { get; protected set; }
public Wire[] ConnectedOutputs { get; protected set; }
protected Dictionary<bool, bool, bool> TruthTable { get; set; }
protected string Text { get; set; }
public bool IsDeleted { get; private set; }
protected Gate(double x, double y, double width, double height) {
Constructor(x, y, width, height);
}
protected Gate() {}
protected void Constructor(double x, double y, double width, double height) {
Position = new Point(x, y);
Size = new Size(width, height);
_textBlock = new TextBlock()
{TextAlignment = TextAlignment.Center, Foreground = Brushes.White, FontSize = 15, IsHitTestVisible = false };
Setup(Window.Board);
Shape.Fill = FromHex(Window.FillColor);
}
private void Setup(Canvas canvas) {
TruthTable = new Dictionary<bool, bool, bool>();
_onMove = (sender, e) => {
if (IsAttached) {
Point mouse = Mouse.GetPosition(canvas);
Position = new Point(
mouse.X - Size.Width / 2,
mouse.Y - Size.Height / 2
);
Update(this);
}
else if (Mouse.LeftButton == MouseButtonState.Pressed && e.OriginalSource.Equals(Shape) && Window.CurrentConnection == null)
AttachToMouse();
};
_onUp = (s, e) => IsAttached = false;
_onLeave = (s, e) => IsAttached = false;
_onDown = (sender, e) => {
if (IsAttached) return;
if (ConnectedOutputs != null) {
for (int i = 0; i < ConnectedOutputs.Length; i++) {
if (IsMouseOver(OutputShapes[i])) {
Window.StartConnectingGates(this, i);
return;
}
}
}
if (ConnectedInputs != null) {
for (int i = 0; i < ConnectedInputs.Length; i++) {
Wire wire = ConnectedInputs[i];
if (IsMouseOver(InputShapes[i])) {
wire.Delete();
return;
}
}
}
};
_onDelete = (sender, e) => {
if (e.OriginalSource.Equals(Shape))
Window.DeleteGate(this);
};
canvas.MouseMove += _onMove;
canvas.MouseLeave += _onLeave;
canvas.MouseUp += _onUp;
canvas.MouseDown += _onDown;
canvas.MouseRightButtonUp += _onDelete;
InternalSetup(canvas);
if (InputShapes != null) ConnectedInputs = Enumerable.Repeat(new Wire(), InputShapes.Length).ToArray();
if (OutputShapes != null) ConnectedOutputs = Enumerable.Repeat(new Wire(), OutputShapes.Length).ToArray();
Update(this);
}
public void AttachToMouse() {
IsAttached = true;
}
protected abstract void InternalSetup(Canvas canvas);
public abstract void Update(Gate source);
protected void UpdateShapes() {
Shape.Width = Size.Width;
Shape.Height = Size.Height;
Canvas.SetLeft(Shape, Position.X);
Canvas.SetTop(Shape, Position.Y);
Canvas.SetZIndex(Shape, 10);
double outSpace = Size.Height / OutputShapes.Length;
for (int i = 0; i < OutputShapes.Length; i++) {
Shape shape = OutputShapes[i];
shape.Width = 10;
shape.Height = 10;
shape.Fill = ConnectedOutputs[i].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
Canvas.SetLeft(shape, Position.X + Size.Width + 5);
Canvas.SetTop(shape, Position.Y + outSpace * i + outSpace / 2 - 5);
Canvas.SetZIndex(shape, 2);
}
double inSpace = Size.Height / InputShapes.Length;
for (int i = 0; i < InputShapes.Length; i++) {
Shape shape = InputShapes[i];
shape.Width = 10;
shape.Height = 10;
shape.Fill = ConnectedInputs[i].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
Canvas.SetLeft(shape, Position.X - 15);
Canvas.SetTop(shape, Position.Y + inSpace * i + inSpace / 2 - 5);
Canvas.SetZIndex(shape, 2);
}
foreach (var line in ConnectorLines) {
Tuple<Shape, Shape> t = line.Item1;
Point p1 = new Point(Canvas.GetLeft(t.Item1) + t.Item1.Width / 2, 0);
Point p2 = new Point(Canvas.GetLeft(t.Item2) + t.Item2.Width / 2,
Canvas.GetTop(t.Item2) + t.Item2.Height / 2);
line.Item2.Stroke = FromHex(Window.FillColor);
line.Item2.StrokeThickness = 1;
line.Item2.X1 = p1.X;
line.Item2.X2 = p2.X;
line.Item2.Y1 = p2.Y;
line.Item2.Y2 = p2.Y;
Canvas.SetZIndex(line.Item2, 1);
}
_textBlock.Width = Size.Width;
_textBlock.Height = Size.Height;
Canvas.SetLeft(_textBlock, Position.X);
Canvas.SetTop(_textBlock, Position.Y);
Canvas.SetZIndex(_textBlock, 11);
_textBlock.Text = Text;
}
protected void UpdateConnectedGates(Gate source) {
if (ConnectedOutputs != null) {
foreach (var output in ConnectedOutputs) {
if (output != null)
output.Update();
else continue;
if (output.Site2 != null) {
if (output.Site2 != source)
output.Site2.Update(source);
}
}
}
if (ConnectedInputs != null) {
foreach (var input in ConnectedInputs) {
if (input != null)
input.Update();
}
}
}
protected void SetInputs(int count) {
InputShapes = new Ellipse[count];
for (int i = 0; i < count; i++) {
InputShapes[i] = new Ellipse();
}
}
protected void SetOutputs(int count) {
OutputShapes = new Ellipse[count];
for (int i = 0; i < count; i++) {
OutputShapes[i] = new Ellipse();
}
}
protected void CreateConnections() {
List<Tuple<Tuple<Shape, Shape>, Line>> connections = new List<Tuple<Tuple<Shape, Shape>, Line>>();
foreach (var inputShape in InputShapes) {
connections.Add(new Tuple<Tuple<Shape, Shape>, Line>(new Tuple<Shape, Shape>(Shape, inputShape), new Line()));
}
foreach (var outputShape in OutputShapes) {
connections.Add(new Tuple<Tuple<Shape, Shape>, Line>(new Tuple<Shape, Shape>(Shape, outputShape), new Line()));
}
ConnectorLines = connections.ToArray();
}
protected void Instantiate() {
foreach (var connectorLine in ConnectorLines) {
Window.Board.Children.Add(connectorLine.Item2);
}
foreach (var inputShape in InputShapes) {
Window.Board.Children.Add(inputShape);
}
foreach (var outputShape in OutputShapes) {
Window.Board.Children.Add(outputShape);
}
Window.Board.Children.Add(Shape);
Window.Board.Children.Add(_textBlock);
}
public void Delete() {
IsDeleted = true;
Window.Board.MouseMove -= _onMove;
Window.Board.MouseLeave -= _onLeave;
Window.Board.MouseUp -= _onUp;
Window.Board.MouseDown -= _onDown;
Window.Board.MouseRightButtonUp -= _onDelete;
Window.Board.Children.Remove(Shape);
Window.Board.Children.Remove(_textBlock);
foreach (var connectorLine in ConnectorLines) {
Window.Board.Children.Remove(connectorLine.Item2);
}
foreach (var inputShape in InputShapes) {
Window.Board.Children.Remove(inputShape);
}
foreach (var outputShape in OutputShapes) {
Window.Board.Children.Remove(outputShape);
}
foreach (var connectedInput in ConnectedInputs) {
connectedInput.Delete();
}
ConnectedInputs = null;
foreach (var connectedOutput in ConnectedOutputs) {
connectedOutput.Delete();
}
ConnectedOutputs = null;
}
// STATIC UTILITIY METHODS
private static Rect GetBounds(Shape shape) {
return shape.TransformToVisual(Window.Board)
.TransformBounds(new Rect(0, 0, shape.ActualWidth, shape.ActualHeight));
}
public static bool CheckBoundingIntersection(Shape shape1, Shape shape2) {
return GetBounds(shape1).IntersectsWith(GetBounds(shape2));
}
public static bool IsMouseOver(Shape shape) {
return GetBounds(shape).Contains(Mouse.GetPosition(Window.Board));
}
public static SolidColorBrush FromHex(String hex) {
return (SolidColorBrush)new BrushConverter().ConvertFromString(hex);
}
}
public class Dictionary<TKey1,TKey2,TValue> : Dictionary<Tuple<TKey1, TKey2>, TValue>, IDictionary<Tuple<TKey1, TKey2>, TValue>
{
public TValue this[TKey1 key1, TKey2 key2]
{
get { return base[Tuple.Create(key1, key2)]; }
set { base[Tuple.Create(key1, key2)] = value; }
}
public void Add(TKey1 key1, TKey2 key2, TValue value)
{
base.Add(Tuple.Create(key1, key2), value);
}
public bool ContainsKey(TKey1 key1, TKey2 key2)
{
return base.ContainsKey(Tuple.Create(key1, key2));
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class AndGate : Gate {
public AndGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, false);
TruthTable.Add(false, true, false);
TruthTable.Add(true, false, false);
TruthTable.Add(true, true, true);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "&";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class CustomGate : Gate {
public int Inputs { get; }
public int Outputs { get; }
public string Symbol { get; }
public LookupTable Lookup { get; }
public CustomGate(double x, double y) : base(x, y, 50, 50) { }
private CustomGate(string symbol, LookupTable lookup) {
Symbol = symbol;
Lookup = lookup;
Inputs = lookup.InputCount;
Outputs = lookup.OutputCount;
Constructor(0, 0, 0, 0);
}
protected override void InternalSetup(Canvas canvas) {
Shape = new Rectangle();
int connectorCount = Math.Max(Inputs, Outputs);
Size = new Size(50, connectorCount * 25);
SetInputs(Inputs);
SetOutputs(Outputs);
CreateConnections();
Text = Symbol;
Instantiate();
}
public override void Update(Gate source) {
bool[] snapshot = new bool[ConnectedInputs.Length];
for (var i = 0; i < snapshot.Length; i++) {
snapshot[i] = ConnectedInputs[i].IsPowered;
}
bool[] outputs = Lookup.GetOutputs(snapshot);
for (var i = 0; i < ConnectedOutputs.Length; i++) {
ConnectedOutputs[i].IsPowered = outputs[i];
}
UpdateShapes();
UpdateConnectedGates(source);
}
public struct LookupTable {
public bool[,] Inputs { get; }
public bool[,] Outputs { get; }
public int InputCount { get; }
public int OutputCount { get; }
public int Length { get; }
public LookupTable(int inputCount, int outputCount, int length) {
Inputs = new bool[length, inputCount];
Outputs = new bool[length, outputCount];
InputCount = inputCount;
OutputCount = outputCount;
Length = length;
}
public bool[] GetOutputs(bool[] inputs) {
if (inputs.Length != InputCount) throw new ArgumentOutOfRangeException(nameof(inputs));
for (int i = 0; i < Length; i++) {
bool found = true;
for (int j = 0; j < InputCount; j++) {
if (Inputs[i, j] != inputs[j]) {
found = false;
break;
}
}
if (found) {
bool[] output = new bool[OutputCount];
for (int o = 0; o < OutputCount; o++) {
output[o] = Outputs[i, o];
}
return output;
}
}
return new bool[OutputCount];
}
public void SetLookup(bool[] inputs, bool[] outputs, int index) {
if (index >= Length) throw new IndexOutOfRangeException(nameof(index));
for (var i = 0; i < inputs.Length; i++) {
Inputs[index, i] = inputs[i];
}
for (var i = 0; i < outputs.Length; i++) {
Outputs[index, i] = outputs[i];
}
}
}
private static LookupTable CreateLookup(Gate[] gates) {
List<Input> inputs = new List<Input>();
List<Output> outputs = new List<Output>();
foreach (var gate in gates) {
if (gate is Input)
inputs.Add(gate as Input);
if (gate is Output)
outputs.Add(gate as Output);
}
int possibilities = (int) Math.Pow(2, inputs.Count);
LookupTable lookupTable = new LookupTable(inputs.Count, outputs.Count, possibilities);
for (var i = 0; i < possibilities; i++) {
bool[] inputSequenze = new bool[inputs.Count];
bool[] outputSequenze = new bool[outputs.Count];
char[] sequenze = Convert.ToString(i, 2).PadLeft(inputs.Count, '0').ToCharArray();
for (var j = 0; j < sequenze.Length; j++) {
inputSequenze[j] = sequenze[j] == '1';
inputs[j].Powered = sequenze[j] == '1';
inputs[j].Update(inputs[j]);
}
for (var j = 0; j < outputs.Count; j++) {
outputSequenze[j] = outputs[j].ConnectedInputs[0].IsPowered;
}
lookupTable.SetLookup(inputSequenze, outputSequenze, i);
}
return lookupTable;
}
public static CustomGate CreateCustomGateFromBoard(Gate[] gates, string symbol) {
return new CustomGate(symbol, CreateLookup(gates));
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class NandGate : Gate {
public NandGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, true);
TruthTable.Add(false, true, true);
TruthTable.Add(true, false, true);
TruthTable.Add(true, true, false);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "!&";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class NorGate : Gate {
public NorGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, true);
TruthTable.Add(false, true, false);
TruthTable.Add(true, false, false);
TruthTable.Add(true, true, false);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "!>1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class NotGate : Gate {
public NotGate(double x, double y) : base(x, y, 25, 25) { }
protected override void InternalSetup(Canvas canvas) {
Shape = new Rectangle();
SetInputs(1);
SetOutputs(1);
CreateConnections();
Text = "!1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = !ConnectedInputs[0].IsPowered;
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class OrGate : Gate {
public OrGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, false);
TruthTable.Add(false, true, true);
TruthTable.Add(true, false, true);
TruthTable.Add(true, true, true);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = ">1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class XnorGate : Gate {
public XnorGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, true);
TruthTable.Add(false, true, false);
TruthTable.Add(true, false, false);
TruthTable.Add(true, true, true);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "!=1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class XorGate : Gate {
public XorGate(double x, double y) : base(x, y, 50, 50) { }
protected override void InternalSetup(Canvas canvas) {
TruthTable.Add(false, false, false);
TruthTable.Add(false, true, true);
TruthTable.Add(true, false, true);
TruthTable.Add(true, true, false);
Shape = new Rectangle();
SetInputs(2);
SetOutputs(1);
CreateConnections();
Text = "=1";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

34
C#/DigiSim/Logic/Input.cs Normal file
View File

@@ -0,0 +1,34 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class Input : Gate {
public bool Powered;
protected override void InternalSetup(Canvas canvas) {
Shape = new Ellipse();
SetOutputs(1);
SetInputs(0);
CreateConnections();
Shape.MouseLeftButtonUp += (sender, args) => {
if (IsAttached) return;
Powered = !Powered;
Update(this);
};
Text = "I";
Instantiate();
}
public override void Update(Gate source) {
ConnectedOutputs[0].IsPowered = Powered;
Shape.Fill = Powered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
UpdateShapes();
UpdateConnectedGates(source);
}
public Input(double x, double y) : base(x, y, 20, 20) { }
}
}

View File

@@ -0,0 +1,26 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class Output : Gate {
public Output(double x, double y) : base(x, y, 20, 20) { }
protected override void InternalSetup(Canvas canvas) {
Shape = new Ellipse();
SetInputs(1);
SetOutputs(0);
CreateConnections();
Text = "O";
Instantiate();
}
public override void Update(Gate source) {
Shape.Fill = ConnectedInputs[0].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

View File

@@ -0,0 +1,27 @@
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class Splitter : Gate {
public Splitter(double x, double y) : base(x, y, 25, 25) { }
protected override void InternalSetup(Canvas canvas) {
Shape = new Rectangle();
SetOutputs(2);
SetInputs(1);
CreateConnections();
Text = "S";
Instantiate();
}
public override void Update(Gate source) {
bool input = ConnectedInputs[0].IsPowered;
ConnectedOutputs[0].IsPowered = input;
ConnectedOutputs[1].IsPowered = input;
UpdateShapes();
UpdateConnectedGates(source);
}
}
}

74
C#/DigiSim/Logic/Wire.cs Normal file
View File

@@ -0,0 +1,74 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace DigiSim.Logic {
public class Wire {
public Gate Site1 { get; set; }
public Gate Site2 { get; set; }
public int OutputIndex { get; set; }
public int InputIndex { get; set; }
public bool IsPowered { get; set; }
public Line Connection { get; }
public Wire() {
Connection = new Line();
Window.Board.Children.Add(Connection);
}
public void Update() {
if (Site1 == null || Site2 == null) return;
Shape site1 = Site1.OutputShapes[OutputIndex];
Shape site2 = Site2.InputShapes[InputIndex];
Point p1 = new Point(Canvas.GetLeft(site1) + site1.Width / 2,
Canvas.GetTop(site1) + site1.Height / 2);
Point p2 = new Point(Canvas.GetLeft(site2) + site2.Width / 2,
Canvas.GetTop(site2) + site2.Height / 2);
Connection.Stroke = IsPowered ? Gate.FromHex(Window.PoweredColor) : Gate.FromHex(Window.FillColor);
Connection.StrokeThickness = 1;
Connection.X1 = p1.X;
Connection.X2 = p2.X;
Connection.Y1 = p1.Y;
Connection.Y2 = p2.Y;
}
public void ConnectShapeToPoint(Shape shape, Point point) {
Point p1 = new Point(Canvas.GetLeft(shape) + shape.Width / 2,
Canvas.GetTop(shape) + shape.Height / 2);
Connection.Stroke = Gate.FromHex(Window.FillColor);
Connection.StrokeThickness = 1;
Connection.X1 = p1.X;
Connection.X2 = point.X;
Connection.Y1 = p1.Y;
Connection.Y2 = point.Y;
}
public void Delete() {
Window.Board.Children.Remove(Connection);
if (Site1 != null) {
if (!Site1.IsDeleted) {
Site1.ConnectedOutputs[OutputIndex] = new Wire();
Site1.Update(Site1);
}
}
if (Site2 != null) {
if (!Site2.IsDeleted) {
Site2.ConnectedInputs[InputIndex] = new Wire();
Site2.Update(Site2);
}
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 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("DigiSim")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DigiSim")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[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)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// 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("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,61 @@
//------------------------------------------------------------------------------
// <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 DigiSim.Properties {
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder",
"4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance",
"CA1811:AvoidUncalledPrivateCode")]
internal Resources() { }
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState
.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if ((resourceMan == null)) {
global::System.Resources.ResourceManager temp =
new global::System.Resources.ResourceManager("DigiSim.Properties.Resources",
typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState
.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get { return resourceCulture; }
set { resourceCulture = value; }
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

199
C#/DigiSim/Window.xaml Normal file
View File

@@ -0,0 +1,199 @@
<Window x:Class="DigiSim.Window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DigiSim"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow" Height="720" Width="1280">
<Window.Resources>
<Brush x:Key="Cyan">#5BC0EB</Brush>
<Brush x:Key="Yellow">#FDE74C</Brush>
<Brush x:Key="Green">#9BC53D</Brush>
<Brush x:Key="Red">#E55934</Brush>
<Brush x:Key="Orange">#FA7921</Brush>
<Brush x:Key="Light">#6D6A75</Brush>
<Brush x:Key="Gray">#524E5A</Brush>
<Brush x:Key="Dark">#37323E</Brush>
<Style TargetType="{x:Type Button}" x:Key="GateButtons">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource Gray}" TargetName="Border" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource Light}" TargetName="Border"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="{StaticResource Dark}">
<Grid.RowDefinitions>
<RowDefinition Height="18"/>
<RowDefinition/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<Menu Grid.Row="0" Background="White">
<MenuItem Header="_File">
<MenuItem Header="_New" Click="NewFile"/>
<MenuItem Header="_Open"/>
<MenuItem Header="_Save"/>
<Separator/>
<MenuItem Header="_Exit"/>
</MenuItem>
<MenuItem Header="_Edit">
<MenuItem Header="_Delete all self build Gates"/>
<MenuItem Header="_Save as Gate" Click="SaveAsGate"/>
</MenuItem>
<MenuItem Header="_Board">
<MenuItem Header="_Add Input"/>
<MenuItem Header="_Add Output"/>
</MenuItem>
<MenuItem Header="_Gates" x:Name="CustomGates">
</MenuItem>
</Menu>
<Canvas Grid.Row="1" Background="{StaticResource Gray}" Margin="50" x:Name="Canvas"/>
<Grid Grid.Row="2">
<Grid.Resources>
<system:Double x:Key="Width">75</system:Double>
</Grid.Resources>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnInput"
Content="Input"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnOutput"
Content="Output"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnButton"
Content="Button"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnSplitter"
Content="Splitter"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnAnd"
Content="AND"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnNand"
Content="NAND"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnOr"
Content="OR"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnNor"
Content="NOR"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnNot"
Content="NOT"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnXor"
Content="XOR"/>
<Button
Width="{StaticResource Width}"
Margin="5"
FontSize="20"
Background="{StaticResource Light}"
Foreground="White"
Style="{StaticResource GateButtons}"
Click="GateButtonClick"
x:Name="BtnXnor"
Content="XNOR"/>
</StackPanel>
</Grid>
</Grid>
</Window>

126
C#/DigiSim/Window.xaml.cs Normal file
View File

@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using DigiSim.Logic;
using DigiSim.Logic.Gates;
namespace DigiSim {
public partial class Window {
public const String FillColor = "#37323E";
public const String PoweredColor = "#E55934";
public static Canvas Board { get; private set; }
private static readonly List<Gate> Gates = new();
public Window() {
ConsoleManager.Show();
InitializeComponent();
Board = Canvas;
Canvas.MouseMove += (sender, e) => {
if (CurrentConnection != null) {
CurrentConnection.ConnectShapeToPoint(CurrentConnection.Site1.OutputShapes[CurrentConnection.OutputIndex], Mouse.GetPosition(Canvas));
}
};
Canvas.MouseUp += (sender, e) => {
if (CurrentConnection != null) {
foreach (var gate in Gates) {
if (gate.InputShapes == null) continue;
for (int i = 0; i < gate.InputShapes.Length; i++) {
if (Gate.IsMouseOver(gate.InputShapes[i])) {
ConnectGates(CurrentConnection.Site1, gate, i, CurrentConnection.OutputIndex);
Canvas.Children.Remove(CurrentConnection.Connection);
CurrentConnection = null;
return;
}
}
}
CurrentConnection.Delete();
CurrentConnection = null;
}
};
}
private void GateButtonClick(object sender, RoutedEventArgs e) {
if (sender.Equals(BtnInput))
CreateGate(new Input(0, 0));
if (sender.Equals(BtnOutput))
CreateGate(new Output(0, 0));
if (sender.Equals(BtnButton))
CreateGate(new ButtonInput(0, 0));
if (sender.Equals(BtnSplitter))
CreateGate(new Splitter(0, 0));
if (sender.Equals(BtnAnd))
CreateGate(new AndGate(0, 0));
if (sender.Equals(BtnNand))
CreateGate(new NandGate(0, 0));
if (sender.Equals(BtnOr))
CreateGate(new OrGate(0, 0));
if (sender.Equals(BtnNor))
CreateGate(new NorGate(0, 0));
if (sender.Equals(BtnNot))
CreateGate(new NotGate(0, 0));
if (sender.Equals(BtnXor))
CreateGate(new XorGate(0, 0));
if (sender.Equals(BtnXnor))
CreateGate(new XnorGate(0, 0));
}
private void CreateGate(Gate gate) {
gate.AttachToMouse();
Gates.Add(gate);
gate.Update(gate);
}
public static Wire CurrentConnection;
public static void StartConnectingGates(Gate gate, int outputIndex) {
CurrentConnection = new Wire();
CurrentConnection.Site1 = gate;
CurrentConnection.OutputIndex = outputIndex;
}
public static void DeleteGate(Gate gate) {
gate.Delete();
Gates.Remove(gate);
}
private void ConnectGates(Gate gate1, Gate gate2, int inputIndex, int outputIndex) {
gate1.ConnectedOutputs[outputIndex].Delete();
gate2.ConnectedInputs[inputIndex].Delete();
Wire wire = new Wire();
wire.Site1 = gate1;
wire.Site2 = gate2;
wire.OutputIndex = outputIndex;
wire.InputIndex = inputIndex;
gate1.ConnectedOutputs[outputIndex] = wire;
gate2.ConnectedInputs[inputIndex] = wire;
wire.Update();
gate1.Update(gate1);
}
private void NewFile(object sender, RoutedEventArgs e) {
Gates.ForEach((gate) => gate.Delete());
Gates.Clear();
}
private void SaveAsGate(object sender, RoutedEventArgs e) {
CustomGate gate = CustomGate.CreateCustomGateFromBoard(Gates.ToArray(), "C");
NewFile(sender, e);
Gates.Add(gate);
gate.AttachToMouse();
}
}
}