Initial commit
This commit is contained in:
5
C#/DigiSim/.gitignore
vendored
Normal file
5
C#/DigiSim/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
13
C#/DigiSim/.idea/.idea.DigiSim/.idea/.gitignore
generated
vendored
Normal file
13
C#/DigiSim/.idea/.idea.DigiSim/.idea/.gitignore
generated
vendored
Normal 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/
|
||||
7
C#/DigiSim/.idea/.idea.DigiSim/.idea/discord.xml
generated
Normal file
7
C#/DigiSim/.idea/.idea.DigiSim/.idea/discord.xml
generated
Normal 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>
|
||||
4
C#/DigiSim/.idea/.idea.DigiSim/.idea/encodings.xml
generated
Normal file
4
C#/DigiSim/.idea/.idea.DigiSim/.idea/encodings.xml
generated
Normal 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>
|
||||
8
C#/DigiSim/.idea/.idea.DigiSim/.idea/indexLayout.xml
generated
Normal file
8
C#/DigiSim/.idea/.idea.DigiSim/.idea/indexLayout.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
||||
9
C#/DigiSim/.idea/.idea.DigiSim/.idea/markdown.xml
generated
Normal file
9
C#/DigiSim/.idea/.idea.DigiSim/.idea/markdown.xml
generated
Normal 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>
|
||||
6
C#/DigiSim/.idea/.idea.DigiSim/.idea/misc.xml
generated
Normal file
6
C#/DigiSim/.idea/.idea.DigiSim/.idea/misc.xml
generated
Normal 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>
|
||||
6
C#/DigiSim/.idea/.idea.DigiSim/.idea/vcs.xml
generated
Normal file
6
C#/DigiSim/.idea/.idea.DigiSim/.idea/vcs.xml
generated
Normal 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
6
C#/DigiSim/App.config
Normal 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
9
C#/DigiSim/App.xaml
Normal 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
6
C#/DigiSim/App.xaml.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace DigiSim {
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App { }
|
||||
}
|
||||
100
C#/DigiSim/ConsoleManager.cs
Normal file
100
C#/DigiSim/ConsoleManager.cs
Normal 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
100
C#/DigiSim/DigiSim.csproj
Normal 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
16
C#/DigiSim/DigiSim.sln
Normal 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
|
||||
39
C#/DigiSim/Logic/ButtonInput.cs
Normal file
39
C#/DigiSim/Logic/ButtonInput.cs
Normal 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
308
C#/DigiSim/Logic/Gate.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/AndGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/AndGate.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
142
C#/DigiSim/Logic/Gates/CustomGate.cs
Normal file
142
C#/DigiSim/Logic/Gates/CustomGate.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/NandGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/NandGate.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/NorGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/NorGate.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
C#/DigiSim/Logic/Gates/NotGate.cs
Normal file
25
C#/DigiSim/Logic/Gates/NotGate.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/OrGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/OrGate.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/XnorGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/XnorGate.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/XorGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/XorGate.cs
Normal 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
34
C#/DigiSim/Logic/Input.cs
Normal 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) { }
|
||||
}
|
||||
}
|
||||
26
C#/DigiSim/Logic/Output.cs
Normal file
26
C#/DigiSim/Logic/Output.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
C#/DigiSim/Logic/Splitter.cs
Normal file
27
C#/DigiSim/Logic/Splitter.cs
Normal 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
74
C#/DigiSim/Logic/Wire.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
55
C#/DigiSim/Properties/AssemblyInfo.cs
Normal file
55
C#/DigiSim/Properties/AssemblyInfo.cs
Normal 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")]
|
||||
61
C#/DigiSim/Properties/Resources.Designer.cs
generated
Normal file
61
C#/DigiSim/Properties/Resources.Designer.cs
generated
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
117
C#/DigiSim/Properties/Resources.resx
Normal file
117
C#/DigiSim/Properties/Resources.resx
Normal 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
199
C#/DigiSim/Window.xaml
Normal 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
126
C#/DigiSim/Window.xaml.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user