diff --git a/.gitignore b/.gitignore
index f1999043..adfc297c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -112,6 +112,10 @@ AppPackages/
# VSCode
.vscode/
+.ionide/
+
+# JetBrains IDE
+.idea/
# Others
sql/
diff --git a/.paket/Paket.Restore.targets b/.paket/Paket.Restore.targets
index 52f41c60..8d37e28b 100644
--- a/.paket/Paket.Restore.targets
+++ b/.paket/Paket.Restore.targets
@@ -5,6 +5,11 @@
$(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+
+ $(MSBuildVersion)
+ 15.0.0
+ false
+ true
true
$(MSBuildThisFileDirectory)
@@ -15,7 +20,7 @@
proj
assembly
native
- /Library/Frameworks/Mono.framework/Commands/mono
+ /Library/Frameworks/Mono.framework/Commands/mono
mono
@@ -23,90 +28,135 @@
$(PaketToolsPath)paket.bootstrapper.exe
$([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\
-
+ "$(PaketBootStrapperExePath)"
+ $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)"
-
- $(PaketRootPath)paket.exe
- $(PaketToolsPath)paket.exe
- $(PaketToolsPath)paket.exe
- $(_PaketBootStrapperExeDir)paket.exe
- paket.exe
+
+
+
+ true
+ true
-
- $(PaketRootPath)paket
- $(PaketToolsPath)paket
- $(PaketToolsPath)paket
+
+ True
-
- $(PaketRootPath)paket.exe
- $(PaketToolsPath)paket.exe
+
+ False
-
- $(PaketBootStrapperExeDir)paket.exe
+ $(BaseIntermediateOutputPath.TrimEnd('\').TrimEnd('\/'))
+
-
- paket
+
+
+
+
+
+
+ $(PaketRootPath)paket
+ $(PaketToolsPath)paket
+
-
- <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)"))
- dotnet "$(PaketExePath)"
- $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"
- "$(PaketExePath)"
+
+
+
+ $(PaketRootPath)paket.exe
+ $(PaketToolsPath)paket.exe
+
+
+
+
+ <_DotnetToolsJson Condition="Exists('$(PaketRootPath)/.config/dotnet-tools.json')">$([System.IO.File]::ReadAllText("$(PaketRootPath)/.config/dotnet-tools.json"))
+ <_ConfigContainsPaket Condition=" '$(_DotnetToolsJson)' != ''">$(_DotnetToolsJson.Contains('"paket"'))
+ <_ConfigContainsPaket Condition=" '$(_ConfigContainsPaket)' == ''">false
+
- "$(PaketBootStrapperExePath)"
- $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)"
+
+
+
+
+
-
-
-
- true
- true
+
+
+ <_PaketCommand>dotnet paket
+
-
- True
-
+
+
+
+ $(PaketToolsPath)paket
+ $(PaketBootStrapperExeDir)paket
+
+
+ paket
+
+
+
+
+ <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)"))
+ <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)"
+ <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"
+ <_PaketCommand Condition=" '$(_PaketCommand)' == '' ">"$(PaketExePath)"
+
+
+
+
+
+
+
+
-
+
+
+
+
-
+
true
$(NoWarn);NU1603;NU1604;NU1605;NU1608
+ false
+ true
-
-
- /usr/bin/shasum "$(PaketRestoreCacheFile)" | /usr/bin/awk '{ print $1 }'
- /usr/bin/shasum "$(PaketLockFilePath)" | /usr/bin/awk '{ print $1 }'
+
+
+
+
+
+
+ $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)'))
+
+
+
+
+
+
+ $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[0].Replace(`"`, ``).Replace(` `, ``))
+ $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[1].Replace(`"`, ``).Replace(` `, ``))
+
+
+
+
+ %(PaketRestoreCachedKeyValue.Value)
+ %(PaketRestoreCachedKeyValue.Value)
-
-
-
-
-
-
-
-
-
-
-
-
-
- $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)'))
- $([System.IO.File]::ReadAllText('$(PaketLockFilePath)'))
+
+
true
- false
+ false
true
-
@@ -114,19 +164,22 @@
+
+
-
+
+
-
+
-
+
- $(MSBuildProjectDirectory)\obj\$(MSBuildProjectFile).paket.references.cached
+ $(PaketIntermediateOutputPath)\$(MSBuildProjectFile).paket.references.cached
$(MSBuildProjectFullPath).paket.references
@@ -161,8 +214,9 @@
-
-
+
+
+
@@ -182,7 +236,7 @@
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4])
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])
+ $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])
%(PaketReferencesFileLinesInfo.PackageVersion)
@@ -195,7 +249,7 @@
- $(MSBuildProjectDirectory)/obj/$(MSBuildProjectFile).paket.clitools
+ $(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools
@@ -214,22 +268,20 @@
-
+
false
- $(MSBuildVersion)
- 15.8.0
-
+
- <_NuspecFilesNewLocation Include="$(BaseIntermediateOutputPath)$(Configuration)\*.nuspec"/>
+ <_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/>
@@ -237,27 +289,78 @@
$(MSBuildProjectDirectory)/$(MSBuildProjectFile)
true
+ false
+ true
false
- true
+ true
false
- true
+ true
false
- true
- $(BaseIntermediateOutputPath)$(Configuration)
- $(BaseIntermediateOutputPath)
+ true
+ $(PaketIntermediateOutputPath)\$(Configuration)
+ $(PaketIntermediateOutputPath)
- <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.nuspec"/>
+ <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion.Split(`+`)[0]).nuspec"/>
-
+
+
+
+
+
= net461
nuget Newtonsoft.Json
+nuget System.Windows.Interactivity.WPF
+nuget Expression.Interaction
nuget System.Xml.XmlDocument
-
group Tests
framework: net461
source https://api.nuget.org/v3/index.json
nuget NSubstitute
-nuget NUnit redirects: force
+nuget NUnit
nuget NUnit3TestAdapter
-nuget FsUnit
+nuget FsUnit redirects: force
group TestRunners
@@ -35,7 +37,6 @@ source https://api.nuget.org/v3/index.json
nuget NUnit.Console
-
group FakeBuild
framework: netstandard2.0
diff --git a/paket.lock b/paket.lock
index 06303d2b..6df725b2 100644
--- a/paket.lock
+++ b/paket.lock
@@ -1,19 +1,22 @@
RESTRICTION: == net461
NUGET
remote: https://api.nuget.org/v3/index.json
- dotnet-fake (5.13) - clitool: true
- FSharp.Core (4.6.2) - redirects: force
+ dotnet-fake (5.18.3) - clitool: true
+ Expression.Interaction (3.0.40218)
+ FSharp.Core (4.7) - redirects: force
GraphX (2.3.6)
QuickGraphPCL
+ log4net (2.0.8)
Microsoft.Msagl (1.0.2)
Microsoft.Msagl.Drawing (1.0.2)
Microsoft.Msagl (>= 1.0.2)
Microsoft.Msagl.GraphViewerGDI (1.0.2)
Microsoft.Msagl.Drawing (>= 1.0.2)
- Newtonsoft.Json (12.0.1)
+ Newtonsoft.Json (12.0.3)
QuickGraphPCL (3.6.61114.2)
- StyleCop.Analyzers (1.0.2)
- System.ValueTuple (4.5)
+ StyleCop.Analyzers (1.1.118)
+ System.ValueTuple (4.4)
+ System.Windows.Interactivity.WPF (2.0.20525)
System.Xml.XmlDocument (4.3)
GROUP FakeBuild
@@ -23,127 +26,125 @@ NUGET
remote: https://api.nuget.org/v3/index.json
BlackFox.VsWhere (1.0)
FSharp.Core (>= 4.2.3)
- Fake.Core.CommandLineParsing (5.13)
+ Fake.Core.CommandLineParsing (5.19)
FParsec (>= 1.0.3)
- FSharp.Core (>= 4.3.4)
- Fake.Core.Context (5.13)
- FSharp.Core (>= 4.3.4)
- Fake.Core.Environment (5.13)
- FSharp.Core (>= 4.3.4)
- Fake.Core.FakeVar (5.13)
- Fake.Core.Context (>= 5.13)
- FSharp.Core (>= 4.3.4)
- Fake.Core.Process (5.13)
- Fake.Core.Environment (>= 5.13)
- Fake.Core.FakeVar (>= 5.13)
- Fake.Core.String (>= 5.13)
- Fake.Core.Trace (>= 5.13)
- Fake.IO.FileSystem (>= 5.13)
- FSharp.Core (>= 4.3.4)
+ FSharp.Core (>= 4.7)
+ Fake.Core.Context (5.19)
+ FSharp.Core (>= 4.7)
+ Fake.Core.Environment (5.19)
+ FSharp.Core (>= 4.7)
+ Fake.Core.FakeVar (5.19)
+ Fake.Core.Context (>= 5.19)
+ FSharp.Core (>= 4.7)
+ Fake.Core.Process (5.19)
+ Fake.Core.Environment (>= 5.19)
+ Fake.Core.FakeVar (>= 5.19)
+ Fake.Core.String (>= 5.19)
+ Fake.Core.Trace (>= 5.19)
+ Fake.IO.FileSystem (>= 5.19)
+ FSharp.Core (>= 4.7)
System.Diagnostics.Process (>= 4.3)
- Fake.Core.ReleaseNotes (5.13)
- Fake.Core.SemVer (>= 5.13)
- Fake.Core.String (>= 5.13)
- FSharp.Core (>= 4.3.4)
- Fake.Core.SemVer (5.13)
- FSharp.Core (>= 4.3.4)
+ Fake.Core.ReleaseNotes (5.19)
+ Fake.Core.SemVer (>= 5.19)
+ Fake.Core.String (>= 5.19)
+ FSharp.Core (>= 4.7)
+ Fake.Core.SemVer (5.19)
+ FSharp.Core (>= 4.7)
System.Runtime.Numerics (>= 4.3)
- Fake.Core.String (5.13)
- FSharp.Core (>= 4.3.4)
- Fake.Core.Target (5.13)
- Fake.Core.CommandLineParsing (>= 5.13)
- Fake.Core.Context (>= 5.13)
- Fake.Core.Environment (>= 5.13)
- Fake.Core.FakeVar (>= 5.13)
- Fake.Core.Process (>= 5.13)
- Fake.Core.String (>= 5.13)
- Fake.Core.Trace (>= 5.13)
+ Fake.Core.String (5.19)
+ FSharp.Core (>= 4.7)
+ Fake.Core.Target (5.19)
+ Fake.Core.CommandLineParsing (>= 5.19)
+ Fake.Core.Context (>= 5.19)
+ Fake.Core.Environment (>= 5.19)
+ Fake.Core.FakeVar (>= 5.19)
+ Fake.Core.Process (>= 5.19)
+ Fake.Core.String (>= 5.19)
+ Fake.Core.Trace (>= 5.19)
FSharp.Control.Reactive (>= 4.2)
- FSharp.Core (>= 4.3.4)
- System.Reactive.Compatibility (>= 4.1.5)
- Fake.Core.Trace (5.13)
- Fake.Core.Environment (>= 5.13)
- Fake.Core.FakeVar (>= 5.13)
- FSharp.Core (>= 4.3.4)
- Fake.DotNet.AssemblyInfoFile (5.13)
- Fake.Core.Environment (>= 5.13)
- Fake.Core.String (>= 5.13)
- Fake.Core.Trace (>= 5.13)
- Fake.IO.FileSystem (>= 5.13)
- FSharp.Core (>= 4.3.4)
- Fake.DotNet.MsBuild (5.13)
+ FSharp.Core (>= 4.7)
+ System.Reactive.Compatibility (>= 4.3.1)
+ Fake.Core.Trace (5.19)
+ Fake.Core.Environment (>= 5.19)
+ Fake.Core.FakeVar (>= 5.19)
+ FSharp.Core (>= 4.7)
+ Fake.DotNet.AssemblyInfoFile (5.19)
+ Fake.Core.Environment (>= 5.19)
+ Fake.Core.String (>= 5.19)
+ Fake.Core.Trace (>= 5.19)
+ Fake.IO.FileSystem (>= 5.19)
+ FSharp.Core (>= 4.7)
+ Fake.DotNet.MsBuild (5.19)
BlackFox.VsWhere (>= 1.0)
- Fake.Core.Environment (>= 5.13)
- Fake.Core.Process (>= 5.13)
- Fake.Core.String (>= 5.13)
- Fake.Core.Trace (>= 5.13)
- Fake.IO.FileSystem (>= 5.13)
- FSharp.Core (>= 4.3.4)
- MSBuild.StructuredLogger (>= 2.0.88)
- Fake.DotNet.Testing.NUnit (5.13)
- Fake.Core.Environment (>= 5.13)
- Fake.Core.Process (>= 5.13)
- Fake.Core.String (>= 5.13)
- Fake.Core.Trace (>= 5.13)
- Fake.IO.FileSystem (>= 5.13)
- Fake.Testing.Common (>= 5.13)
- FSharp.Core (>= 4.3.4)
+ Fake.Core.Environment (>= 5.19)
+ Fake.Core.Process (>= 5.19)
+ Fake.Core.String (>= 5.19)
+ Fake.Core.Trace (>= 5.19)
+ Fake.IO.FileSystem (>= 5.19)
+ FSharp.Core (>= 4.7)
+ MSBuild.StructuredLogger (>= 2.0.152)
+ Fake.DotNet.Testing.NUnit (5.19)
+ Fake.Core.Environment (>= 5.19)
+ Fake.Core.Process (>= 5.19)
+ Fake.Core.String (>= 5.19)
+ Fake.Core.Trace (>= 5.19)
+ Fake.IO.FileSystem (>= 5.19)
+ Fake.Testing.Common (>= 5.19)
+ FSharp.Core (>= 4.7)
System.Linq.Parallel (>= 4.3)
System.Xml.XDocument (>= 4.3)
- Fake.IO.FileSystem (5.13)
- Fake.Core.String (>= 5.13)
- FSharp.Core (>= 4.3.4)
+ Fake.IO.FileSystem (5.19)
+ Fake.Core.String (>= 5.19)
+ FSharp.Core (>= 4.7)
System.Diagnostics.FileVersionInfo (>= 4.3)
System.IO.FileSystem.Watcher (>= 4.3)
- Fake.Testing.Common (5.13)
- Fake.Core.Trace (>= 5.13)
+ Fake.Testing.Common (5.19)
+ Fake.Core.Trace (>= 5.19)
+ FSharp.Core (>= 4.7)
+ FParsec (1.1.1)
FSharp.Core (>= 4.3.4)
- FParsec (1.0.3)
- FSharp.Core (>= 4.2.3)
- NETStandard.Library (>= 1.6.1)
FSharp.Control.Reactive (4.2)
FSharp.Core (>= 4.2.3)
System.Reactive (>= 4.0)
- FSharp.Core (4.6.2)
- Microsoft.Build (16.0.461)
- Microsoft.Build.Framework (16.0.461)
+ FSharp.Core (4.7)
+ Microsoft.Build (16.4)
+ Microsoft.Build.Framework (16.4)
System.Runtime.Serialization.Primitives (>= 4.1.1)
System.Threading.Thread (>= 4.0)
- Microsoft.Build.Tasks.Core (16.0.461)
- Microsoft.Build.Framework (>= 16.0.461)
- Microsoft.Build.Utilities.Core (>= 16.0.461)
+ Microsoft.Build.Tasks.Core (16.4)
+ Microsoft.Build.Framework (>= 16.4)
+ Microsoft.Build.Utilities.Core (>= 16.4)
Microsoft.Win32.Registry (>= 4.3)
System.CodeDom (>= 4.4)
System.Collections.Immutable (>= 1.5)
System.Linq.Parallel (>= 4.0.1)
- System.Net.Http (>= 4.3)
+ System.Net.Http (>= 4.3.4)
System.Reflection.Metadata (>= 1.6)
System.Reflection.TypeExtensions (>= 4.1)
+ System.Resources.Extensions (>= 4.6)
System.Resources.Writer (>= 4.0)
- System.Threading.Tasks.Dataflow (>= 4.6)
- Microsoft.Build.Utilities.Core (16.0.461)
- Microsoft.Build.Framework (>= 16.0.461)
+ System.Threading.Tasks.Dataflow (>= 4.9)
+ Microsoft.Build.Utilities.Core (16.4)
+ Microsoft.Build.Framework (>= 16.4)
Microsoft.Win32.Registry (>= 4.3)
System.Collections.Immutable (>= 1.5)
System.Text.Encoding.CodePages (>= 4.0.1)
- Microsoft.NETCore.Platforms (2.2)
- Microsoft.NETCore.Targets (2.1)
+ Microsoft.NETCore.Platforms (3.1)
+ Microsoft.NETCore.Targets (3.1)
Microsoft.Win32.Primitives (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
System.Runtime (>= 4.3)
- Microsoft.Win32.Registry (4.5)
- System.Buffers (>= 4.4)
- System.Memory (>= 4.5)
- System.Security.AccessControl (>= 4.5)
- System.Security.Principal.Windows (>= 4.5)
- MSBuild.StructuredLogger (2.0.88)
+ Microsoft.Win32.Registry (4.7)
+ System.Buffers (>= 4.5)
+ System.Memory (>= 4.5.3)
+ System.Security.AccessControl (>= 4.7)
+ System.Security.Principal.Windows (>= 4.7)
+ MSBuild.StructuredLogger (2.0.174)
Microsoft.Build (>= 15.8.166)
Microsoft.Build.Framework (>= 15.8.166)
Microsoft.Build.Tasks.Core (>= 15.8.166)
Microsoft.Build.Utilities.Core (>= 15.8.166)
- NETStandard.Library (2.0.3)
- Microsoft.NETCore.Platforms (>= 1.1)
runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
@@ -185,7 +186,7 @@ NUGET
runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
System.Buffers (4.5)
- System.CodeDom (4.5)
+ System.CodeDom (4.7)
System.Collections (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
@@ -201,12 +202,14 @@ NUGET
System.Runtime.Extensions (>= 4.3)
System.Threading (>= 4.3)
System.Threading.Tasks (>= 4.3)
- System.Collections.Immutable (1.5)
+ System.Collections.Immutable (1.7)
+ System.Memory (>= 4.5.3)
System.Diagnostics.Debug (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
System.Runtime (>= 4.3)
- System.Diagnostics.DiagnosticSource (4.5.1)
+ System.Diagnostics.DiagnosticSource (4.7)
+ System.Memory (>= 4.5.3)
System.Diagnostics.FileVersionInfo (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
System.Globalization (>= 4.3)
@@ -314,7 +317,7 @@ NUGET
System.Runtime.Extensions (>= 4.3)
System.Threading (>= 4.3)
System.Threading.Tasks (>= 4.3)
- System.Memory (4.5.2)
+ System.Memory (4.5.3)
System.Buffers (>= 4.4)
System.Numerics.Vectors (>= 4.4)
System.Runtime.CompilerServices.Unsafe (>= 4.5.2)
@@ -345,49 +348,51 @@ NUGET
System.Text.Encoding (>= 4.3)
System.Threading (>= 4.3)
System.Threading.Tasks (>= 4.3)
- System.Net.Primitives (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
+ System.Net.Primitives (4.3.1)
+ Microsoft.NETCore.Platforms (>= 1.1.1)
+ Microsoft.NETCore.Targets (>= 1.1.3)
+ System.Runtime (>= 4.3.1)
System.Runtime.Handles (>= 4.3)
System.Numerics.Vectors (4.5)
- System.Reactive (4.1.5)
+ System.Reactive (4.3.2)
System.Runtime.InteropServices.WindowsRuntime (>= 4.3)
- System.Threading.Tasks.Extensions (>= 4.5.2)
- System.Reactive.Compatibility (4.1.5)
- System.Reactive.Core (>= 4.1.5)
- System.Reactive.Interfaces (>= 4.1.5)
- System.Reactive.Linq (>= 4.1.5)
- System.Reactive.PlatformServices (>= 4.1.5)
- System.Reactive.Providers (>= 4.1.5)
- System.Reactive.Core (4.1.5)
- System.Reactive (>= 4.1.5)
- System.Threading.Tasks.Extensions (>= 4.5.2)
- System.Reactive.Interfaces (4.1.5)
- System.Reactive (>= 4.1.5)
- System.Threading.Tasks.Extensions (>= 4.5.2)
- System.Reactive.Linq (4.1.5)
- System.Reactive (>= 4.1.5)
- System.Threading.Tasks.Extensions (>= 4.5.2)
- System.Reactive.PlatformServices (4.1.5)
- System.Reactive (>= 4.1.5)
- System.Threading.Tasks.Extensions (>= 4.5.2)
- System.Reactive.Providers (4.1.5)
- System.Reactive (>= 4.1.5)
- System.Threading.Tasks.Extensions (>= 4.5.2)
+ System.Threading.Tasks.Extensions (>= 4.5.3)
+ System.Reactive.Compatibility (4.3.2)
+ System.Reactive.Core (>= 4.3.2)
+ System.Reactive.Interfaces (>= 4.3.2)
+ System.Reactive.Linq (>= 4.3.2)
+ System.Reactive.PlatformServices (>= 4.3.2)
+ System.Reactive.Providers (>= 4.3.2)
+ System.Reactive.Core (4.3.2)
+ System.Reactive (>= 4.3.2)
+ System.Threading.Tasks.Extensions (>= 4.5.3)
+ System.Reactive.Interfaces (4.3.2)
+ System.Reactive (>= 4.3.2)
+ System.Threading.Tasks.Extensions (>= 4.5.3)
+ System.Reactive.Linq (4.3.2)
+ System.Reactive (>= 4.3.2)
+ System.Threading.Tasks.Extensions (>= 4.5.3)
+ System.Reactive.PlatformServices (4.3.2)
+ System.Reactive (>= 4.3.2)
+ System.Threading.Tasks.Extensions (>= 4.5.3)
+ System.Reactive.Providers (4.3.2)
+ System.Reactive (>= 4.3.2)
+ System.Threading.Tasks.Extensions (>= 4.5.3)
System.Reflection (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
System.IO (>= 4.3)
System.Reflection.Primitives (>= 4.3)
System.Runtime (>= 4.3)
- System.Reflection.Metadata (1.6)
- System.Collections.Immutable (>= 1.5)
+ System.Reflection.Metadata (1.8)
+ System.Collections.Immutable (>= 1.7)
System.Reflection.Primitives (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
System.Runtime (>= 4.3)
- System.Reflection.TypeExtensions (4.5.1)
+ System.Reflection.TypeExtensions (4.7)
+ System.Resources.Extensions (4.7)
+ System.Memory (>= 4.5.3)
System.Resources.ResourceManager (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
@@ -404,7 +409,7 @@ NUGET
System.Runtime (4.3.1)
Microsoft.NETCore.Platforms (>= 1.1.1)
Microsoft.NETCore.Targets (>= 1.1.3)
- System.Runtime.CompilerServices.Unsafe (4.5.2)
+ System.Runtime.CompilerServices.Unsafe (4.7)
System.Runtime.Extensions (4.3.1)
Microsoft.NETCore.Platforms (>= 1.1.1)
Microsoft.NETCore.Targets (>= 1.1.3)
@@ -430,8 +435,8 @@ NUGET
System.Runtime.Serialization.Primitives (4.3)
System.Resources.ResourceManager (>= 4.3)
System.Runtime (>= 4.3)
- System.Security.AccessControl (4.5)
- System.Security.Principal.Windows (>= 4.5)
+ System.Security.AccessControl (4.7)
+ System.Security.Principal.Windows (>= 4.7)
System.Security.Cryptography.Algorithms (4.3.1)
Microsoft.NETCore.Platforms (>= 1.1)
runtime.native.System.Security.Cryptography.Apple (>= 4.3.1)
@@ -447,7 +452,7 @@ NUGET
System.Security.Cryptography.Encoding (>= 4.3)
System.Security.Cryptography.Primitives (>= 4.3)
System.Text.Encoding (>= 4.3)
- System.Security.Cryptography.Cng (4.5)
+ System.Security.Cryptography.Cng (4.7)
System.Security.Cryptography.Csp (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
System.IO (>= 4.3)
@@ -475,7 +480,7 @@ NUGET
System.Runtime.InteropServices (>= 4.3)
System.Security.Cryptography.Primitives (>= 4.3)
System.Text.Encoding (>= 4.3)
- System.Security.Cryptography.OpenSsl (4.5.1)
+ System.Security.Cryptography.OpenSsl (4.7)
System.Security.Cryptography.Primitives (4.3)
System.Diagnostics.Debug (>= 4.3)
System.Globalization (>= 4.3)
@@ -510,24 +515,24 @@ NUGET
System.Security.Cryptography.Primitives (>= 4.3)
System.Text.Encoding (>= 4.3)
System.Threading (>= 4.3)
- System.Security.Principal.Windows (4.5.1)
+ System.Security.Principal.Windows (4.7)
System.Text.Encoding (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
System.Runtime (>= 4.3)
- System.Text.Encoding.CodePages (4.5.1)
- System.Runtime.CompilerServices.Unsafe (>= 4.5.2)
+ System.Text.Encoding.CodePages (4.7)
+ System.Runtime.CompilerServices.Unsafe (>= 4.7)
System.Text.Encoding.Extensions (4.3)
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
System.Runtime (>= 4.3)
System.Text.Encoding (>= 4.3)
- System.Text.RegularExpressions (4.3)
+ System.Text.RegularExpressions (4.3.1)
System.Collections (>= 4.3)
System.Globalization (>= 4.3)
System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
+ System.Runtime (>= 4.3.1)
+ System.Runtime.Extensions (>= 4.3.1)
System.Threading (>= 4.3)
System.Threading (4.3)
System.Runtime (>= 4.3)
@@ -541,8 +546,8 @@ NUGET
Microsoft.NETCore.Platforms (>= 1.1)
Microsoft.NETCore.Targets (>= 1.1)
System.Runtime (>= 4.3)
- System.Threading.Tasks.Dataflow (4.9)
- System.Threading.Tasks.Extensions (4.5.2)
+ System.Threading.Tasks.Dataflow (4.11)
+ System.Threading.Tasks.Extensions (4.5.3)
System.Runtime.CompilerServices.Unsafe (>= 4.5.2)
System.Threading.Thread (4.3)
System.Runtime (>= 4.3)
@@ -592,9 +597,9 @@ NUGET
NUnit.Extension.VSProjectLoader (>= 3.8)
NUnit.ConsoleRunner (3.10)
NUnit.Extension.NUnitProjectLoader (3.6)
- NUnit.Extension.NUnitV2Driver (3.7)
+ NUnit.Extension.NUnitV2Driver (3.8)
NUnit.Extension.NUnitV2ResultWriter (3.6)
- NUnit.Extension.TeamCityEventListener (1.0.6)
+ NUnit.Extension.TeamCityEventListener (1.0.7)
NUnit.Extension.VSProjectLoader (3.8)
GROUP Tests
@@ -602,15 +607,15 @@ RESTRICTION: == net461
NUGET
remote: https://api.nuget.org/v3/index.json
Castle.Core (4.4)
- FSharp.Core (4.6.2)
- FsUnit (3.4)
+ FSharp.Core (4.7) - redirects: force
+ FsUnit (3.8) - redirects: force
FSharp.Core (>= 4.2.3)
- NUnit (>= 3.11 < 4.0)
- NSubstitute (4.0)
- Castle.Core (>= 4.3.1)
+ NUnit (>= 3.12 < 4.0)
+ NSubstitute (4.2.1)
+ Castle.Core (>= 4.4)
System.Threading.Tasks.Extensions (>= 4.3)
- NUnit (3.11) - redirects: force
- NUnit3TestAdapter (3.13)
- System.Runtime.CompilerServices.Unsafe (4.5.2)
- System.Threading.Tasks.Extensions (4.5.2)
+ NUnit (3.12)
+ NUnit3TestAdapter (3.16.1)
+ System.Runtime.CompilerServices.Unsafe (4.7)
+ System.Threading.Tasks.Extensions (4.5.3)
System.Runtime.CompilerServices.Unsafe (>= 4.5.2)
diff --git a/paket.references b/paket.references
index 999041f6..b4fe1b99 100644
--- a/paket.references
+++ b/paket.references
@@ -1 +1,2 @@
-dotnet-fake
\ No newline at end of file
+FSharp.Core
+System.ValueTuple
\ No newline at end of file
diff --git a/src/AirSim/AirSimLib/CodeExecution.cs b/src/AirSim/AirSimLib/CodeExecution.cs
index d4776ec9..4a40d889 100644
--- a/src/AirSim/AirSimLib/CodeExecution.cs
+++ b/src/AirSim/AirSimLib/CodeExecution.cs
@@ -14,12 +14,12 @@
namespace AirSim.AirSimLib
{
+ using Repo;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
- using Repo;
///
/// Class for execution of visual program on AirSim
diff --git a/src/AirSim/AirSimLib/MultirotorClient.cs b/src/AirSim/AirSimLib/MultirotorClient.cs
index 630723b3..b6636df9 100644
--- a/src/AirSim/AirSimLib/MultirotorClient.cs
+++ b/src/AirSim/AirSimLib/MultirotorClient.cs
@@ -16,9 +16,7 @@ namespace AirSim.AirSimLib
{
using System;
using System.Drawing;
- using System.IO;
using System.Runtime.InteropServices;
- using Microsoft.Win32.SafeHandles;
///
/// DLL library wrapper
diff --git a/src/AirSim/App.config b/src/AirSim/App.config
index c077b6dd..1afd8421 100644
--- a/src/AirSim/App.config
+++ b/src/AirSim/App.config
@@ -7,6 +7,6 @@
True
-
+
diff --git a/src/AirSim/View/MainWindow.xaml.cs b/src/AirSim/View/MainWindow.xaml.cs
index 83e1b3ec..9dc74a86 100644
--- a/src/AirSim/View/MainWindow.xaml.cs
+++ b/src/AirSim/View/MainWindow.xaml.cs
@@ -14,16 +14,16 @@
namespace AirSim.View
{
+ using AirSimLib;
+ using EditorPluginInterfaces;
+ using PluginManager;
+ using Repo;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
- using AirSimLib;
- using EditorPluginInterfaces;
- using PluginManager;
- using Repo;
using WpfControlsLib.Controls.Console;
using WpfControlsLib.Controls.ModelSelector;
using WpfControlsLib.Controls.Scene;
@@ -34,7 +34,7 @@ namespace AirSim.View
///
internal partial class MainWindow
{
- private readonly WpfControlsLib.Model.Model model = new WpfControlsLib.Model.Model();
+ private readonly WpfControlsLib.Model.SceneModel model = new WpfControlsLib.Model.SceneModel();
private readonly WpfControlsLib.Controller.Controller controller = new WpfControlsLib.Controller.Controller();
public AppConsoleViewModel Console { get; } = new AppConsoleViewModel();
diff --git a/src/EditorPluginInterfaces/EdgeEventArgs.cs b/src/EditorPluginInterfaces/EdgeEventArgs.cs
index a1e79d32..d5a107e0 100644
--- a/src/EditorPluginInterfaces/EdgeEventArgs.cs
+++ b/src/EditorPluginInterfaces/EdgeEventArgs.cs
@@ -11,8 +11,11 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. */
-
- namespace EditorPluginInterfaces
+
+using Repo;
+using Repo.FacadeLayer;
+
+namespace EditorPluginInterfaces
{
using System;
@@ -21,6 +24,13 @@ namespace EditorPluginInterfaces
///
public class EdgeEventArgs : EventArgs
{
+ public EdgeEventArgs(IEdge edge, IElement source = null, IElement target = null)
+ {
+ Edge = edge;
+ Source = source;
+ Target = target;
+ }
+
///
/// Metatype of an edge.
/// TODO: Nobody cares about metatype, give us actual created edge!
diff --git a/src/EditorPluginInterfaces/EditorPluginInterfaces.csproj b/src/EditorPluginInterfaces/EditorPluginInterfaces.csproj
index c52affd8..93f79a8c 100644
--- a/src/EditorPluginInterfaces/EditorPluginInterfaces.csproj
+++ b/src/EditorPluginInterfaces/EditorPluginInterfaces.csproj
@@ -60,7 +60,7 @@
-
+
diff --git a/src/EditorPluginInterfaces/ElementEventArgs.cs b/src/EditorPluginInterfaces/ElementEventArgs.cs
index 783c1d6c..20a4ced6 100644
--- a/src/EditorPluginInterfaces/ElementEventArgs.cs
+++ b/src/EditorPluginInterfaces/ElementEventArgs.cs
@@ -21,11 +21,17 @@ namespace EditorPluginInterfaces
///
public class ElementEventArgs : EventArgs
{
+ public ElementEventArgs(Repo.IElement element, bool isAllowed = false)
+ {
+ this.Element = element;
+ this.IsAllowed = isAllowed;
+ }
+
///
/// Element.
///
- public Repo.IElement Element { get; set; }
+ public Repo.IElement Element { get; }
- public bool IsAllowed { get; set; }
+ public bool IsAllowed { get; }
}
}
\ No newline at end of file
diff --git a/src/EditorPluginInterfaces/IScene.cs b/src/EditorPluginInterfaces/IScene.cs
index 5ba5fff8..110ffb5f 100644
--- a/src/EditorPluginInterfaces/IScene.cs
+++ b/src/EditorPluginInterfaces/IScene.cs
@@ -11,8 +11,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. */
-
- namespace EditorPluginInterfaces
+
+namespace EditorPluginInterfaces
{
///
/// Abstraction of editor's scene
diff --git a/src/EditorPluginInterfaces/IModel.cs b/src/EditorPluginInterfaces/ISceneModel.cs
similarity index 50%
rename from src/EditorPluginInterfaces/IModel.cs
rename to src/EditorPluginInterfaces/ISceneModel.cs
index ef39c52e..6fcaaaea 100644
--- a/src/EditorPluginInterfaces/IModel.cs
+++ b/src/EditorPluginInterfaces/ISceneModel.cs
@@ -12,6 +12,9 @@
* See the License for the specific language governing permissions and
* limitations under the License. */
+using Repo;
+using Repo.Visual;
+
namespace EditorPluginInterfaces
{
using System;
@@ -19,7 +22,7 @@ namespace EditorPluginInterfaces
///
/// Interface of a model in editor that allows to manipulate repository maintaining consistency with editor.
///
- public interface IModel
+ public interface ISceneModel
{
///
/// Model name.
@@ -36,6 +39,26 @@ public interface IModel
///
event EventHandler NewEdgeAdded;
+ ///
+ /// Element was deleted from model.
+ ///
+ event EventHandler ElementRemoved;
+
+ ///
+ /// Node's scene visual representation changed
+ ///
+ event EventHandler NodeVisualChanged;
+
+ ///
+ /// Edge's scene visual representation changed
+ ///
+ event EventHandler EdgeVisualChanged;
+
+ ///
+ /// Element that should be checked from model.
+ ///
+ event EventHandler ElementCheck;
+
///
/// Repository. Can be used for queries, but shall not be used for direct manipulation of a model.
///
@@ -44,21 +67,42 @@ public interface IModel
///
/// Creates a new node in a model.
///
- /// Metatype of created node.
- void CreateNode(Repo.IElement element);
+ /// Metatype of created node.
+ /// Position of node on scene.
+ Repo.INode CreateNode(Repo.IElement nodeType, Repo.VisualPoint position);
///
/// Creates a new edge in a model.
///
- /// Metatype of an edge.
+ /// Metatype of an edge.
/// Node that will be a source of an edge.
/// Node that will be destination of an edge.
- void CreateEdge(Repo.IEdge edge, Repo.IElement source, Repo.IElement destination);
+ Repo.IEdge CreateEdge(Repo.IEdge edgeType, Repo.IElement source, Repo.IElement destination);
+
+ ///
+ /// Restores element after this element being deleted.
+ ///
+ /// Element to restore.
+ void RestoreElement(Repo.IElement element);
///
- /// Removes an adge or node from a model.
+ /// Removes an edge or node from a model.
///
/// Element to remove from model.
void RemoveElement(Repo.IElement element);
+
+ ///
+ /// Notifies that visual representation of this node changed
+ ///
+ ///
+ ///
+ void UpdateNodeVisual(INode node, in IVisualNodeInfo nodeVisual);
+
+ ///
+ /// Notifies that visual representation of this node changed
+ ///
+ ///
+ ///
+ void UpdateEdgeVisual(IEdge edge, in IVisualEdgeInfo edgeVisual);
}
}
diff --git a/src/EditorPluginInterfaces/PluginConfig.cs b/src/EditorPluginInterfaces/PluginConfig.cs
index 31b591d9..df243659 100644
--- a/src/EditorPluginInterfaces/PluginConfig.cs
+++ b/src/EditorPluginInterfaces/PluginConfig.cs
@@ -11,12 +11,11 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. */
-
+
namespace EditorPluginInterfaces
{
using System;
using System.Windows.Controls;
- using Toolbar;
///
/// Plugins' configuration class
@@ -26,7 +25,7 @@ public class PluginConfig
///
/// Model of the editor, allows to manipulate repository and keep consistence with editor.
///
- public IModel Model { get; }
+ public ISceneModel Model { get; }
///
/// Scene's reference that should be given to plugin
@@ -79,7 +78,7 @@ public class PluginConfig
/// Palette
/// Grid where left panel elements are located. Empty by default, but plugins can
/// use it to add some new tools.
- public PluginConfig(IModel model, IScene scene, IToolbar toolbar, IConsole console, IPalette palette, Grid leftPanelGrid)
+ public PluginConfig(ISceneModel model, IScene scene, IToolbar toolbar, IConsole console, IPalette palette, Grid leftPanelGrid)
{
this.Model = model;
this.Scene = scene;
diff --git a/src/EditorPluginInterfaces/Toolbar/IToolbar.cs b/src/EditorPluginInterfaces/Toolbar/IToolbar.cs
index a62232a2..cdfc7159 100644
--- a/src/EditorPluginInterfaces/Toolbar/IToolbar.cs
+++ b/src/EditorPluginInterfaces/Toolbar/IToolbar.cs
@@ -1,6 +1,7 @@
-using System.Collections.Generic;
+using EditorPluginInterfaces.Toolbar;
+using System.Collections.Generic;
-namespace EditorPluginInterfaces.Toolbar
+namespace EditorPluginInterfaces
{
///
/// Interface that is abstraction of editor's toolbar
diff --git a/src/EditorPluginInterfaces/VertexEventArgs.cs b/src/EditorPluginInterfaces/VertexEventArgs.cs
index 690aee77..cc14b5c7 100644
--- a/src/EditorPluginInterfaces/VertexEventArgs.cs
+++ b/src/EditorPluginInterfaces/VertexEventArgs.cs
@@ -12,6 +12,8 @@
* See the License for the specific language governing permissions and
* limitations under the License. */
+using Repo;
+
namespace EditorPluginInterfaces
{
using System;
@@ -21,9 +23,14 @@ namespace EditorPluginInterfaces
///
public class VertexEventArgs : EventArgs
{
+ public VertexEventArgs(INode node)
+ {
+ this.Node = node;
+ }
+
///
/// Newly created node.
///
- public Repo.INode Node { get; set; }
+ public Repo.INode Node { get; }
}
}
diff --git a/src/EditorPluginInterfaces/app.config b/src/EditorPluginInterfaces/app.config
index 6c060a74..10b094f8 100644
--- a/src/EditorPluginInterfaces/app.config
+++ b/src/EditorPluginInterfaces/app.config
@@ -4,6 +4,6 @@
True
-
+
diff --git a/src/EditorPluginInterfaces/paket.references b/src/EditorPluginInterfaces/paket.references
new file mode 100644
index 00000000..e69de29b
diff --git a/src/Interpreters/AssemblyInfo.fs b/src/Interpreters/AssemblyInfo.fs
new file mode 100644
index 00000000..f2ec5dfd
--- /dev/null
+++ b/src/Interpreters/AssemblyInfo.fs
@@ -0,0 +1,41 @@
+namespace Interpreters.AssemblyInfo
+
+open System.Reflection
+open System.Runtime.CompilerServices
+open System.Runtime.InteropServices
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+
+// 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.
+[]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[]
+
+// 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:
+// []
+[]
+[]
+
+do
+ ()
\ No newline at end of file
diff --git a/src/Interpreters/Common/VariableList.fs b/src/Interpreters/Common/VariableList.fs
new file mode 100644
index 00000000..89f20b18
--- /dev/null
+++ b/src/Interpreters/Common/VariableList.fs
@@ -0,0 +1,48 @@
+module Interpreters.Common
+
+open Interpreters
+
+type VariableList(variables: Variable list) =
+ struct
+ new(variables: seq) = VariableList(Seq.toList variables)
+
+ interface IVariableSet with
+
+ member this.Add(v: Variable): IVariableSet =
+ VariableList(v :: variables) :> IVariableSet
+
+ member this.FindAllByName(name: string): Variable list =
+ List.filter (fun x -> x.Name = name) variables
+
+ member this.FindByName(name: string): Variable =
+ List.find (fun x-> x.Name = name) variables
+
+ member this.Remove(v: Variable): IVariableSet =
+ let rec remove v variables =
+ match variables with
+ | [] -> invalidOp "there is no such variable"
+ | h :: t when h = v -> t
+ | _ :: t -> remove v t
+ new VariableList(remove v variables) :> IVariableSet
+
+ member this.RemoveAll(v: Variable): IVariableSet =
+ new VariableList(List.filter ((=) v) variables) :> IVariableSet
+
+ member this.ChangeValue(v: Variable) (newValue: VariableValue): IVariableSet =
+ let rec change list result =
+ match list with
+ | h :: t ->
+ if v = h then (List.rev result) @ ((Variable.changeValue newValue v) :: t)
+ else change t (h :: result)
+ | [] -> invalidOp "there is no such variable"
+ new VariableList(change variables []) :> IVariableSet
+
+ member this.ChangeValueByName(name: string) (newValue: VariableValue): IVariableSet =
+ raise (System.NotImplementedException())
+
+ member this.Drop(): IVariableSet = new VariableList(variables.Tail) :> IVariableSet
+
+ member this.Filter filter = List.filter filter variables
+
+ member this.ToList: Variable list = variables
+ end
\ No newline at end of file
diff --git a/src/Interpreters/Exceptions.fs b/src/Interpreters/Exceptions.fs
new file mode 100644
index 00000000..f16805ac
--- /dev/null
+++ b/src/Interpreters/Exceptions.fs
@@ -0,0 +1,37 @@
+namespace Interpreters
+
+type ParserException(message: string, place: PlaceOfCreation) =
+ class
+ inherit System.Exception(message)
+
+ new(message) = new ParserException(message, PlaceOfCreation.empty)
+
+ member this.PlaceWhereRaised = place
+
+ member this.IsRaisedInModel =
+ match place with
+ | PlaceOfCreation(Some _, _) -> true
+ | _ -> false
+
+ member this.ModelWhereRaised =
+ match place with
+ | PlaceOfCreation(Some m, _) -> m
+ | _ -> invalidOp "No model"
+
+ member this.IsRaisedInElement =
+ match place with
+ | PlaceOfCreation(_, Some _) -> true
+ | _ -> false
+
+ member this.ElementWhereRaised =
+ match place with
+ | PlaceOfCreation(_, Some e) -> e
+ | _ -> invalidOp "No element"
+ end
+
+module ParserException =
+
+ let raiseException message = new ParserException(message) |> raise
+
+ let raiseWithPlace (message: string) (place: PlaceOfCreation) = new ParserException(message) |> raise
+
diff --git a/src/Interpreters/ExpressionParserBuilder.fs b/src/Interpreters/ExpressionParserBuilder.fs
new file mode 100644
index 00000000..7d3e3f69
--- /dev/null
+++ b/src/Interpreters/ExpressionParserBuilder.fs
@@ -0,0 +1,16 @@
+namespace Interpreters.Expressions
+
+open System.Linq.Expressions
+open System.Text
+open Interpreters.Expressions.ExpressionParsers
+
+type StringExpressionParserBuilder private
+ (
+ expressionParser: StringExpressionParser
+ ) =
+ class
+ new() = new StringExpressionParserBuilder(new StringExpressionParser())
+
+ member this.Build = expressionParser :> IStringExpressionParser
+ end
+
diff --git a/src/Interpreters/Expressions/ExpressionParser.fs b/src/Interpreters/Expressions/ExpressionParser.fs
new file mode 100644
index 00000000..dd0911af
--- /dev/null
+++ b/src/Interpreters/Expressions/ExpressionParser.fs
@@ -0,0 +1,11 @@
+namespace Interpreters.Expressions
+
+open Interpreters
+
+type IStringExpressionParser =
+ interface
+ abstract member Parse : set: IVariableSet -> stringExpression: string -> VariableValue
+
+ abstract member TryParse: set: IVariableSet -> stringExpression: string -> VariableValue option
+ end
+
\ No newline at end of file
diff --git a/src/Interpreters/Expressions/ExpressionParsers/StringExpressionParser.fs b/src/Interpreters/Expressions/ExpressionParsers/StringExpressionParser.fs
new file mode 100644
index 00000000..5c866f08
--- /dev/null
+++ b/src/Interpreters/Expressions/ExpressionParsers/StringExpressionParser.fs
@@ -0,0 +1,50 @@
+module Interpreters.Expressions.ExpressionParsers
+
+open System
+open System.Text.RegularExpressions
+open Interpreters
+
+/// Combines two parsers: tries to parse using first parser, then second.
+let combine parser1 parser2 =
+ let combine' p1 p2 (parsing: string): VariableValue option =
+ match p1 parsing with
+ | None -> p2 parsing
+ | x -> x
+ combine' parser1 parser2
+
+/// Infix variant of combine.
+let (>>+) parser1 parser2 = combine parser1 parser2
+
+module Helper =
+
+ let parseDouble (expr: string) =
+ try
+ expr
+ |> double
+ |> VariableValue.createDouble
+ |> Some
+ with :? FormatException -> None
+
+ let parseInt (expr: string) =
+ try
+ expr
+ |> int
+ |> VariableValue.createInt
+ |> Some
+ with :? FormatException -> None
+
+ let parser = (parseInt >>+ parseDouble)
+
+open Helper
+
+type StringExpressionParser() =
+ class
+ interface IStringExpressionParser with
+ member this.TryParse set stringExpression = parser stringExpression
+
+ member this.Parse set stringExpression =
+ let parsed = (this :> IStringExpressionParser).TryParse set stringExpression
+ match parsed with
+ | Some value -> value
+ | None -> new FormatException "Can't recognize expression" |> raise
+ end
diff --git a/src/Interpreters/IVariableSet.fs b/src/Interpreters/IVariableSet.fs
new file mode 100644
index 00000000..dbfedb0c
--- /dev/null
+++ b/src/Interpreters/IVariableSet.fs
@@ -0,0 +1,34 @@
+namespace Interpreters
+
+open Interpreters
+
+type IVariableSet =
+ interface
+ abstract member Add: v: Variable -> IVariableSet
+
+ abstract member Remove: v: Variable -> IVariableSet
+
+ abstract member RemoveAll: v: Variable -> IVariableSet
+
+ abstract member FindByName: name: string -> Variable
+
+ abstract member FindAllByName: name: string -> Variable list
+
+ abstract member Filter: (Variable -> bool) -> Variable list
+
+ abstract member ChangeValue: v: Variable -> newValue: VariableValue -> IVariableSet
+
+ abstract member ChangeValueByName: name: string -> newValue: VariableValue -> IVariableSet
+
+ abstract member Drop: unit -> IVariableSet
+
+ abstract member ToList: Variable list
+ end
+
+
+
+
+
+
+
+
diff --git a/src/Interpreters/Interpreter.fs b/src/Interpreters/Interpreter.fs
new file mode 100644
index 00000000..6966ec56
--- /dev/null
+++ b/src/Interpreters/Interpreter.fs
@@ -0,0 +1,39 @@
+namespace Interpreters
+
+open Repo
+
+type IPerformerCommand =
+ interface
+ abstract member Description: string with get
+ end
+
+type IProgramRunner<'T> =
+ interface
+ abstract member SpecificContext: 'T with get
+
+ abstract member Run: unit -> unit
+
+ abstract member Model: IModel with get
+
+ abstract member SetModel: model: IModel -> unit
+ end
+
+type IInterpreter<'T> =
+ interface
+ inherit IProgramRunner<'T>
+
+ abstract member CurrentElement: IElement with get
+
+ abstract member Step : unit -> unit
+
+ abstract member StepInto : unit -> unit
+
+ abstract member Debug : unit -> unit
+
+ abstract member BreakPoints : IElement list with get, set
+
+ abstract member Continue: unit -> unit
+
+ abstract member Stop: unit -> unit
+ end
+
diff --git a/src/Interpreters/InterpreterHelper.fs b/src/Interpreters/InterpreterHelper.fs
new file mode 100644
index 00000000..14e126e0
--- /dev/null
+++ b/src/Interpreters/InterpreterHelper.fs
@@ -0,0 +1,13 @@
+module Interpreters.InterpreterHelper
+
+open Repo
+
+module Element =
+ let findAllEdgesFrom (model: IModel) (element: IElement) =
+ model.Edges |> Seq.filter (fun (e: IEdge) -> e.From = element)
+
+ let next (model: IModel) (element: IElement) = findAllEdgesFrom model element |> Seq.exactlyOne
+
+ let findAllEdgesTo (model: IModel) (element: IElement) =
+ model.Edges |> Seq.filter (fun (e: IEdge) -> e.To = element)
+
diff --git a/src/Interpreters/Interpreters.fsproj b/src/Interpreters/Interpreters.fsproj
new file mode 100644
index 00000000..19b1c0fc
--- /dev/null
+++ b/src/Interpreters/Interpreters.fsproj
@@ -0,0 +1,93 @@
+
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ 522a914e-b787-43b6-9630-b169c8c3441b
+ Library
+ Interpreters
+ Interpreters
+ true
+ v4.6.1
+ true
+ 3239;$(WarningsAsErrors)
+ Interpreters
+
+
+ true
+ full
+ false
+ false
+ bin\$(Configuration)\
+ DEBUG;TRACE
+ 3
+ bin\$(Configuration)\$(AssemblyName).XML
+
+
+ pdbonly
+ true
+ true
+ bin\$(Configuration)\
+ TRACE
+ 3
+ bin\$(Configuration)\$(AssemblyName).XML
+
+
+ 11
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll
+ True
+
+
+ Repo
+ {9e7065a4-ba5e-4752-84bf-54d5c00db60c}
+ True
+
+
+
+
+
+
+ ..\..\packages\FSharp.Core\lib\net45\FSharp.Core.dll
+ True
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Interpreters/Parser.fs b/src/Interpreters/Parser.fs
new file mode 100644
index 00000000..c43d1c04
--- /dev/null
+++ b/src/Interpreters/Parser.fs
@@ -0,0 +1,47 @@
+namespace Interpreters
+
+open Repo
+
+/// State that should be parsed.
+type Parsing<'T> =
+ { Variables: IVariableSet; Context: 'T; Model:IModel; Element: IElement }
+
+module Parsing =
+
+ /// Gets the Variables component from Parsing.
+ let variables (p: Parsing<'T>) = p.Variables
+
+ /// Gets the Context component from Parsing.
+ let context (p: Parsing<'T>) = p.Context
+
+ /// Gets the Model component from Parsing.
+ let model (p: Parsing<'T>) = p.Model
+
+ /// Gets the element component from Parsing.
+ let element (p: Parsing<'T>) = p.Element
+
+/// Type of function which transforms one Parsing into another.
+type Parser<'T> = Parsing<'T> option -> Parsing<'T> option
+
+module Parser =
+ /// Combines two parsers: tries to parse using first parser, then second.
+ let combine parser1 parser2 =
+ let combine' p1 p2 parsing =
+ if parsing = None then None
+ else match p1 parsing with
+ | None -> p2 parsing
+ | x -> x
+ combine' parser1 parser2
+
+ /// Infix variant of combine.
+ let (>>+) parser1 parser2 = combine parser1 parser2
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Interpreters/Variable.fs b/src/Interpreters/Variable.fs
new file mode 100644
index 00000000..5ac99fe9
--- /dev/null
+++ b/src/Interpreters/Variable.fs
@@ -0,0 +1,130 @@
+namespace Interpreters
+
+open System
+open Repo
+
+/// Represents primitive types, such as int, double and boolean
+type RegularType =
+ | Int of int
+ | Double of double
+ | Boolean of bool
+
+/// Represents a value, could be regular or complex
+type VariableValue =
+ | Regular of RegularType
+ | Complex
+
+/// Mutability of variable.
+type VariableMutability =
+ | Mutable = 0
+ | Immutable = 1
+
+/// Block where variable was created or its absence.
+type PlaceOfCreation =
+ | PlaceOfCreation of IModel option * IElement option
+
+/// Meta info about variable, such as mutability, place of creation.
+type MetaData = {Mutability: VariableMutability; PlaceOfCreation: PlaceOfCreation} with
+ member this.IsMutable = this.Mutability = VariableMutability.Mutable
+
+/// Represents a variable, contains name, value and meta.
+type Variable = { Name: string; Value: VariableValue; Meta: MetaData } with
+ /// Checks values of given variables for equality.
+ static member (==) (x, y) = x.Value = y.Value
+
+ /// Checks variable's mutability.
+ member this.IsMutable = this.Meta.IsMutable
+
+module PlaceOfCreation =
+ /// Creates none block PlaceOfCreation.
+ let empty = PlaceOfCreation(None, None)
+
+module RegularType =
+ /// Checks that types of given values are equal.
+ let isTypesEqual xValue yValue =
+ match (xValue, yValue) with
+ | (Int _, Int _) -> true
+ | (Boolean _, Boolean _) -> true
+ | (Double _, Double _) -> true
+ | _ -> false // notice: not implemented for other types
+
+ /// Creates wrapped int value.
+ let createInt x = Int x
+
+ /// Creates wrapped double value.
+ let createDouble x = Double x
+
+ /// Creates wrapped boolean value.
+ let createBoolean x = Boolean x
+
+module VariableValue =
+ /// Checks is given type regular.
+ let isRegular (value: VariableValue) =
+ match value with
+ | Regular _ -> true
+ | _ -> false
+
+ /// Checks that types of given values are equal.
+ let isTypesEqual xValue yValue =
+ match (xValue, yValue) with
+ | (Regular xv, Regular yv) -> RegularType.isTypesEqual xv yv
+ | _ -> new NotImplementedException() |> raise
+
+ /// Creates wrapped int value.
+ let createInt x = x |> RegularType.createInt |> Regular
+
+ /// Creates wrapped double value.
+ let createDouble x = x |> RegularType.createDouble |> Regular
+
+ /// Creates wrapped boolean value.
+ let createBoolean x = x |> RegularType.createBoolean |> Regular
+
+module MetaData =
+ /// Creates meta data.
+ let createMeta isMutable (place: (IModel option * IElement option)) =
+ let toPlace = PlaceOfCreation
+ match isMutable with
+ | true -> {Mutability = VariableMutability.Mutable; PlaceOfCreation = (toPlace place)}
+ | _ -> {Mutability = VariableMutability.Immutable; PlaceOfCreation = (toPlace place)}
+
+ /// Makes data immutable.
+ let makeImmutable (data: MetaData) = {data with Mutability = VariableMutability.Immutable}
+
+ /// Makes data mutable.
+ let makeMutable (data: MetaData) = {data with Mutability = VariableMutability.Mutable}
+
+module Variable =
+ /// Checks is given variable regular.
+ let isRegular variable = VariableValue.isRegular variable.Value
+
+ /// Checks given variables' types for equality.
+ let isTypesEqual xVariable yVariable = VariableValue.isTypesEqual xVariable.Value yVariable.Value
+
+ /// Checks given variable for mutability.
+ let isMutable (x: Variable) = x.IsMutable
+
+ /// Makes variable mutable.
+ let makeMutable variable = {variable with Meta = MetaData.makeMutable variable.Meta}
+
+ /// Makes variable immutable.
+ let makeImmutable variable = {variable with Meta = MetaData.makeImmutable variable.Meta}
+
+ /// Creates int variable with given name, value and meta.
+ let createInt name x place = {Name = name; Value = (VariableValue.createInt x); Meta = MetaData.createMeta true place}
+
+ /// Creates double variable with given name, value and meta.
+ let createDouble name x place = {Name = name; Value = (VariableValue.createDouble x); Meta = MetaData.createMeta true place}
+
+ /// Creates boolean variable with given name, value and meta.
+ let createBoolean name x place = {Name = name; Value = (VariableValue.createBoolean x); Meta = MetaData.createMeta true place}
+
+ /// Changes value of given variable.
+ let changeValue (newValue: VariableValue) (variable: Variable) =
+ if (not variable.IsMutable) then invalidOp "Variable is immutable"
+ elif (VariableValue.isTypesEqual newValue variable.Value) then {variable with Value = newValue}
+ else invalidOp "Not equal types"
+ /// Changes value of given value in spite of constraints.
+ let forceChangeValue (newValue: VariableValue) (variable: Variable) = {variable with Value = newValue}
+
+
+
diff --git a/src/Interpreters/VariableSet.fs b/src/Interpreters/VariableSet.fs
new file mode 100644
index 00000000..b6fe60d1
--- /dev/null
+++ b/src/Interpreters/VariableSet.fs
@@ -0,0 +1,19 @@
+namespace Interpreters
+
+ module VariableSet =
+
+ open Interpreters.Common
+
+ type VariableSetFactory =
+ struct
+ static member CreateVariableSet (variables: seq) = new VariableList(variables) :> IVariableSet
+
+ static member CreateVariableSet variables = new VariableList(variables) :> IVariableSet
+ end
+
+
+
+
+
+
+
diff --git a/src/Interpreters/app.config b/src/Interpreters/app.config
new file mode 100644
index 00000000..2ff85cbe
--- /dev/null
+++ b/src/Interpreters/app.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+ True
+
+
+
+
\ No newline at end of file
diff --git a/src/Interpreters/paket.references b/src/Interpreters/paket.references
new file mode 100644
index 00000000..640cf914
--- /dev/null
+++ b/src/Interpreters/paket.references
@@ -0,0 +1 @@
+FSharp.Core
\ No newline at end of file
diff --git a/src/LOGO/Interpreters.Logo/AssemblyInfo.fs b/src/LOGO/Interpreters.Logo/AssemblyInfo.fs
new file mode 100644
index 00000000..6d5c6c5e
--- /dev/null
+++ b/src/LOGO/Interpreters.Logo/AssemblyInfo.fs
@@ -0,0 +1,41 @@
+namespace Interpreters.Logo.AssemblyInfo
+
+open System.Reflection
+open System.Runtime.CompilerServices
+open System.Runtime.InteropServices
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+
+// 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.
+[]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[]
+
+// 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:
+// []
+[]
+[]
+
+do
+ ()
\ No newline at end of file
diff --git a/src/LOGO/Interpreters.Logo/Interpreters.Logo.fsproj b/src/LOGO/Interpreters.Logo/Interpreters.Logo.fsproj
new file mode 100644
index 00000000..3d3c6c12
--- /dev/null
+++ b/src/LOGO/Interpreters.Logo/Interpreters.Logo.fsproj
@@ -0,0 +1,93 @@
+
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ 1d57e43c-c29e-4ea5-be01-028d73781637
+ Library
+ Interpreters.Logo
+ Interpreters.Logo
+ true
+ v4.6.1
+ true
+ 3239;$(WarningsAsErrors)
+ Interpreters.Logo
+
+
+ true
+ full
+ false
+ false
+ bin\$(Configuration)\
+ DEBUG;TRACE
+ 3
+ bin\$(Configuration)\$(AssemblyName).XML
+
+
+ pdbonly
+ true
+ true
+ bin\$(Configuration)\
+ TRACE
+ 3
+ bin\$(Configuration)\$(AssemblyName).XML
+
+
+ 11
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll
+ True
+
+
+
+
+ Interpreters
+ {522a914e-b787-43b6-9630-b169c8c3441b}
+ True
+
+
+ Repo
+ {9e7065a4-ba5e-4752-84bf-54d5c00db60c}
+ True
+
+
+
+
+
+
+ ..\..\..\packages\FSharp.Core\lib\net45\FSharp.Core.dll
+ True
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LOGO/Interpreters.Logo/Logo/LogoInterpeter.fs b/src/LOGO/Interpreters.Logo/Logo/LogoInterpeter.fs
new file mode 100644
index 00000000..805c6805
--- /dev/null
+++ b/src/LOGO/Interpreters.Logo/Logo/LogoInterpeter.fs
@@ -0,0 +1,84 @@
+namespace Interpreters.Logo.LogoInterpeter
+
+open Repo
+
+open Interpreters.Logo
+
+open Interpreters.Logo.LogoParser
+
+open Interpreters.Logo.LogoSpecific
+
+open Interpreters
+
+open TurtleCommand
+open System
+
+type LogoContext(list) =
+ class
+ interface ILogoContext with
+ member this.LogoCommands = List.toSeq list
+ end
+
+type LogoRunner(model: IModel) =
+ class
+ let mutable currentModel = model
+
+ let mutable commandList = []
+
+ let isInitial (element: IElement) = element.Class.Name = "InitialNode"
+
+ let isFinal (element: IElement) = element.Class.Name = "FinalNode"
+
+ let getInitialNode() =
+ try model.Elements |> Seq.filter isInitial |> Seq.exactlyOne
+ with :? ArgumentException -> ParserException.raiseException "Can't find initial node"
+
+ let getFinalNode() =
+ try model.Elements |> Seq.filter isFinal |> Seq.exactlyOne
+ with :? ArgumentException -> ParserException.raiseException "Can't find final node"
+
+ let findAllEdgesFrom (element: IElement) =
+ model.Edges |> Seq.filter (fun (e: IEdge) -> e.From = element)
+
+ let next (element: IElement) = let edge = findAllEdgesFrom element |> Seq.exactlyOne in edge.To
+
+ member this.Model: IModel = currentModel
+
+ member this.Run() =
+ let rec run (p: Parsing option) =
+ match p with
+ | Some { Variables = set; Context = context; Model = model; Element = element} as result when element = getFinalNode() -> result
+ | None -> failwith "can not be parsed"
+ | _ -> p |> LogoParser.parseLogo |> run
+ let emtyVariableSet = Interpreters.VariableSet.VariableSetFactory.CreateVariableSet([])
+ let context = Context.createContext
+ let firstBlock =
+ try getInitialNode() |> next
+ with :? ArgumentException ->
+ ParserException.raiseWithPlace "More than one edge from initial node" (PlaceOfCreation (Some model, getInitialNode() |> Some))
+ let (wrapped: Parsing option) = {Variables = emtyVariableSet; Context = context; Model = model; Element = firstBlock} |> Some
+ let result = run wrapped
+ let context = result.Value |> Parsing.context
+ commandList <- context.Commands
+
+ member this.SpecificContext: ILogoContext =
+ let convertedList = List.map convertToLogoCommand commandList
+ new LogoContext(convertedList) :> ILogoContext
+
+ interface IProgramRunner with
+ member this.Model: IModel = this.Model
+
+ member this.SetModel(model: IModel): unit = currentModel <- model
+
+ member this.Run() = this.Run()
+
+ member this.SpecificContext: ILogoContext = this.SpecificContext
+ end
+
+module Test =
+
+ let repo = RepoFactory.Create()
+ let model = repo.CreateModel("some", "LogoMetamodel")
+
+ let runner = new LogoRunner(model)
+
diff --git a/src/LOGO/Interpreters.Logo/Logo/LogoParser.fs b/src/LOGO/Interpreters.Logo/Logo/LogoParser.fs
new file mode 100644
index 00000000..e0c9ba6f
--- /dev/null
+++ b/src/LOGO/Interpreters.Logo/Logo/LogoParser.fs
@@ -0,0 +1,159 @@
+module Interpreters.Logo.LogoParser
+
+open Interpreters.Parser
+
+open Interpreters.Logo.TurtleCommand
+
+open Repo
+
+open Interpreters
+
+type Context = { Commands: LCommand list}
+
+module Context =
+ let createContext = {Commands = []}
+
+module private Helper =
+ let findAttributeValueByName (element: IElement) (name: string) =
+ let list = element.Attributes
+ let e = Seq.find (fun (x: IAttribute) -> x.Name = name) list
+ e.StringValue
+
+ let distanceName = "Distance"
+
+ let degreesName = "Degrees"
+
+ let stringToDouble expr = double expr
+
+ let stringToInt expr = int expr
+
+ let findAllEdgesFrom (model: IModel) (element: IElement) =
+ model.Edges |> Seq.filter (fun (e: IEdge) -> e.From = element)
+
+ let next (model: IModel) (element: IElement) = findAllEdgesFrom model element |> Seq.exactlyOne
+
+ let findAllEdgesTo (model: IModel) (element: IElement) =
+ model.Edges |> Seq.filter (fun (e: IEdge) -> e.To = element)
+
+
+ let hasAttribute name (element: IElement) =
+ element.Attributes |> Seq.filter (fun x -> x.Name = name) |> Seq.isEmpty |> not
+
+module AvailableParsers =
+
+ let parseForward (parsing: Parsing option) : Parsing option =
+ match parsing with
+ | None -> None
+ | Some {Variables = set; Context = context; Model = model; Element = element} ->
+ if (element.Class.Name = "Forward")
+ then let distanceString = Helper.findAttributeValueByName element Helper.distanceName
+ let distance = distanceString |> Helper.stringToDouble
+ let command = LForward distance
+ let newContext = {context with Commands = command :: context.Commands}
+ let edges = Helper.findAllEdgesFrom model element
+ if Seq.length edges > 1 then None
+ else let edge = Seq.exactlyOne edges
+ let parsed = {Variables = set; Context = newContext; Model = model; Element = edge.To}
+ parsed |> Some
+ else None
+
+ let parseBackward (parsing: Parsing option) : Parsing option =
+ match parsing with
+ | None -> None
+ | Some {Variables = set; Context = context; Model = model; Element = element} ->
+ if (element.Class.Name = "Backward")
+ then let distanceString = Helper.findAttributeValueByName element Helper.distanceName
+ let distance = distanceString |> Helper.stringToDouble
+ let command = LBackward distance
+ let newContext = {context with Commands = command :: context.Commands}
+ let edges = Helper.findAllEdgesFrom model element
+ if Seq.length edges > 1 then None
+ else let edge = Seq.exactlyOne edges
+ let parsed = {Variables = set; Context = newContext; Model = model; Element = edge.To}
+ parsed |> Some
+ else None
+
+ let parseRight (parsing: Parsing option) : Parsing option =
+ match parsing with
+ | None -> None
+ | Some {Variables = set; Context = context; Model = model; Element = element} ->
+ if (element.Class.Name = "Right")
+ then let degreesString = Helper.findAttributeValueByName element Helper.degreesName
+ let degrees = degreesString |> Helper.stringToDouble
+ let command = LRight degrees
+ let newContext = {context with Commands = command :: context.Commands}
+ let edges = Helper.findAllEdgesFrom model element
+ if Seq.length edges > 1 then None
+ else let edge = Seq.exactlyOne edges
+ let parsed = {Variables = set; Context = newContext; Model = model; Element = edge.To}
+ parsed |> Some
+ else None
+
+ let parseLeft (parsing: Parsing option) : Parsing option =
+ match parsing with
+ | None -> None
+ | Some {Variables = set; Context = context; Model = model; Element = element} ->
+ if (element.Class.Name = "Left")
+ then let degreesString = Helper.findAttributeValueByName element Helper.degreesName
+ let degrees = degreesString |> Helper.stringToDouble
+ let command = LLeft degrees
+ let newContext = {context with Commands = command :: context.Commands}
+ let edges = Helper.findAllEdgesFrom model element
+ if Seq.length edges > 1 then None
+ else let edge = Seq.exactlyOne edges
+ let parsed = {Variables = set; Context = newContext; Model = model; Element = edge.To}
+ parsed |> Some
+ else None
+
+ let parseRepeat (parsing: Parsing option) : Parsing option =
+ match parsing with
+ | None -> None
+ | Some ({Variables = set; Context = context; Model = model; Element = element} as p) ->
+ if (element.Class.Name = "Repeat") then
+ let filter (var: Variable) =
+ match var.Meta.PlaceOfCreation with
+ | PlaceOfCreation(_, Some element) -> true
+ | _ -> false
+ let edges = Helper.findAllEdgesFrom model element
+ let exitOption = edges |> Seq.filter (Helper.hasAttribute "Tag") |> Seq.tryExactlyOne
+ match exitOption with
+ | None -> ParserException.raiseWithPlace "No exit found" (PlaceOfCreation(Some model, Some element))
+ | Some exitEdge ->
+ let exit = exitEdge.To
+ let nextElementOption = edges |> Seq.except [exitEdge] |> Seq.tryExactlyOne
+ match nextElementOption with
+ | None -> ParserException.raiseWithPlace "No next element found" (PlaceOfCreation(Some model, Some element))
+ | Some nextElementEdge ->
+ let nextElement = nextElementEdge.To
+ let vars = set.Filter filter
+ if vars.IsEmpty then
+ let countString = Helper.findAttributeValueByName element "Count"
+ let count = countString |> Helper.stringToInt
+ if (count = 0) then
+ Some {p with Element = exit}
+ else
+ let i = Variable.createInt "repeatI" count (Some model, Some element)
+ let newSet = set.Add i
+ Some {p with Variables = newSet; Element = nextElement}
+ else
+ let countVarOption = vars |> Seq.filter (fun x -> x.Name = "repeatI") |> Seq.tryExactlyOne
+ match countVarOption with
+ | None -> ParserException.raiseWithPlace "No correct count variable found" (PlaceOfCreation(Some model, Some element))
+ | Some ({Value = value} as countVar) ->
+ match value with
+ | Regular (Int intVal) ->
+ if (intVal = 1) then
+ let newSet = set.Remove countVar
+ Some {p with Element = exit; Variables = newSet}
+ else
+ let newVal = VariableValue.createInt (intVal - 1)
+ let newSet = set.ChangeValue countVar newVal
+ Some {p with Element = nextElement; Variables = newSet}
+ | _ -> None
+ else None
+
+open AvailableParsers
+
+let parseMovement: Parser = parseForward >>+ parseRight >>+ parseBackward >>+ parseLeft
+
+let parseLogo = parseMovement >>+ parseRepeat
\ No newline at end of file
diff --git a/src/LOGO/Interpreters.Logo/Logo/LogoSpecific.fs b/src/LOGO/Interpreters.Logo/Logo/LogoSpecific.fs
new file mode 100644
index 00000000..300e486a
--- /dev/null
+++ b/src/LOGO/Interpreters.Logo/Logo/LogoSpecific.fs
@@ -0,0 +1,108 @@
+namespace Interpreters.Logo.LogoSpecific
+
+open System
+
+type LogoTurtle(x: double, y: double, angle: double, isPenDown: bool, speed: double) =
+ struct
+ member this.X = x
+
+ member this.Y = y
+
+ member this.Position = (x, y)
+
+ member this.Angle = angle
+
+ member this.AngleInRadians = angle / 360.0 * 2.0 * Math.PI
+
+ member this.IsPenDown = isPenDown
+
+ member this.Speed = speed;
+
+ static member NewPosition (turtle: LogoTurtle) (x, y) = LogoTurtle (x, y, turtle.Angle, turtle.IsPenDown, turtle.Speed)
+
+ static member NewX (turtle: LogoTurtle) x = LogoTurtle.NewPosition turtle (x, turtle.Y)
+
+ static member NewY (turtle: LogoTurtle) y = LogoTurtle.NewPosition turtle (turtle.X, y)
+
+ static member PenDown (turtle: LogoTurtle) = LogoTurtle (turtle.X, turtle.Y, turtle.Angle, true, turtle.Speed)
+
+ static member PenUp (turtle: LogoTurtle) = LogoTurtle (turtle.X, turtle.Y, turtle.Angle, false, turtle.Speed)
+
+ static member NewAngle (turtle: LogoTurtle) angle =
+ let rec findCorrectAngle (angle: double) =
+ if (angle > 360.0) then findCorrectAngle (angle - 360.0)
+ elif (angle < 0.0) then findCorrectAngle (angle + 360.0)
+ else angle
+ let newAngle = findCorrectAngle angle
+ LogoTurtle (turtle.X, turtle.Y, newAngle, turtle.IsPenDown, turtle.Speed)
+ end
+
+type LogoStats(distance: double, time: double) =
+ struct
+ member this.Distance = distance
+
+ member this.Time = time
+
+ static member NewDistance (stats: LogoStats) distance = LogoStats(distance, stats.Time)
+
+ static member NewTime (stats: LogoStats) time = LogoStats(stats.Distance, time)
+ end
+
+[]
+type LogoCommand() =
+ class
+ abstract member Description: string with get
+ end
+
+type LogoForward(distance: double) =
+ inherit LogoCommand()
+
+ override this.Description = "forward " + distance.ToString()
+
+ member this.Distance = distance
+
+type LogoBackward(distance: double) =
+ inherit LogoCommand()
+
+ override this.Description = "backward " + distance.ToString()
+
+ member this.Distance = distance
+
+type LogoLeft(degrees: double) =
+ inherit LogoCommand()
+
+ override this.Description = "left " + degrees.ToString()
+
+ member this.Degrees = degrees
+
+type LogoRight(degrees: double) =
+ inherit LogoCommand()
+
+ override this.Description = "right " + degrees.ToString()
+
+ member this.Degrees = degrees
+
+type LogoPenUp() =
+ inherit LogoCommand()
+
+ override this.Description = "pen up"
+
+type LogoPenDown() =
+ inherit LogoCommand()
+
+ override this.Description = "pen down"
+
+type LogoSetSpeed(speed: double) =
+ inherit LogoCommand()
+
+ override this.Description = "set speed"
+
+ member this.Speed = speed
+
+type ILogoContext =
+ interface
+ abstract member LogoCommands: seq with get
+ end
+
+
+
diff --git a/src/LOGO/Interpreters.Logo/Logo/TurtleCommand.fs b/src/LOGO/Interpreters.Logo/Logo/TurtleCommand.fs
new file mode 100644
index 00000000..b74af6e3
--- /dev/null
+++ b/src/LOGO/Interpreters.Logo/Logo/TurtleCommand.fs
@@ -0,0 +1,42 @@
+module Interpreters.Logo.TurtleCommand
+
+open Interpreters.Logo.LogoSpecific
+
+type LCommand =
+ | LForward of double
+ | LBackward of double
+ | LLeft of double
+ | LRight of double
+ | LPenDown
+ | LPenUp
+ | LSetSpeed of double
+ | LNoCommand
+
+let (*) x (y, z) = (x * y, x * z)
+
+let (+.) (x, y) (z, t) = (x + z, y + t)
+
+let evaluateTime (distance: double) speed = distance / speed
+
+let forward distance (turtle: LogoTurtle) (stats: LogoStats) =
+ let dp = distance * (cos(turtle.AngleInRadians), sin(turtle.AngleInRadians))
+ let time = evaluateTime distance turtle.Speed
+ let st = LogoStats(stats.Distance + distance, stats.Time + time)
+ let newTurtle = LogoTurtle.NewPosition turtle (turtle.Position +. dp)
+ (newTurtle, st)
+
+
+let convertToLogoCommand (command: LCommand) : LogoCommand =
+ match command with
+ | LForward d -> new LogoForward(d) :> LogoCommand
+ | LBackward d -> new LogoBackward(d) :> LogoCommand
+ | LRight d -> new LogoRight(d) :> LogoCommand
+ | LLeft d -> new LogoLeft(d) :> LogoCommand
+ | LPenUp -> new LogoPenUp() :> LogoCommand
+ | LPenDown -> new LogoPenDown() :> LogoCommand
+ | LSetSpeed s -> new LogoSetSpeed(s) :> LogoCommand
+ | _ -> failwith "unknown command"
+
+
+
+
\ No newline at end of file
diff --git a/src/LOGO/Interpreters.Logo/app.config b/src/LOGO/Interpreters.Logo/app.config
new file mode 100644
index 00000000..2ff85cbe
--- /dev/null
+++ b/src/LOGO/Interpreters.Logo/app.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+ True
+
+
+
+
\ No newline at end of file
diff --git a/src/LOGO/Interpreters.Logo/paket.references b/src/LOGO/Interpreters.Logo/paket.references
new file mode 100644
index 00000000..640cf914
--- /dev/null
+++ b/src/LOGO/Interpreters.Logo/paket.references
@@ -0,0 +1 @@
+FSharp.Core
\ No newline at end of file
diff --git a/src/LOGO/Logo.TurtleInterfaces/DoublePoint.cs b/src/LOGO/Logo.TurtleInterfaces/DoublePoint.cs
new file mode 100644
index 00000000..3576a501
--- /dev/null
+++ b/src/LOGO/Logo.TurtleInterfaces/DoublePoint.cs
@@ -0,0 +1,15 @@
+namespace Logo.TurtleInterfaces
+{
+ public struct DoublePoint
+ {
+ public DoublePoint(double x, double y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public double X { get; }
+
+ public double Y { get; }
+ }
+}
diff --git a/src/LOGO/Logo.TurtleInterfaces/ITurtle.cs b/src/LOGO/Logo.TurtleInterfaces/ITurtle.cs
new file mode 100644
index 00000000..7f3da09c
--- /dev/null
+++ b/src/LOGO/Logo.TurtleInterfaces/ITurtle.cs
@@ -0,0 +1,17 @@
+namespace Logo.TurtleInterfaces
+{
+ public interface ITurtle
+ {
+ double Speed { get; }
+
+ double X { get; }
+
+ double Y { get; }
+
+ DoublePoint Position { get; }
+
+ double Angle { get; }
+
+ bool IsPenDown { get; }
+ }
+}
diff --git a/src/LOGO/Logo.TurtleInterfaces/ITurtleCommander.cs b/src/LOGO/Logo.TurtleInterfaces/ITurtleCommander.cs
new file mode 100644
index 00000000..a0ca7d70
--- /dev/null
+++ b/src/LOGO/Logo.TurtleInterfaces/ITurtleCommander.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Logo.TurtleInterfaces
+{
+ public interface ITurtleCommander
+ {
+ ITurtle Turtle { get; }
+
+ void MoveBackward(double distance);
+
+ void MoveForward(double distance);
+
+ void PenDown();
+
+ void PenUp();
+
+ void RotateLeft(double degrees);
+
+ void RotateRight(double degrees);
+
+ void SetSpeed(double speed);
+ }
+}
diff --git a/src/LOGO/Logo.TurtleInterfaces/Logo.TurtleInterfaces.csproj b/src/LOGO/Logo.TurtleInterfaces/Logo.TurtleInterfaces.csproj
new file mode 100644
index 00000000..405fce45
--- /dev/null
+++ b/src/LOGO/Logo.TurtleInterfaces/Logo.TurtleInterfaces.csproj
@@ -0,0 +1,75 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {69309937-D690-4365-85D8-698C30FCEFF4}
+ Library
+ Properties
+ Logo.TurtleInterfaces
+ Logo.TurtleInterfaces
+ v4.6.1
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\packages\FSharp.Core\lib\net45\FSharp.Core.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ True
+
+
+ ..\..\..\packages\System.ValueTuple\lib\net461\System.ValueTuple.dll
+ True
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LOGO/Logo.TurtleInterfaces/Properties/AssemblyInfo.cs b/src/LOGO/Logo.TurtleInterfaces/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..3f0b6918
--- /dev/null
+++ b/src/LOGO/Logo.TurtleInterfaces/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Общие сведения об этой сборке предоставляются следующим набором
+// набора атрибутов. Измените значения этих атрибутов для изменения сведений,
+// связанные со сборкой.
+[assembly: AssemblyTitle("Logo.TurtleInterfaces")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Logo.TurtleInterfaces")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми
+// для компонентов COM. Если необходимо обратиться к типу в этой сборке через
+// COM, задайте атрибуту ComVisible значение TRUE для этого типа.
+[assembly: ComVisible(false)]
+
+// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
+[assembly: Guid("69309937-d690-4365-85d8-698c30fceff4")]
+
+// Сведения о версии сборки состоят из указанных ниже четырех значений:
+//
+// Основной номер версии
+// Дополнительный номер версии
+// Номер сборки
+// Редакция
+//
+// Можно задать все значения или принять номера сборки и редакции по умолчанию
+// используя "*", как показано ниже:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/LOGO/LogoScene/App.config b/src/LOGO/LogoScene/App.config
new file mode 100644
index 00000000..17c15a09
--- /dev/null
+++ b/src/LOGO/LogoScene/App.config
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
diff --git a/src/LOGO/LogoScene/App.xaml b/src/LOGO/LogoScene/App.xaml
new file mode 100644
index 00000000..c7aafa7b
--- /dev/null
+++ b/src/LOGO/LogoScene/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/src/LOGO/LogoScene/App.xaml.cs b/src/LOGO/LogoScene/App.xaml.cs
new file mode 100644
index 00000000..b5f4409a
--- /dev/null
+++ b/src/LOGO/LogoScene/App.xaml.cs
@@ -0,0 +1,11 @@
+using System.Windows;
+
+namespace LogoScene
+{
+ ///
+ /// Логика взаимодействия для App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/src/LOGO/LogoScene/ArhitectureDiagrams/SimpleArchitecture.cd b/src/LOGO/LogoScene/ArhitectureDiagrams/SimpleArchitecture.cd
new file mode 100644
index 00000000..c4b3d5b1
--- /dev/null
+++ b/src/LOGO/LogoScene/ArhitectureDiagrams/SimpleArchitecture.cd
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+ AAAACAAQAAQAEAIEAAAAAAAAAAAAhIAAAAQAAAAIAAg=
+ ViewModels\DrawingSceneViewModel.cs
+
+
+
+
+
+
+
+
+ AAIAAAASACAAAAAgAEAAAAAAAAAABAAQAAQAEgAAEAA=
+ ViewModels\TurtleControlViewModel.cs
+
+
+
+
+
+
+ AAAAAAAAAAAAAAAAIAAAAAAAgAAAAAAAAAAAAAAAAAA=
+ ViewModels\ViewModelBase.cs
+
+
+
+
+
+
+
+
+
+
+
+ Models\DrawingScene.cs
+
+
+
+
+
+ AAAAAAIAAAAIAAAAAAAAQAAAAAAAAAAABAAAAAAAAAA=
+ Models\DrawingScene.cs
+
+
+
+
+
+ AAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAEAAAAAAYAA=
+ Models\ITurtle.cs
+
+
+
+
+
+ AAAAAAAAAQgAAAAAAAAAABAAAoEABAAAAAAAAAAEIAA=
+ Models\ITurtleCommander.cs
+
+
+
+
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/Controls/Converters/BoolToVisibilityConverter.cs b/src/LOGO/LogoScene/Controls/Converters/BoolToVisibilityConverter.cs
new file mode 100644
index 00000000..4f932ca0
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/Converters/BoolToVisibilityConverter.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace LogoScene.Controls.Converters
+{
+ public class BoolToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var IsVisible = (bool)value;
+ return IsVisible ? "Visible" : "Collapsed";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Controls/Converters/MinusConverter.cs b/src/LOGO/LogoScene/Controls/Converters/MinusConverter.cs
new file mode 100644
index 00000000..452a3024
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/Converters/MinusConverter.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace LogoScene.Controls.Converters
+{
+ public class MinusConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var toNegative = (double)value;
+ return -toNegative;
+
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Controls/Converters/TurtleAngleConverter.cs b/src/LOGO/LogoScene/Controls/Converters/TurtleAngleConverter.cs
new file mode 100644
index 00000000..a7844a19
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/Converters/TurtleAngleConverter.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace LogoScene.Controls.Converters
+{
+ public class TurtleAngleConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var angle = (double)value;
+ return -(angle - 90);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Controls/Converters/TurtleXConverter.cs b/src/LOGO/LogoScene/Controls/Converters/TurtleXConverter.cs
new file mode 100644
index 00000000..ae0124b9
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/Converters/TurtleXConverter.cs
@@ -0,0 +1,32 @@
+using Logo.TurtleInterfaces;
+using LogoScene.Models;
+using LogoScene.Operations;
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace LogoScene.Controls.Converters
+{
+ public class TurtleXConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ DoublePoint start = (DoublePoint)values[0];
+ DoublePoint end = (DoublePoint)values[1];
+ double speed = (double)values[2];
+ double tag = (double)values[3];
+ var lambda = tag;
+ // position = (1-lambda)*start+lambda*end
+ var position = PointOperations.Plus(PointOperations.ScalarMultiply(1 - lambda, start),
+ PointOperations.ScalarMultiply(lambda, end));
+ var shift = new DoublePoint(Constants.TurtleWidth / 2, Constants.TurtleHeight / 2);
+ var transformedPosition = PointOperations.Minus(position, shift);
+ return transformedPosition.X;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Controls/Converters/TurtleYConverter.cs b/src/LOGO/LogoScene/Controls/Converters/TurtleYConverter.cs
new file mode 100644
index 00000000..631e0d80
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/Converters/TurtleYConverter.cs
@@ -0,0 +1,32 @@
+using Logo.TurtleInterfaces;
+using LogoScene.Models;
+using LogoScene.Operations;
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace LogoScene.Controls.Converters
+{
+ public class TurtleYConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ DoublePoint start = (DoublePoint)values[0];
+ DoublePoint end = (DoublePoint)values[1];
+ double speed = (double)values[2];
+ double tag = (double)values[3];
+ var lambda = tag;
+ // position = (1-lambda)*start+lambda*end
+ var position = PointOperations.Plus(PointOperations.ScalarMultiply(1 - lambda, start),
+ PointOperations.ScalarMultiply(lambda, end));
+ var shift = new DoublePoint(Constants.TurtleWidth / 2, Constants.TurtleHeight / 2);
+ var transformedPosition = PointOperations.Minus(position, shift);
+ return transformedPosition.Y;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Controls/Converters/XLineConverter.cs b/src/LOGO/LogoScene/Controls/Converters/XLineConverter.cs
new file mode 100644
index 00000000..2031d13b
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/Converters/XLineConverter.cs
@@ -0,0 +1,30 @@
+using Logo.TurtleInterfaces;
+using LogoScene.Models.Log;
+using LogoScene.Operations;
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace LogoScene.Controls.Converters
+{
+ public class XLineConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ DoublePoint start = (DoublePoint)values[0];
+ DoublePoint end = (DoublePoint)values[1];
+ double tag = (double)values[2];
+ var lambda = tag;
+ Logger.Log.Info(tag);
+ // position = (1-lambda)*start+lambda*end
+ var position = PointOperations.Plus(PointOperations.ScalarMultiply(1 - lambda, start),
+ PointOperations.ScalarMultiply(lambda, end));
+ return position.X;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Controls/Converters/YLineConverter.cs b/src/LOGO/LogoScene/Controls/Converters/YLineConverter.cs
new file mode 100644
index 00000000..a8a78fb4
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/Converters/YLineConverter.cs
@@ -0,0 +1,28 @@
+using Logo.TurtleInterfaces;
+using LogoScene.Operations;
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace LogoScene.Controls.Converters
+{
+ public class YLineConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ DoublePoint start = (DoublePoint)values[0];
+ DoublePoint end = (DoublePoint)values[1];
+ double tag = (double)values[2];
+ var lambda = tag;
+ // position = (1-lambda)*start+lambda*end
+ var position = PointOperations.Plus(PointOperations.ScalarMultiply(1 - lambda, start),
+ PointOperations.ScalarMultiply(lambda, end));
+ return -position.Y;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Controls/DrawingScene.xaml b/src/LOGO/LogoScene/Controls/DrawingScene.xaml
new file mode 100644
index 00000000..715a5e70
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/DrawingScene.xaml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/LOGO/LogoScene/Controls/DrawingScene.xaml.cs b/src/LOGO/LogoScene/Controls/DrawingScene.xaml.cs
new file mode 100644
index 00000000..f4488c89
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/DrawingScene.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace LogoScene.Controls
+{
+ ///
+ /// Логика взаимодействия для DrawingScene.xaml
+ ///
+ public partial class DrawingScene : UserControl
+ {
+ public DrawingScene()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Controls/TurtleControl.xaml b/src/LOGO/LogoScene/Controls/TurtleControl.xaml
new file mode 100644
index 00000000..1e5f8c34
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/TurtleControl.xaml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/LOGO/LogoScene/Controls/TurtleControl.xaml.cs b/src/LOGO/LogoScene/Controls/TurtleControl.xaml.cs
new file mode 100644
index 00000000..3b7927ca
--- /dev/null
+++ b/src/LOGO/LogoScene/Controls/TurtleControl.xaml.cs
@@ -0,0 +1,24 @@
+using LogoScene.ViewModels.Animation;
+using System;
+using System.Windows.Controls;
+
+namespace LogoScene.Controls
+{
+ ///
+ /// Логика взаимодействия для TurtleControl.xaml
+ ///
+ public partial class TurtleControl : UserControl
+ {
+
+ public TurtleControl()
+ {
+ InitializeComponent();
+ }
+
+ private void OnStoryboardCompleted(object sender, EventArgs e)
+ {
+ var animationCompleted = DataContext as IAnimationCompletedHandler;
+ animationCompleted.AnimationCompletedCommand.Execute(null);
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/EventArgs/LineEventArgs.cs b/src/LOGO/LogoScene/EventArgs/LineEventArgs.cs
new file mode 100644
index 00000000..8fa21828
--- /dev/null
+++ b/src/LOGO/LogoScene/EventArgs/LineEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Logo.TurtleInterfaces
+{
+ public class LineEventArgs : EventArgs
+ {
+ public DoublePoint StartPoint => Line.Start;
+
+ public DoublePoint EndPoint => Line.End;
+
+ public OrientedLine Line { get; }
+
+ public LineEventArgs(DoublePoint oldPosition, DoublePoint newPosition) => Line = new OrientedLine(oldPosition, newPosition);
+
+ public LineEventArgs(OrientedLine line) => this.Line = line;
+ }
+}
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/EventArgs/PenActionEventArgs.cs b/src/LOGO/LogoScene/EventArgs/PenActionEventArgs.cs
new file mode 100644
index 00000000..3bccfabd
--- /dev/null
+++ b/src/LOGO/LogoScene/EventArgs/PenActionEventArgs.cs
@@ -0,0 +1,6 @@
+namespace Logo.TurtleInterfaces
+{
+ public class PenActionEventArgs
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/EventArgs/RotationEventArgs.cs b/src/LOGO/LogoScene/EventArgs/RotationEventArgs.cs
new file mode 100644
index 00000000..ec526778
--- /dev/null
+++ b/src/LOGO/LogoScene/EventArgs/RotationEventArgs.cs
@@ -0,0 +1,6 @@
+namespace Logo.TurtleInterfaces
+{
+ public class RotationEventArgs
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/EventArgs/SpeedUpdateEventArgs.cs b/src/LOGO/LogoScene/EventArgs/SpeedUpdateEventArgs.cs
new file mode 100644
index 00000000..c03d54d5
--- /dev/null
+++ b/src/LOGO/LogoScene/EventArgs/SpeedUpdateEventArgs.cs
@@ -0,0 +1,6 @@
+namespace Logo.TurtleInterfaces
+{
+ public class SpeedUpdateEventArgs
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/LogoScene.csproj b/src/LOGO/LogoScene/LogoScene.csproj
new file mode 100644
index 00000000..c3a3bfe3
--- /dev/null
+++ b/src/LOGO/LogoScene/LogoScene.csproj
@@ -0,0 +1,339 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {032211BF-D5A1-4177-BB41-0FC32D57D56C}
+ WinExe
+ LogoScene
+ LogoScene
+ v4.6.1
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MainWindow.xaml
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ App.xaml
+ Code
+
+
+ DrawingScene.xaml
+
+
+ TurtleControl.xaml
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+ {6e5f1b5d-f165-4cec-a240-8887ebd28e3b}
+ EditorPluginInterfaces
+
+
+ {522a914e-b787-43b6-9630-b169c8c3441b}
+ Interpreters
+
+
+ {8b9c8d76-65b3-4a01-9d6f-b6192a823642}
+ PluginManager
+
+
+ {9e7065a4-ba5e-4752-84bf-54d5c00db60c}
+ Repo
+
+
+ {1dcb1d77-ab11-404c-bce4-8eb7bf8f549d}
+ WpfControlsLib
+
+
+ {1d57e43c-c29e-4ea5-be01-028d73781637}
+ Interpreters.Logo
+
+
+ {69309937-d690-4365-85d8-698c30fceff4}
+ Logo.TurtleInterfaces
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\packages\Expression.Interaction\lib\net46\Microsoft.Expression.Interactions.dll
+ True
+ True
+
+
+ ..\..\..\packages\Expression.Interaction\lib\net46\System.Windows.Interactivity.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\..\packages\FSharp.Core\lib\net45\FSharp.Core.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ True
+
+
+ ..\..\..\packages\GraphX\lib\net40-client\GraphX.PCL.Common.dll
+ True
+ True
+
+
+ ..\..\..\packages\GraphX\lib\net40-client\GraphX.PCL.Logic.dll
+ True
+ True
+
+
+ ..\..\..\packages\GraphX\lib\net40-client\GraphX.WPF.Controls.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\..\packages\log4net\lib\net45-full\log4net.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\..\packages\QuickGraphPCL\lib\net40-client\QuickGraph.dll
+ True
+ True
+
+
+ ..\..\..\packages\QuickGraphPCL\lib\net40-client\QuickGraph.Data.dll
+ True
+ True
+
+
+ ..\..\..\packages\QuickGraphPCL\lib\net40-client\QuickGraph.Graphviz.dll
+ True
+ True
+
+
+ ..\..\..\packages\QuickGraphPCL\lib\net40-client\QuickGraph.Serialization.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ True
+
+
+ ..\..\..\packages\System.ValueTuple\lib\net461\System.ValueTuple.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\..\packages\System.Windows.Interactivity.WPF\lib\net40\Microsoft.Expression.Interactions.dll
+ True
+ True
+
+
+ ..\..\..\packages\System.Windows.Interactivity.WPF\lib\net40\System.Windows.Interactivity.dll
+ True
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/Models/Constants/Constants.cs b/src/LOGO/LogoScene/Models/Constants/Constants.cs
new file mode 100644
index 00000000..6599e934
--- /dev/null
+++ b/src/LOGO/LogoScene/Models/Constants/Constants.cs
@@ -0,0 +1,22 @@
+/* Copyright 2017-2019 REAL.NET group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. */
+namespace LogoScene.Models
+{
+ public static class Constants
+ {
+ public static double TurtleWidth = 36;
+
+ public static double TurtleHeight = 50;
+ }
+}
diff --git a/src/LOGO/LogoScene/Models/DataLayer/DrawingScene.cs b/src/LOGO/LogoScene/Models/DataLayer/DrawingScene.cs
new file mode 100644
index 00000000..dde377c5
--- /dev/null
+++ b/src/LOGO/LogoScene/Models/DataLayer/DrawingScene.cs
@@ -0,0 +1,61 @@
+using Logo.TurtleInterfaces;
+using LogoScene.Models.DataLayer;
+using System;
+using System.Collections.Generic;
+
+namespace LogoScene.Models
+{
+ internal class DrawingScene
+ {
+ public ITurtleCommanderAsync GetTurtleCommander() => turtleCommander;
+
+ public IEnumerable Lines => lines;
+
+ public event EventHandler MovementOnDrawingSceneStarted;
+
+ public event EventHandler LineAdded;
+
+ public DrawingScene()
+ {
+ this.turtleCommander = new TurtleCommanderAsync();
+ this.turtleCommander.MovementStarted += RaiseMovementOnDrawingSceneStarted;
+ }
+
+ public void NotifyMovementPerformed()
+ {
+ if (turtleCommander.Turtle.IsPenDown)
+ {
+ AddLine(startOfLine, endOfLine);
+ LineAdded?.Invoke(this, new LineEventArgs(startOfLine, endOfLine));
+ }
+ turtleCommander.NotifyMovementPerformed();
+ }
+
+ public void NotifyRotationPerformed() => turtleCommander.NotifyRotationPerformed();
+
+ public void NotifySpeedUpdatedPerformed() => turtleCommander.NotifySpeedUpdatedPerformed();
+
+ public void NotifyPenActionPerformed() => turtleCommander.NotifyPenActionPerformed();
+
+ private readonly TurtleCommanderAsync turtleCommander;
+
+ private List lines = new List();
+
+ private DoublePoint startOfLine;
+
+ private DoublePoint endOfLine;
+
+ private void RaiseMovementOnDrawingSceneStarted(object sender, LineEventArgs e)
+ {
+ startOfLine = e.StartPoint;
+ endOfLine = e.EndPoint;
+ MovementOnDrawingSceneStarted?.Invoke(this, e);
+ }
+
+ private void AddLine(DoublePoint start, DoublePoint end)
+ {
+ var line = new OrientedLine(start, end);
+ lines.Add(line);
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Models/DataLayer/Turtle.cs b/src/LOGO/LogoScene/Models/DataLayer/Turtle.cs
new file mode 100644
index 00000000..2f227ed5
--- /dev/null
+++ b/src/LOGO/LogoScene/Models/DataLayer/Turtle.cs
@@ -0,0 +1,58 @@
+using Logo.TurtleInterfaces;
+
+namespace LogoScene.Models.DataLayer
+{
+ internal class Turtle : ITurtle
+ {
+ public double Speed { get; private set; }
+
+ public double X { get; private set; }
+
+ public double Y { get; private set; }
+
+ public double Angle { get; private set; }
+
+ public bool IsPenDown { get; private set; }
+
+ public DoublePoint Position => new DoublePoint(this.X, this.Y);
+
+ public Turtle(double x, double y, double angle, bool isPenDown, double speed)
+ {
+ this.X = x;
+ this.Y = y;
+ this.Angle = angle;
+ this.IsPenDown = isPenDown;
+ this.Speed = speed;
+ }
+
+ public Turtle(double x, double y, double angle, bool isPenDown)
+ : this(x, y, angle, isPenDown, 1) { }
+
+ public void SetX(double newX) => this.X = newX;
+
+ public void SetY(double newY) => this.Y = newY;
+
+ public void SetSpeed(double newSpeed) => this.Speed = newSpeed;
+
+ public void SetIsPenDown(bool isPenDown) => this.IsPenDown = isPenDown;
+
+ public void SetAngle(double newAngle)
+ {
+ while (newAngle >= 360)
+ {
+ newAngle -= 360;
+ }
+ while (newAngle < 0)
+ {
+ newAngle += 360;
+ }
+ this.Angle = newAngle;
+ }
+
+ public void SetPosition(DoublePoint position)
+ {
+ this.X = position.X;
+ this.Y = position.Y;
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Models/DataLayer/TurtleCommander.cs b/src/LOGO/LogoScene/Models/DataLayer/TurtleCommander.cs
new file mode 100644
index 00000000..ecc2473a
--- /dev/null
+++ b/src/LOGO/LogoScene/Models/DataLayer/TurtleCommander.cs
@@ -0,0 +1,168 @@
+using Logo.TurtleInterfaces;
+using System;
+
+namespace LogoScene.Models.DataLayer
+{
+ internal class TurtleCommander : ITurtleCommanderAsync
+ {
+ public ITurtle Turtle => turtle;
+
+ public bool IsInProgress { get => inProgress; private set => inProgress = value; }
+
+ private readonly Turtle turtle;
+
+ private DoublePoint positionAfterMovement;
+
+ private volatile bool inProgress;
+
+ public TurtleCommander(Turtle turtle)
+ {
+ this.turtle = turtle;
+ this.positionAfterMovement = new DoublePoint(0, 0);
+ this.MovementPerformed += RaiseActionPerformed;
+ this.RotationPerformed += RaiseActionPerformed;
+ this.PenActionPerformed += RaiseActionPerformed;
+ this.SpeedUpdatedPerformed += RaiseActionPerformed;
+ }
+
+ public TurtleCommander()
+ : this(new Turtle(100, 100, 90, true))
+ { }
+
+ public event EventHandler ActionPerformed;
+
+ public event EventHandler PenActionPerformed;
+
+ public event EventHandler MovementPerformed;
+
+ public event EventHandler RotationPerformed;
+
+ public event EventHandler SpeedUpdatedPerformed;
+
+ public event EventHandler MovementStarted;
+
+ public event EventHandler RotationStarted;
+
+ public event EventHandler PenActionStarted;
+
+ public event EventHandler SpeedUpdateStarted;
+
+ public void MoveBackward(double distance)
+ {
+ if (distance < 0)
+ {
+ throw new ArgumentException("distance should be non-negative");
+ }
+ Move(-distance);
+ }
+
+ public void MoveForward(double distance)
+ {
+ if (distance < 0)
+ {
+ throw new ArgumentException("distance should be non-negative");
+ }
+ Move(distance);
+ }
+
+ public void PenDown()
+ {
+ turtle.SetIsPenDown(true);
+ inProgress = true;
+ PenActionStarted?.Invoke(this, new PenActionEventArgs());
+ }
+
+ public void PenUp()
+ {
+ turtle.SetIsPenDown(false);
+ inProgress = true;
+ PenActionStarted?.Invoke(this, new PenActionEventArgs());
+ }
+
+ public void RotateLeft(double degrees)
+ {
+ if (degrees < 0)
+ {
+ throw new ArgumentException("degrees should be non-negative");
+ }
+ turtle.SetAngle(turtle.Angle + degrees);
+ inProgress = true;
+ RotationStarted?.Invoke(this, new RotationEventArgs());
+ }
+
+ public void RotateRight(double degrees)
+ {
+ if (degrees < 0)
+ {
+ throw new ArgumentException("degrees should be non-negative");
+ }
+ turtle.SetAngle(turtle.Angle - degrees);
+ inProgress = true;
+ RotationStarted?.Invoke(this, new RotationEventArgs());
+ }
+
+ public void SetSpeed(double speed)
+ {
+ if (speed < 0)
+ {
+ throw new ArgumentException("speed should be non-negative");
+ }
+ turtle.SetSpeed(speed);
+ IsInProgress = true;
+ SpeedUpdateStarted?.Invoke(this, new SpeedUpdateEventArgs());
+ }
+
+ public void NotifyMovementPerformed()
+ {
+ lock (this)
+ {
+ turtle.SetX(positionAfterMovement.X);
+ turtle.SetY(positionAfterMovement.Y);
+ inProgress = false;
+ MovementPerformed?.Invoke(this, EventArgs.Empty);
+ }
+ }
+
+ public void NotifyRotationPerformed()
+ {
+ lock (this)
+ {
+ inProgress = false;
+ RotationPerformed?.Invoke(this, EventArgs.Empty);
+ }
+ }
+
+ public void NotifySpeedUpdatePerformed()
+ {
+ lock (this)
+ {
+ inProgress = false;
+ SpeedUpdatedPerformed?.Invoke(this, EventArgs.Empty);
+ }
+ }
+
+ public void NotifyPenActionPerformed()
+ {
+ lock (this)
+ {
+ inProgress = false;
+ PenActionPerformed?.Invoke(this, EventArgs.Empty);
+ }
+ }
+
+ private void Move(double distance)
+ {
+ var oldX = turtle.X;
+ var oldY = turtle.Y;
+ var angleInRadians = turtle.Angle * Math.PI / 180;
+ var newX = oldX + Math.Cos(angleInRadians) * distance;
+ var newY = oldY + Math.Sin(angleInRadians) * distance;
+ var oldPosition = new DoublePoint(oldX, oldY);
+ positionAfterMovement = new DoublePoint(newX, newY);
+ inProgress = true;
+ MovementStarted?.Invoke(this, new LineEventArgs(oldPosition, positionAfterMovement));
+ }
+
+ private void RaiseActionPerformed(object sender, EventArgs e) => ActionPerformed?.Invoke(this, EventArgs.Empty);
+ }
+}
diff --git a/src/LOGO/LogoScene/Models/DataLayer/TurtleCommanderAsync.cs b/src/LOGO/LogoScene/Models/DataLayer/TurtleCommanderAsync.cs
new file mode 100644
index 00000000..59ea0e60
--- /dev/null
+++ b/src/LOGO/LogoScene/Models/DataLayer/TurtleCommanderAsync.cs
@@ -0,0 +1,256 @@
+using log4net;
+using Logo.TurtleInterfaces;
+using LogoScene.Models.Log;
+using System;
+using System.Collections.Concurrent;
+
+namespace LogoScene.Models.DataLayer
+{
+ internal class TurtleCommanderAsync : ITurtleCommanderAsync
+ {
+ private readonly TurtleCommander turtleCommander;
+
+ private readonly ConcurrentQueue actionQueue;
+
+ private readonly ILog log = Logger.Log;
+
+ private object objectToLock = new object();
+
+ private TurtleCommanderAsync(TurtleCommander turtleCommander)
+ {
+ this.turtleCommander = turtleCommander;
+ this.actionQueue = new ConcurrentQueue();
+ this.ActionPerformed += OnActionPerformed;
+ }
+
+ public TurtleCommanderAsync()
+ : this(new TurtleCommander()) { }
+
+ public ITurtle Turtle => turtleCommander.Turtle;
+
+ public bool IsInProgress => turtleCommander.IsInProgress;
+
+ public event EventHandler PenActionPerformed
+ {
+ add
+ {
+ turtleCommander.PenActionPerformed += value;
+ }
+
+ remove
+ {
+ turtleCommander.PenActionPerformed -= value;
+ }
+ }
+
+ public event EventHandler MovementStarted
+ {
+ add
+ {
+ turtleCommander.MovementStarted += value;
+ }
+
+ remove
+ {
+ turtleCommander.MovementStarted -= value;
+ }
+ }
+
+ public event EventHandler ActionPerformed
+ {
+ add
+ {
+ turtleCommander.ActionPerformed += value;
+ }
+
+ remove
+ {
+ turtleCommander.ActionPerformed -= value;
+ }
+ }
+
+ public event EventHandler MovementPerformed
+ {
+ add
+ {
+ turtleCommander.MovementPerformed += value;
+ }
+
+ remove
+ {
+ turtleCommander.MovementPerformed -= value;
+ }
+ }
+
+ public event EventHandler RotationPerformed
+ {
+ add
+ {
+ turtleCommander.RotationPerformed += value;
+ }
+
+ remove
+ {
+ turtleCommander.RotationPerformed -= value;
+ }
+ }
+
+ public event EventHandler SpeedUpdatedPerformed
+ {
+ add
+ {
+ turtleCommander.SpeedUpdatedPerformed += value;
+ }
+
+ remove
+ {
+ turtleCommander.SpeedUpdatedPerformed -= value;
+ }
+ }
+
+ public event EventHandler RotationStarted
+ {
+ add
+ {
+ ((ITurtleCommanderAsync)turtleCommander).RotationStarted += value;
+ }
+
+ remove
+ {
+ turtleCommander.RotationStarted -= value;
+ }
+ }
+
+ public event EventHandler PenActionStarted
+ {
+ add
+ {
+ turtleCommander.PenActionStarted += value;
+ }
+
+ remove
+ {
+ turtleCommander.PenActionStarted -= value;
+ }
+ }
+
+ public event EventHandler SpeedUpdateStarted
+ {
+ add
+ {
+ turtleCommander.SpeedUpdateStarted += value;
+ }
+
+ remove
+ {
+ turtleCommander.SpeedUpdateStarted -= value;
+ }
+ }
+
+ public void MoveBackward(double distance)
+ {
+ lock (objectToLock)
+ {
+ Action action = () => { turtleCommander.MoveBackward(distance); };
+ AddActionToQueue(action);
+ }
+ }
+
+ public void MoveForward(double distance)
+ {
+ lock (objectToLock)
+ {
+ Action action = () => turtleCommander.MoveForward(distance);
+ AddActionToQueue(action);
+ }
+ }
+
+ public void PenDown()
+ {
+ lock (objectToLock)
+ {
+ Action action = () => turtleCommander.PenDown();
+ AddActionToQueue(action);
+ }
+ }
+
+ public void PenUp()
+ {
+ lock (objectToLock)
+ {
+ Action action = () => turtleCommander.PenUp();
+ AddActionToQueue(action);
+ }
+ }
+
+ public void RotateLeft(double degrees)
+ {
+ lock (objectToLock)
+ {
+ Action action = () => turtleCommander.RotateLeft(degrees);
+ AddActionToQueue(action);
+ }
+ }
+
+ public void RotateRight(double degrees)
+ {
+ lock (objectToLock)
+ {
+ Action action = () => turtleCommander.RotateRight(degrees);
+ AddActionToQueue(action);
+ }
+ }
+
+ public void SetSpeed(double speed)
+ {
+ lock (objectToLock)
+ {
+ Action action = () => turtleCommander.SetSpeed(speed);
+ AddActionToQueue(action);
+ }
+ }
+
+ public void NotifyMovementPerformed()
+ {
+ this.turtleCommander.NotifyMovementPerformed();
+ }
+
+ public void NotifyRotationPerformed() => this.turtleCommander.NotifyRotationPerformed();
+
+ public void NotifySpeedUpdatedPerformed() => this.turtleCommander.NotifySpeedUpdatePerformed();
+
+ public void NotifyPenActionPerformed() => this.turtleCommander.NotifyPenActionPerformed();
+
+ private void OnActionPerformed(object sender, EventArgs e)
+ {
+ lock (this)
+ {
+ if (!actionQueue.IsEmpty)
+ {
+ Action action;
+ var attempt = actionQueue.TryDequeue(out action);
+ if (!attempt)
+ {
+ throw new SystemException("can't get action from queue");
+ }
+ action?.Invoke();
+ }
+ }
+ }
+
+ private void AddActionToQueue(Action action)
+ {
+ lock (this)
+ {
+ if (actionQueue.IsEmpty && !turtleCommander.IsInProgress)
+ {
+ action?.Invoke();
+ }
+ else
+ {
+ actionQueue.Enqueue(action);
+ }
+ }
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Models/Log/Logger.cs b/src/LOGO/LogoScene/Models/Log/Logger.cs
new file mode 100644
index 00000000..971d93eb
--- /dev/null
+++ b/src/LOGO/LogoScene/Models/Log/Logger.cs
@@ -0,0 +1,15 @@
+using log4net;
+using log4net.Config;
+
+namespace LogoScene.Models.Log
+{
+ public static class Logger
+ {
+ public static ILog Log { get; } = LogManager.GetLogger("LOGGER");
+
+ public static void InitLogger()
+ {
+ XmlConfigurator.Configure();
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Operations/PointOperations.cs b/src/LOGO/LogoScene/Operations/PointOperations.cs
new file mode 100644
index 00000000..ea4a5ede
--- /dev/null
+++ b/src/LOGO/LogoScene/Operations/PointOperations.cs
@@ -0,0 +1,14 @@
+using Logo.TurtleInterfaces;
+
+
+namespace LogoScene.Operations
+{
+ public static class PointOperations
+ {
+ public static DoublePoint Plus(DoublePoint pointA, DoublePoint pointB) => new DoublePoint(pointA.X + pointB.X, pointA.Y + pointB.Y);
+
+ public static DoublePoint Minus(DoublePoint pointA, DoublePoint pointB) => new DoublePoint(pointA.X - pointB.X, pointA.Y - pointB.Y);
+
+ public static DoublePoint ScalarMultiply(double scalar, DoublePoint point) => new DoublePoint(scalar * point.X, scalar * point.Y);
+ }
+}
diff --git a/src/LOGO/LogoScene/ProgramRunner/Interpeter/LogoInterpeter.cs b/src/LOGO/LogoScene/ProgramRunner/Interpeter/LogoInterpeter.cs
new file mode 100644
index 00000000..3977111d
--- /dev/null
+++ b/src/LOGO/LogoScene/ProgramRunner/Interpeter/LogoInterpeter.cs
@@ -0,0 +1,19 @@
+using Repo;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LogoScene.ProgramRunner.Interpeter
+{
+ public class LogoInterpeter
+ {
+ LogoInterpeter(IModel model)
+ {
+ Model = model;
+ }
+
+ public IModel Model { get; }
+ }
+}
diff --git a/src/LOGO/LogoScene/ProgramRunner/ProgramRunner.cs b/src/LOGO/LogoScene/ProgramRunner/ProgramRunner.cs
new file mode 100644
index 00000000..c0246b6b
--- /dev/null
+++ b/src/LOGO/LogoScene/ProgramRunner/ProgramRunner.cs
@@ -0,0 +1,103 @@
+using EditorPluginInterfaces;
+using Interpreters.Logo.LogoInterpeter;
+using Logo.TurtleInterfaces;
+using Repo;
+using System.Collections.Generic;
+using System.Linq;
+using Interpreters.Logo.LogoSpecific;
+using Interpreters;
+using System;
+
+namespace LogoScene.ProgramRunner
+{
+ public class ProgramRunner
+ {
+ private readonly ITurtleCommanderAsync commander;
+
+ private readonly IToolbar toolbar;
+
+ private readonly IConsole console;
+
+ private readonly IRepo repo;
+
+ private IModel model;
+
+ public ProgramRunner(ITurtleCommanderAsync commander, IToolbar toolbar, IConsole console, IRepo repo)
+ {
+ this.commander = commander;
+ this.toolbar = toolbar;
+ this.console = console;
+ this.repo = repo;
+ AddButtons();
+ }
+
+ public void SetModel(string modelName) => this.model = repo.Model(modelName);
+
+ private void AddButtons()
+ {
+ var command = new WpfControlsLib.Controls.Toolbar.Command(LaunchProgram);
+ var pictureLocation = "pack://application:,,,/" + "View/Pictures/Toolbar/play.png";
+ var button = new WpfControlsLib.Controls.Toolbar.Button(command, "Run program", pictureLocation);
+ toolbar.AddButton(button);
+ }
+
+ private void LaunchProgram()
+ {
+ if (model == null)
+ {
+ console.ReportError("No model selected");
+ }
+ else
+ {
+ var list = RunProgram(this.model);
+ RunCommandList(list);
+ }
+ }
+
+ private List RunProgram(Repo.IModel model)
+ {
+ var runner = new LogoRunner(model);
+ try
+ {
+ runner.Run();
+ }
+ catch (ParserException e)
+ {
+ console.ReportError(e.Message);
+ }
+ ILogoContext context = runner.SpecificContext;
+ var commandList = context.LogoCommands.ToList();
+ commandList.Reverse();
+ return commandList;
+ }
+
+ private void RunCommandList(List list)
+ {
+ foreach (var command in list)
+ {
+ // clumsy: fix it
+ if (command is LogoForward)
+ {
+ var forward = (LogoForward)command;
+ this.commander.MoveForward(forward.Distance);
+ }
+ else if (command is LogoBackward)
+ {
+ var backward = (LogoBackward)command;
+ this.commander.MoveBackward(backward.Distance);
+ }
+ else if (command is LogoRight)
+ {
+ var right = (LogoRight)command;
+ this.commander.RotateRight(right.Degrees);
+ }
+ else if (command is LogoLeft)
+ {
+ var left = (LogoLeft)command;
+ this.commander.RotateLeft(left.Degrees);
+ }
+ else { }
+ }
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Properties/AssemblyInfo.cs b/src/LOGO/LogoScene/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..fd9b994e
--- /dev/null
+++ b/src/LOGO/LogoScene/Properties/AssemblyInfo.cs
@@ -0,0 +1,53 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// Общие сведения об этой сборке предоставляются следующим набором
+// набор атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
+// связанные со сборкой.
+[assembly: AssemblyTitle("LogoScene")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("LogoScene")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми
+// для компонентов COM. Если необходимо обратиться к типу в этой сборке через
+// из модели COM, установите атрибут ComVisible для этого типа в значение true.
+[assembly: ComVisible(false)]
+
+//Чтобы начать создание локализуемых приложений, задайте
+//CultureYouAreCodingWith в файле .csproj
+//в . Например, при использовании английского (США)
+//в своих исходных файлах установите в en-US. Затем отмените преобразование в комментарий
+//атрибута NeutralResourceLanguage ниже. Обновите "en-US" в
+//строка внизу для обеспечения соответствия настройки UICulture в файле проекта.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //где расположены словари ресурсов по конкретным тематикам
+ //(используется, если ресурс не найден на странице,
+ // или в словарях ресурсов приложения)
+ ResourceDictionaryLocation.SourceAssembly //где расположен словарь универсальных ресурсов
+ //(используется, если ресурс не найден на странице,
+ // в приложении или в каких-либо словарях ресурсов для конкретной темы)
+)]
+
+
+// Сведения о версии для сборки включают четыре следующих значения:
+//
+// Основной номер версии
+// Дополнительный номер версии
+// Номер сборки
+// Номер редакции
+//
+// Можно задать все значения или принять номера сборки и редакции по умолчанию
+// используя "*", как показано ниже:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/LOGO/LogoScene/Properties/Resources.Designer.cs b/src/LOGO/LogoScene/Properties/Resources.Designer.cs
new file mode 100644
index 00000000..ee95abdc
--- /dev/null
+++ b/src/LOGO/LogoScene/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// Этот код был создан программным средством.
+// Версия среды выполнения: 4.0.30319.42000
+//
+// Изменения в этом файле могут привести к неправильному поведению и будут утрачены, если
+// код создан повторно.
+//
+//------------------------------------------------------------------------------
+
+namespace LogoScene.Properties
+{
+
+
+ ///
+ /// Класс ресурсов со строгим типом для поиска локализованных строк и пр.
+ ///
+ // Этот класс был автоматически создан при помощи StronglyTypedResourceBuilder
+ // класс с помощью таких средств, как ResGen или Visual Studio.
+ // Для добавления или удаления члена измените файл .ResX, а затем перезапустите ResGen
+ // с параметром /str или заново постройте свой VS-проект.
+ [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()
+ {
+ }
+
+ ///
+ /// Возврат кэшированного экземпляра ResourceManager, используемого этим классом.
+ ///
+ [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("LogoScene.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Переопределяет свойство CurrentUICulture текущего потока для всех
+ /// подстановки ресурсов с помощью этого класса ресурсов со строгим типом.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Properties/Resources.resx b/src/LOGO/LogoScene/Properties/Resources.resx
new file mode 100644
index 00000000..af7dbebb
--- /dev/null
+++ b/src/LOGO/LogoScene/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/Properties/Settings.Designer.cs b/src/LOGO/LogoScene/Properties/Settings.Designer.cs
new file mode 100644
index 00000000..3f101164
--- /dev/null
+++ b/src/LOGO/LogoScene/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// 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.
+//
+//------------------------------------------------------------------------------
+
+namespace LogoScene.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/src/LOGO/LogoScene/Properties/Settings.settings b/src/LOGO/LogoScene/Properties/Settings.settings
new file mode 100644
index 00000000..033d7a5e
--- /dev/null
+++ b/src/LOGO/LogoScene/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/TurtleInterfaces/ITurtleCommanderAsync.cs b/src/LOGO/LogoScene/TurtleInterfaces/ITurtleCommanderAsync.cs
new file mode 100644
index 00000000..3d9e3049
--- /dev/null
+++ b/src/LOGO/LogoScene/TurtleInterfaces/ITurtleCommanderAsync.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Logo.TurtleInterfaces
+{
+ public interface ITurtleCommanderAsync : ITurtleCommander
+ {
+ event EventHandler MovementStarted;
+
+ event EventHandler RotationStarted;
+
+ event EventHandler PenActionStarted;
+
+ event EventHandler SpeedUpdateStarted;
+
+ event EventHandler ActionPerformed;
+
+ event EventHandler MovementPerformed;
+
+ event EventHandler RotationPerformed;
+
+ event EventHandler PenActionPerformed;
+
+ event EventHandler SpeedUpdatedPerformed;
+
+ bool IsInProgress { get; }
+ }
+}
diff --git a/src/LOGO/LogoScene/TurtleInterfaces/OrientedLine.cs b/src/LOGO/LogoScene/TurtleInterfaces/OrientedLine.cs
new file mode 100644
index 00000000..9ac67213
--- /dev/null
+++ b/src/LOGO/LogoScene/TurtleInterfaces/OrientedLine.cs
@@ -0,0 +1,20 @@
+namespace Logo.TurtleInterfaces
+{
+ public struct OrientedLine
+ {
+ public OrientedLine(DoublePoint start, DoublePoint end)
+ {
+ Start = start;
+ End = end;
+ }
+
+ public DoublePoint Start { get; }
+
+ public DoublePoint End { get; }
+
+ public override string ToString()
+ {
+ return $"{Start}, {End}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/View/MainWindow.xaml b/src/LOGO/LogoScene/View/MainWindow.xaml
new file mode 100644
index 00000000..fd1b2138
--- /dev/null
+++ b/src/LOGO/LogoScene/View/MainWindow.xaml
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Interpreter
+
+
+
+
+
+ Editor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/View/MainWindow.xaml.cs b/src/LOGO/LogoScene/View/MainWindow.xaml.cs
new file mode 100644
index 00000000..e627673d
--- /dev/null
+++ b/src/LOGO/LogoScene/View/MainWindow.xaml.cs
@@ -0,0 +1,264 @@
+/* Copyright 2017-2018 REAL.NET group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. */
+
+namespace WpfEditor.View
+{
+ using EditorPluginInterfaces;
+ using LogoScene.ViewModels;
+ using PluginManager;
+ using Repo;
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Windows;
+ using System.Windows.Controls;
+ using WpfControlsLib.Controls.AttributesPanel;
+ using WpfControlsLib.Controls.Console;
+ using WpfControlsLib.Controls.ModelSelector;
+ using WpfControlsLib.Controls.Scene;
+ using WpfControlsLib.Controls.Toolbar;
+ using Palette = WpfControlsLib.Controls.Palette.Palette;
+
+ ///
+ /// Main window of the application, launches on application startup.
+ ///
+ internal partial class MainWindow : INotifyPropertyChanged
+ {
+ private readonly WpfControlsLib.Model.SceneModel model;
+
+ private readonly WpfControlsLib.Controller.Controller controller;
+
+ private LogoScene.ProgramRunner.ProgramRunner programRunner;
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public event Action OnModelChanged;
+
+ public AppConsoleViewModel Console { get; } = new AppConsoleViewModel();
+
+ public ToolbarViewModel Toolbar { get; } = new ToolbarViewModel();
+
+ public DrawingSceneViewModel DrawingScene { get; } = new DrawingSceneViewModel();
+
+ public AttributesPanelViewModel AttributesPanel { get; } = new AttributesPanelViewModel();
+
+ public string WindowTitle
+ {
+ get
+ {
+ var fileName = (model == null || model.CurrentFileName == "")
+ ? "(unsaved)"
+ : model.CurrentFileName;
+ var unsavedChanges = model?.HasUnsavedChanges == true ? "*" : "";
+ return $"REAL.NET {fileName} {unsavedChanges}";
+ }
+ }
+
+ public MainWindow()
+ {
+ // TODO: Fix sequential coupling here.
+ this.DataContext = this;
+ this.InitializeComponent();
+
+ this.model = new WpfControlsLib.Model.SceneModel();
+
+ this.model.Reinit += this.Reinit;
+
+ this.model.FileSaved += (_, __) => NotifyTitleChanged();
+ this.model.UnsavedChanges += (_, __) => NotifyTitleChanged();
+
+ // Notifying window first time, to initialize title.
+ NotifyTitleChanged();
+
+ this.palette.SetModel(this.model);
+
+ this.controller = new WpfControlsLib.Controller.Controller();
+
+ this.Closed += this.CloseChildrenWindows;
+
+ this.scene.ElementManipulationDone += (sender, args) => this.palette.ClearSelection();
+ this.scene.ElementAdded += (sender, args) => this.modelExplorer.NewElement(args.Element);
+ this.scene.ElementRemoved += (sender, args) => this.modelExplorer.RemoveElement(args.Element);
+ this.scene.NodeSelected += (sender, args) => this.AttributesPanel.Attributes = args.Node.Attributes;
+ this.scene.EdgeSelected += (sender, args) => this.AttributesPanel.Attributes = args.Edge.Attributes;
+
+ this.scene.Init(this.model, this.controller, new PaletteAdapter(this.palette));
+
+ this.InitAndLaunchPlugins();
+ this.InitToolbar();
+ this.InitProgramRunner();
+
+ this.modelSelector.Init(this.model);
+ this.modelSelector.ChangeModel(0);
+ }
+
+ private void Reinit(object sender, EventArgs e)
+ {
+ this.SelectModel(this.modelSelector.ModelNames[2]);
+ }
+
+ private void OnModelSelectionChanged(object sender, ModelSelector.ModelSelectedEventArgs args)
+ {
+ SelectModel(args.ModelName);
+ }
+
+ private void SelectModel(string modelName)
+ {
+ this.scene.Clear();
+ this.modelExplorer.Clear();
+ this.model.ModelName = modelName;
+ this.palette.InitPalette(this.model.ModelName);
+ this.scene.Reload();
+ this.OnModelChanged?.Invoke(this.model.ModelName);
+ this.programRunner.SetModel(modelName);
+ }
+
+ private void InitToolbar()
+ {
+ this.Console.Messages.Add("Initializing ToolBar");
+ var sample = new WpfControlsLib.Controls.Toolbar.StandardButtonsAndMenus.SampleButtonsCollection(this.Console, this.controller);
+ var buttons = sample.SampleButtons;
+ foreach (var button in buttons)
+ {
+ this.Toolbar.AddButton(button);
+ }
+ }
+
+ private void InitAndLaunchPlugins()
+ {
+ var libs = new PluginLauncher();
+ const string folder = "../../../../plugins";
+ var pluginDirs = new List(System.IO.Directory.GetDirectories(folder));
+ foreach (var plugindir in pluginDirs)
+ {
+ var dirs = new List(System.IO.Directory.GetDirectories(plugindir + "/bin"));
+ var config = new PluginConfig(this.model, null, null, this.Console, null, this.leftPanelGrid);
+ config.ChangeModelSelectorVisibility = (x) => { this.modelSelector.SelectorVisibility = x; };
+ config.ChangeModel = this.SelectModel;
+ foreach (var dir in dirs)
+ {
+ libs.LaunchPlugins(dir, config);
+ }
+
+ if (config.OnMainModelChanged != null)
+ {
+ this.OnModelChanged += new Action(config.OnMainModelChanged);
+ }
+ }
+ }
+
+ private void CloseChildrenWindows(object sender, EventArgs e)
+ {
+ foreach (Window w in Application.Current.Windows)
+ {
+ w.Close();
+ }
+ }
+
+ private void AttributesViewCellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
+ => this.scene.ChangeEdgeLabel(((TextBox)e.EditingElement).Text);
+
+ private class PaletteAdapter : IElementProvider
+ {
+ private readonly Palette palette;
+
+ internal PaletteAdapter(Palette palette)
+ {
+ this.palette = palette;
+ }
+
+ public IElement Element => this.palette.SelectedElement;
+ }
+
+ private void NotifyTitleChanged() => this.PropertyChanged?.Invoke(
+ this,
+ new PropertyChangedEventArgs(nameof(this.WindowTitle))
+ );
+
+ private void OnCanExecuteForAlwaysExecutable(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
+ {
+ e.CanExecute = true;
+ }
+
+ private void OnNewExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
+ {
+ this.model.New();
+ this.controller.ClearHistory();
+ NotifyTitleChanged();
+ }
+
+ private void OnOpenExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
+ {
+ var dialog = new Microsoft.Win32.OpenFileDialog
+ {
+ DefaultExt = ".rns",
+ Filter = "Real.NET Saves (.rns)|*.rns"
+ };
+
+ var result = dialog.ShowDialog();
+
+ // Get the selected file name and display in a TextBox
+ if (result == true)
+ {
+ model.Open(dialog.FileName);
+ this.controller.ClearHistory();
+ NotifyTitleChanged();
+ }
+ }
+
+ private void OnSaveExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
+ {
+ if (this.model.CurrentFileName == string.Empty)
+ {
+ this.SaveAs();
+ }
+ else
+ {
+ this.model.Save();
+ }
+ }
+
+ private void OnSaveAsExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
+ {
+ SaveAs();
+ }
+
+ private void OnQuitExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
+ {
+ this.Close();
+ }
+
+ private void SaveAs()
+ {
+ var dialog = new Microsoft.Win32.SaveFileDialog
+ {
+ DefaultExt = ".rns",
+ Filter = "Real.NET Saves|*.rns"
+ };
+
+ var result = dialog.ShowDialog();
+
+ // Get the selected file name and display in a TextBox
+ if (result == true)
+ {
+ model.SaveAs(dialog.FileName);
+ }
+ }
+
+ private void InitProgramRunner()
+ {
+ programRunner = new LogoScene.ProgramRunner.ProgramRunner(this.DrawingScene.TurtleCommander, this.Toolbar, this.Console, this.model.Repo);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LOGO/LogoScene/View/Pictures/LogoPictures/backward.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/backward.png
new file mode 100644
index 00000000..9fad7118
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/LogoPictures/backward.png differ
diff --git a/src/WpfControlsLib/Controls/Scene/Pictures/edge.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/edge.png
similarity index 100%
rename from src/WpfControlsLib/Controls/Scene/Pictures/edge.png
rename to src/LOGO/LogoScene/View/Pictures/LogoPictures/edge.png
diff --git a/src/WpfControlsLib/Controls/Scene/Pictures/finalBlock.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/finalBlock.png
similarity index 100%
rename from src/WpfControlsLib/Controls/Scene/Pictures/finalBlock.png
rename to src/LOGO/LogoScene/View/Pictures/LogoPictures/finalBlock.png
diff --git a/src/LOGO/LogoScene/View/Pictures/LogoPictures/forward.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/forward.png
new file mode 100644
index 00000000..9fd0b1d9
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/LogoPictures/forward.png differ
diff --git a/src/WpfControlsLib/Controls/Scene/Pictures/initialBlock.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/initialBlock.png
similarity index 100%
rename from src/WpfControlsLib/Controls/Scene/Pictures/initialBlock.png
rename to src/LOGO/LogoScene/View/Pictures/LogoPictures/initialBlock.png
diff --git a/src/LOGO/LogoScene/View/Pictures/LogoPictures/left.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/left.png
new file mode 100644
index 00000000..b37beec6
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/LogoPictures/left.png differ
diff --git a/src/LOGO/LogoScene/View/Pictures/LogoPictures/penDown.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/penDown.png
new file mode 100644
index 00000000..73a122ca
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/LogoPictures/penDown.png differ
diff --git a/src/LOGO/LogoScene/View/Pictures/LogoPictures/penUp.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/penUp.png
new file mode 100644
index 00000000..ee5f5ea4
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/LogoPictures/penUp.png differ
diff --git a/src/LOGO/LogoScene/View/Pictures/LogoPictures/repeat.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/repeat.png
new file mode 100644
index 00000000..6ebbf6ae
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/LogoPictures/repeat.png differ
diff --git a/src/LOGO/LogoScene/View/Pictures/LogoPictures/right.png b/src/LOGO/LogoScene/View/Pictures/LogoPictures/right.png
new file mode 100644
index 00000000..bb950cbd
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/LogoPictures/right.png differ
diff --git a/src/LOGO/LogoScene/View/Pictures/Toolbar/play.png b/src/LOGO/LogoScene/View/Pictures/Toolbar/play.png
new file mode 100644
index 00000000..df170ce9
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/Toolbar/play.png differ
diff --git a/src/LOGO/LogoScene/View/Pictures/Toolbar/redo.png b/src/LOGO/LogoScene/View/Pictures/Toolbar/redo.png
new file mode 100644
index 00000000..db5a8939
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/Toolbar/redo.png differ
diff --git a/src/LOGO/LogoScene/View/Pictures/Toolbar/undo.png b/src/LOGO/LogoScene/View/Pictures/Toolbar/undo.png
new file mode 100644
index 00000000..bfd2050a
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/Toolbar/undo.png differ
diff --git a/src/LOGO/LogoScene/View/Pictures/vertex.png b/src/LOGO/LogoScene/View/Pictures/vertex.png
new file mode 100644
index 00000000..1a8827f8
Binary files /dev/null and b/src/LOGO/LogoScene/View/Pictures/vertex.png differ
diff --git a/src/WpfControlsLib/View/Templates/EditorTemplate.xaml b/src/LOGO/LogoScene/View/Templates/EditorTemplate.xaml
similarity index 100%
rename from src/WpfControlsLib/View/Templates/EditorTemplate.xaml
rename to src/LOGO/LogoScene/View/Templates/EditorTemplate.xaml
diff --git a/src/WpfEditor/View/Templates/GeneralTemplate.xaml b/src/LOGO/LogoScene/View/Templates/GeneralTemplate.xaml
similarity index 92%
rename from src/WpfEditor/View/Templates/GeneralTemplate.xaml
rename to src/LOGO/LogoScene/View/Templates/GeneralTemplate.xaml
index b83caf72..e46f3472 100644
--- a/src/WpfEditor/View/Templates/GeneralTemplate.xaml
+++ b/src/LOGO/LogoScene/View/Templates/GeneralTemplate.xaml
@@ -18,7 +18,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="http://schemas.panthernet.ru/graphx/"
xmlns:scene="clr-namespace:WpfControlsLib.Controls.Scene;assembly=WpfControlsLib">
-
+
@@ -75,7 +98,7 @@
-
@@ -159,7 +182,6 @@
-
diff --git a/src/WpfControlsLib/Controls/Scene/VirtualVertexData.cs b/src/WpfControlsLib/Controls/Scene/VirtualVertexData.cs
new file mode 100644
index 00000000..84229b58
--- /dev/null
+++ b/src/WpfControlsLib/Controls/Scene/VirtualVertexData.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using WpfControlsLib.ViewModel;
+
+namespace WpfControlsLib.Controls.Scene
+{
+ public class VirtualVertexData : NodeViewModel
+ {
+ private string picture = @"View/Pictures/vertex.png";
+
+ public VirtualVertexData() : base()
+ {
+ this.IsVirtual = true;
+ this.Picture = this.picture;
+ this.BorderColor = Brushes.Black;
+ this.Color = Brushes.Gray;
+ }
+
+ public static bool IsVirtualVertex(NodeViewModel node) => node is VirtualVertexData;
+ }
+}
diff --git a/src/WpfControlsLib/Controls/Toolbar/Button.cs b/src/WpfControlsLib/Controls/Toolbar/Button.cs
index c8b42ccf..73b249e1 100644
--- a/src/WpfControlsLib/Controls/Toolbar/Button.cs
+++ b/src/WpfControlsLib/Controls/Toolbar/Button.cs
@@ -14,9 +14,9 @@
namespace WpfControlsLib.Controls.Toolbar
{
- using System;
using EditorPluginInterfaces;
using EditorPluginInterfaces.Toolbar;
+ using System;
///
/// Class that implements IButton interface
@@ -28,9 +28,9 @@ public class Button : IButton
///
/// Command
/// Description of command
- /// Image to attachImage to attach
/// Is this button should be enabled
- public Button(ICommand command, string description, string image, bool isEnabled)
+ public Button(ICommand command, string description, string image, bool isEnabled = true)
{
this.Command = command;
this.Description = description;
@@ -38,16 +38,6 @@ public Button(ICommand command, string description, string image, bool isEnabled
this.IsEnabled = isEnabled;
}
- ///
- /// Initializes a new instance of the class.
- /// Default : isEnabled = true
- ///
- /// Command
- /// Description of command
- /// Image to attach
/// Throws when button's visibility changed
///
@@ -73,10 +63,10 @@ public Button(ICommand command, string description, string image)
///
public bool IsEnabled { get; private set; }
- ///
- /// Sets this button enabled
- ///
- public void SetEnabled()
+ ///
+ /// Sets this button enabled
+ ///
+ public void SetEnabled()
{
this.IsEnabled = true;
this.ThrowButtonEnabledChanged();
diff --git a/src/WpfControlsLib/Controls/Toolbar/ButtonWrapper.cs b/src/WpfControlsLib/Controls/Toolbar/ButtonWrapper.cs
index 2e084491..daa5c7be 100644
--- a/src/WpfControlsLib/Controls/Toolbar/ButtonWrapper.cs
+++ b/src/WpfControlsLib/Controls/Toolbar/ButtonWrapper.cs
@@ -1,9 +1,9 @@
namespace WpfControlsLib.Controls.Toolbar
{
- using System;
- using System.ComponentModel;
using EditorPluginInterfaces;
using EditorPluginInterfaces.Toolbar;
+ using System;
+ using System.ComponentModel;
public class ButtonWrapper : IButton, INotifyPropertyChanged
{
diff --git a/src/WpfControlsLib/Controls/Toolbar/Command.cs b/src/WpfControlsLib/Controls/Toolbar/Command.cs
index da77885a..d7c591d3 100644
--- a/src/WpfControlsLib/Controls/Toolbar/Command.cs
+++ b/src/WpfControlsLib/Controls/Toolbar/Command.cs
@@ -14,8 +14,8 @@
namespace WpfControlsLib.Controls.Toolbar
{
- using System;
using EditorPluginInterfaces;
+ using System;
///
/// Class that implements pattern Command
diff --git a/src/WpfControlsLib/Controls/Toolbar/CommandXAMLAdapter.cs b/src/WpfControlsLib/Controls/Toolbar/CommandXAMLAdapter.cs
index 4f51cebb..59abaa06 100644
--- a/src/WpfControlsLib/Controls/Toolbar/CommandXAMLAdapter.cs
+++ b/src/WpfControlsLib/Controls/Toolbar/CommandXAMLAdapter.cs
@@ -1,7 +1,7 @@
namespace WpfControlsLib.Controls.Toolbar
{
- using System;
using EditorPluginInterfaces;
+ using System;
public class CommandXAMLAdapter : System.Windows.Input.ICommand
{
diff --git a/src/WpfControlsLib/Controls/Toolbar/StandardButtonsAndMenus/SampleButtonsCollection.cs b/src/WpfControlsLib/Controls/Toolbar/StandardButtonsAndMenus/SampleButtonsCollection.cs
index 35fb4476..fa336f53 100644
--- a/src/WpfControlsLib/Controls/Toolbar/StandardButtonsAndMenus/SampleButtonsCollection.cs
+++ b/src/WpfControlsLib/Controls/Toolbar/StandardButtonsAndMenus/SampleButtonsCollection.cs
@@ -1,25 +1,53 @@
namespace WpfControlsLib.Controls.Toolbar.StandardButtonsAndMenus
{
- using System.Collections.Generic;
using Controller;
using EditorPluginInterfaces;
using EditorPluginInterfaces.Toolbar;
+ using System.Collections.Generic;
public class SampleButtonsCollection
{
+ private IButton undoButton;
+ private IButton redoButton;
+
public SampleButtonsCollection(IConsole console, Controller controller)
{
var undoAction = new Command(() => { controller.Undo(); });
var redoAction = new Command(() => { controller.Redo(); });
var undoImage = "pack://application:,,,/" + "View/Pictures/Toolbar/undo.png";
var redoImage = "pack://application:,,,/" + "View/Pictures/Toolbar/redo.png";
- var undoButton = new Button(undoAction, "Undo button", undoImage);
- var redoButton = new Button(redoAction, "Redo Button", redoImage);
-
+ undoButton = new Button(undoAction, "Undo button", undoImage, false);
+ redoButton = new Button(redoAction, "Redo Button", redoImage, false);
+ controller.UndoAvailabilityChanged += OnUndoAvailabilityChanged;
+ controller.RedoAvailabilityChanged += OnRedoAvailabilityChanged;
this.SampleButtons.Add(undoButton);
this.SampleButtons.Add(redoButton);
}
+ private void OnRedoAvailabilityChanged(object sender, UndoRedoAvailabilityChangedArgs e)
+ {
+ if (e.IsAvailable)
+ {
+ redoButton.SetEnabled();
+ }
+ else
+ {
+ redoButton.SetDisabled();
+ }
+ }
+
+ private void OnUndoAvailabilityChanged(object sender, UndoRedoAvailabilityChangedArgs e)
+ {
+ if (e.IsAvailable)
+ {
+ undoButton.SetEnabled();
+ }
+ else
+ {
+ undoButton.SetDisabled();
+ }
+ }
+
public IList SampleButtons { get; private set; } = new List();
}
}
diff --git a/src/WpfControlsLib/Controls/Toolbar/ToolbarView.xaml b/src/WpfControlsLib/Controls/Toolbar/ToolbarView.xaml
index 57e3cd36..132dc74b 100644
--- a/src/WpfControlsLib/Controls/Toolbar/ToolbarView.xaml
+++ b/src/WpfControlsLib/Controls/Toolbar/ToolbarView.xaml
@@ -24,16 +24,28 @@
d:DesignWidth="300"
mc:Ignorable="d"
d:DataContext="{toolbar:ToolbarViewModel}">
-
+
-
+
+
+
+
+
+
+
diff --git a/src/WpfControlsLib/Controls/Toolbar/ToolbarViewModel.cs b/src/WpfControlsLib/Controls/Toolbar/ToolbarViewModel.cs
index 0d550fbb..2241d756 100644
--- a/src/WpfControlsLib/Controls/Toolbar/ToolbarViewModel.cs
+++ b/src/WpfControlsLib/Controls/Toolbar/ToolbarViewModel.cs
@@ -14,10 +14,11 @@
namespace WpfControlsLib.Controls.Toolbar
{
+ using EditorPluginInterfaces;
+ using EditorPluginInterfaces.Toolbar;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
- using EditorPluginInterfaces.Toolbar;
///
/// ViewModel for toolbar control, allows to register some commands and show them as buttons. Can be used from
diff --git a/src/WpfControlsLib/Model/Graph.cs b/src/WpfControlsLib/Model/Graph.cs
index 77bf11bf..ad928fc1 100644
--- a/src/WpfControlsLib/Model/Graph.cs
+++ b/src/WpfControlsLib/Model/Graph.cs
@@ -14,17 +14,18 @@
namespace WpfControlsLib.Model
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
+ using EditorPluginInterfaces;
using GraphX.PCL.Common;
using QuickGraph;
using Repo;
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
using ViewModel;
using WpfControlsLib.Controls.Scene.EventArguments;
///
- /// Represents diagram as GraphX graph. Wraps and synchronizes changes in repo and in GraphX
+ /// Represents diagram as GraphX graph. Wraps and synchronizes changes in repo and in GraphX
/// graph representation.
///
/// Also this class serves as a factory and container for ViewModels for various parts of visual model
@@ -33,9 +34,9 @@ namespace WpfControlsLib.Model
///
public class Graph
{
- private readonly Model model;
+ private readonly ISceneModel model;
- internal Graph(Model repoModel)
+ internal Graph(SceneModel repoModel)
{
this.model = repoModel;
this.DataGraph = new BidirectionalGraph();
@@ -43,6 +44,7 @@ internal Graph(Model repoModel)
this.model.NewEdgeAdded += (sender, args) => this.CreateEdge(args.Edge, args.Source, args.Target);
this.model.ElementRemoved += (sender, args) => this.RemoveElement(args.Element);
this.model.ElementCheck += (sender, args) => this.CheckElement(args.Element, args.IsAllowed);
+ this.model.NodeVisualChanged += OnNodeVisualChanged;
}
public event EventHandler DrawGraph;
@@ -55,6 +57,10 @@ internal Graph(Model repoModel)
public event EventHandler AddNewEdgeControl;
+ public event EventHandler NodeVisualChanged;
+
+ public event EventHandler EdgeVisualChanged;
+
public BidirectionalGraph DataGraph { get; }
// Should be replaced
@@ -110,7 +116,7 @@ public void InitModel(string modelName)
}
this.DataGraph.AddEdge(newEdge);
- this.ElementAdded?.Invoke(this, new ElementAddedEventArgs {Element = edge});
+ this.ElementAdded?.Invoke(this, new ElementAddedEventArgs { Element = edge });
}
this.DrawGraph?.Invoke(this, EventArgs.Empty);
@@ -215,6 +221,14 @@ private void CheckElement(IElement element, bool isAllowed)
nodeViewModel.IsAllowed = isAllowed;
}
}
+
+
+ private void OnNodeVisualChanged(object sender, VertexEventArgs e)
+ {
+ var node = e.Node;
+ var nodeData = this.DataGraph.Vertices.First(x => x.Node == e.Node);
+ this.NodeVisualChanged?.Invoke(this, new DataVertexArgs(){DataVertex = nodeData});
+ }
public class DataVertexArgs : EventArgs
{
diff --git a/src/WpfControlsLib/Model/Model.cs b/src/WpfControlsLib/Model/SceneModel.cs
similarity index 71%
rename from src/WpfControlsLib/Model/Model.cs
rename to src/WpfControlsLib/Model/SceneModel.cs
index 5d20b84c..8762bb4d 100644
--- a/src/WpfControlsLib/Model/Model.cs
+++ b/src/WpfControlsLib/Model/SceneModel.cs
@@ -12,10 +12,14 @@
* See the License for the specific language governing permissions and
* limitations under the License. */
+using Repo;
+using System.Collections.Generic;
+using System.Linq;
+
namespace WpfControlsLib.Model
{
- using System;
using EditorPluginInterfaces;
+ using System;
///
/// Model in MVC architecture. Wraps repository, provides operations like adding or removing models, edges and
@@ -24,11 +28,11 @@ namespace WpfControlsLib.Model
/// This class is a ground truth about visual model currently edited and is supposed to be used by all tools and
/// parts of an editor who need to listen for visual model changes and/or modify visual model.
///
- public class Model : IModel
+ public class SceneModel : ISceneModel
{
private bool hasUnsavedChanges = false;
- public Model()
+ public SceneModel()
{
this.Repo = global::Repo.RepoFactory.Create();
}
@@ -38,6 +42,10 @@ public Model()
public event EventHandler NewEdgeAdded;
public event EventHandler ElementRemoved;
+
+ public event EventHandler NodeVisualChanged;
+
+ public event EventHandler EdgeVisualChanged;
public event EventHandler ElementCheck;
@@ -70,15 +78,16 @@ public bool HasUnsavedChanges
{
get => hasUnsavedChanges;
- private set {
+ private set
+ {
if (hasUnsavedChanges && !value)
{
- hasUnsavedChanges = value;
+ hasUnsavedChanges = false;
FileSaved?.Invoke(this, EventArgs.Empty);
}
else if (!hasUnsavedChanges && value)
{
- hasUnsavedChanges = value;
+ hasUnsavedChanges = true;
UnsavedChanges?.Invoke(this, EventArgs.Empty);
}
}
@@ -133,7 +142,7 @@ public void SaveAs(string fileName)
this.Save();
}
- public void CreateNode(Repo.IElement element)
+ public Repo.INode CreateNode(Repo.IElement element, Repo.VisualPoint position)
{
if (string.IsNullOrEmpty(this.ModelName))
{
@@ -144,74 +153,92 @@ public void CreateNode(Repo.IElement element)
var model = this.Repo.Model(this.ModelName);
- var newNode = model.CreateElement(element) as Repo.INode;
- HasUnsavedChanges = true;
- this.RaiseNewVertex(newNode);
+ var newNode = model.CreateElement(element) as Repo.INode;
+ newNode.VisualInfo.Position = position;
+ HasUnsavedChanges = true;
+ this.RaiseNewVertex(newNode);
+ return newNode;
+ }
+
+ public Repo.IEdge CreateEdge(Repo.IEdge edge, Repo.IElement source, Repo.IElement destination)
+ {
+ var model = this.Repo.Model(this.ModelName);
+ var newEdge = model.CreateElement(edge as Repo.IElement) as Repo.IEdge;
+ newEdge.Name = "a" + edge.Name;
+ newEdge.From = source;
+ newEdge.To = destination;
+ HasUnsavedChanges = true;
+ this.RaiseNewEdge(newEdge, newEdge.From, newEdge.To);
+ return newEdge;
}
- public void CreateEdge(Repo.IEdge edge, Repo.IElement source, Repo.IElement destination)
+ public void RestoreElement(Repo.IElement element)
{
- var model = this.Repo.Model(this.ModelName);
- var newEdge = model.CreateElement(edge as Repo.IElement) as Repo.IEdge;
- newEdge.Name = "a" + edge.Name;
- newEdge.From = source;
- newEdge.To = destination;
- HasUnsavedChanges = true;
- this.RaiseNewEdge(newEdge, newEdge.From, newEdge.To);
+ var model = this.Repo.Model(this.ModelName);
+ model.RestoreElement(element);
+ // Raising new element
+ HasUnsavedChanges = true;
+ if (element is INode node)
+ {
+ this.RaiseNewVertex(node);
+ }
+ else if (element is IEdge edge)
+ {
+ this.RaiseNewEdge(edge, edge.From, edge.To);
+ }
}
public void RemoveElement(Repo.IElement element)
{
var model = this.Repo.Model(this.ModelName);
- model.DeleteElement(element);
+ var a = model.Elements.Count();
+ model.RemoveElement(element);
+ var b = model.Elements.Count();
HasUnsavedChanges = true;
this.RaiseElementRemoved(element);
}
+ public void UpdateNodeVisual(INode node, in IVisualNodeInfo nodeVisual)
+ {
+ node.VisualInfo = nodeVisual;
+ this.NodeVisualChanged?.Invoke(this, new VertexEventArgs(node));
+ }
+
+ public void UpdateEdgeVisual(IEdge edge, in IVisualEdgeInfo edgeVisual)
+ {
+ edge.VisualInfo = edgeVisual;
+ this.EdgeVisualChanged?.Invoke(this, new EdgeEventArgs(edge));
+ }
+
public void SetElementAllowed(Repo.IElement element, bool isAllowed)
=> this.RaiseElementCheck(element, isAllowed);
private void RaiseNewVertex(Repo.INode node)
{
- var args = new VertexEventArgs
- {
- Node = node
- };
-
+ var args = new VertexEventArgs(node);
this.NewVertexAdded?.Invoke(this, args);
}
private void RaiseNewEdge(Repo.IEdge edge, Repo.IElement prevVer, Repo.IElement ctrlVer)
{
var args = new EdgeEventArgs
- {
- Edge = edge,
- Source = prevVer,
- Target = ctrlVer
- };
-
+ (
+ edge,
+ prevVer,
+ ctrlVer
+ );
this.NewEdgeAdded?.Invoke(this, args);
}
private void RaiseElementRemoved(Repo.IElement element)
{
- var args = new ElementEventArgs
- {
- Element = element
- };
-
+ var args = new ElementEventArgs(element);
this.ElementRemoved?.Invoke(this, args);
}
private void RaiseElementCheck(Repo.IElement element, bool isAllowed)
{
- var args = new ElementEventArgs
- {
- Element = element,
- IsAllowed = isAllowed
- };
-
-
+ var args = new ElementEventArgs(element, isAllowed);
this.ElementCheck?.Invoke(this, args);
}
}
diff --git a/src/WpfControlsLib/ViewModel/EdgeViewModel.cs b/src/WpfControlsLib/ViewModel/EdgeViewModel.cs
index 14c90276..a2cf951d 100644
--- a/src/WpfControlsLib/ViewModel/EdgeViewModel.cs
+++ b/src/WpfControlsLib/ViewModel/EdgeViewModel.cs
@@ -1,10 +1,10 @@
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Windows.Media;
-using GraphX.Measure;
+using GraphX.Measure;
using GraphX.PCL.Common.Interfaces;
using GraphX.PCL.Common.Models;
using Repo;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows.Media;
namespace WpfControlsLib.ViewModel
{
diff --git a/src/WpfControlsLib/ViewModel/NodeViewModel.cs b/src/WpfControlsLib/ViewModel/NodeViewModel.cs
index 8dac7da4..f94d3c8d 100644
--- a/src/WpfControlsLib/ViewModel/NodeViewModel.cs
+++ b/src/WpfControlsLib/ViewModel/NodeViewModel.cs
@@ -1,9 +1,9 @@
-using System.Collections.Generic;
+using GraphX.PCL.Common.Models;
+using Repo;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Media;
-using GraphX.PCL.Common.Models;
-using Repo;
namespace WpfControlsLib.ViewModel
{
@@ -14,7 +14,7 @@ public class NodeViewModel : VertexBase, INotifyPropertyChanged
{
private Brush color = Brushes.Green;
private IList attributes = new List();
- private Brush borderColor = Brushes.White;
+ private Brush borderColor = Brushes.Black;
private bool isAllowed = true;
private string picture = string.Empty;
@@ -78,7 +78,7 @@ public IList Attributes
}
}
- public string Picture
+ public virtual string Picture
{
get => "pack://application:,,,/" + this.picture;
@@ -89,7 +89,7 @@ public string Picture
}
}
- public bool IsVirtual { get; set; } = false;
+ public bool IsVirtual { get; protected set; } = false;
public override string ToString()
{
diff --git a/src/WpfControlsLib/WpfControlsLib.csproj b/src/WpfControlsLib/WpfControlsLib.csproj
index 86a03736..d979f88c 100644
--- a/src/WpfControlsLib/WpfControlsLib.csproj
+++ b/src/WpfControlsLib/WpfControlsLib.csproj
@@ -102,6 +102,7 @@
AttributesPanel.xaml
+
AppConsole.xaml
@@ -125,6 +126,8 @@
+
+
@@ -138,6 +141,7 @@
Scene.xaml
+
@@ -147,7 +151,7 @@
ToolbarView.xaml
-
+
@@ -183,6 +187,10 @@
Designer
MSBuild:Compile
+
+ MSBuild:Compile
+ Designer
+
MSBuild:Compile
Designer
@@ -190,14 +198,6 @@
-
- MSBuild:Compile
- Designer
-
-
- MSBuild:Compile
- Designer
-
@@ -247,48 +247,6 @@
false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/WpfControlsLib/WpfControlsLib.csproj.DotSettings b/src/WpfControlsLib/WpfControlsLib.csproj.DotSettings
deleted file mode 100644
index 58ad6c88..00000000
--- a/src/WpfControlsLib/WpfControlsLib.csproj.DotSettings
+++ /dev/null
@@ -1,2 +0,0 @@
-
- CSharp71
\ No newline at end of file
diff --git a/src/WpfEditor/App.config b/src/WpfEditor/App.config
index c077b6dd..1afd8421 100644
--- a/src/WpfEditor/App.config
+++ b/src/WpfEditor/App.config
@@ -7,6 +7,6 @@
True
-
+
diff --git a/src/WpfEditor/View/MainWindow.xaml b/src/WpfEditor/View/MainWindow.xaml
index 297783a2..7d3809b3 100644
--- a/src/WpfEditor/View/MainWindow.xaml
+++ b/src/WpfEditor/View/MainWindow.xaml
@@ -40,14 +40,6 @@
-
-
-
-
-
-
-
-
diff --git a/src/WpfEditor/View/MainWindow.xaml.cs b/src/WpfEditor/View/MainWindow.xaml.cs
index 252aa84a..5213182e 100644
--- a/src/WpfEditor/View/MainWindow.xaml.cs
+++ b/src/WpfEditor/View/MainWindow.xaml.cs
@@ -14,19 +14,19 @@
namespace WpfEditor.View
{
+ using EditorPluginInterfaces;
+ using PluginManager;
+ using Repo;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
- using EditorPluginInterfaces;
- using PluginManager;
- using Repo;
+ using WpfControlsLib.Controls.AttributesPanel;
using WpfControlsLib.Controls.Console;
using WpfControlsLib.Controls.ModelSelector;
using WpfControlsLib.Controls.Scene;
using WpfControlsLib.Controls.Toolbar;
- using WpfControlsLib.Controls.AttributesPanel;
using Palette = WpfControlsLib.Controls.Palette.Palette;
///
@@ -34,7 +34,7 @@ namespace WpfEditor.View
///
internal partial class MainWindow : INotifyPropertyChanged
{
- private readonly WpfControlsLib.Model.Model model;
+ private readonly WpfControlsLib.Model.SceneModel model;
private readonly WpfControlsLib.Controller.Controller controller;
public event PropertyChangedEventHandler PropertyChanged;
@@ -58,14 +58,14 @@ public string WindowTitle
return $"REAL.NET {fileName} {unsavedChanges}";
}
}
-
+
public MainWindow()
{
// TODO: Fix sequential coupling here.
this.DataContext = this;
this.InitializeComponent();
- this.model = new WpfControlsLib.Model.Model();
+ this.model = new WpfControlsLib.Model.SceneModel();
this.model.Reinit += this.Reinit;
@@ -93,7 +93,7 @@ public MainWindow()
this.InitToolbar();
this.modelSelector.Init(this.model);
- this.modelSelector.ChangeModel(2);
+ this.modelSelector.ChangeModel(4);
}
private void Reinit(object sender, EventArgs e)
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/backward.png b/src/WpfEditor/View/Pictures/LogoPictures/backward.png
new file mode 100644
index 00000000..9fad7118
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/backward.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/edge.png b/src/WpfEditor/View/Pictures/LogoPictures/edge.png
new file mode 100644
index 00000000..63c483ab
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/edge.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/finalBlock.png b/src/WpfEditor/View/Pictures/LogoPictures/finalBlock.png
new file mode 100644
index 00000000..2e1d2aaf
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/finalBlock.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/forward.png b/src/WpfEditor/View/Pictures/LogoPictures/forward.png
new file mode 100644
index 00000000..9fd0b1d9
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/forward.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/initialBlock.png b/src/WpfEditor/View/Pictures/LogoPictures/initialBlock.png
new file mode 100644
index 00000000..6bb7ca67
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/initialBlock.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/left.png b/src/WpfEditor/View/Pictures/LogoPictures/left.png
new file mode 100644
index 00000000..b37beec6
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/left.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/penDown.png b/src/WpfEditor/View/Pictures/LogoPictures/penDown.png
new file mode 100644
index 00000000..73a122ca
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/penDown.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/penUp.png b/src/WpfEditor/View/Pictures/LogoPictures/penUp.png
new file mode 100644
index 00000000..ee5f5ea4
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/penUp.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/repeat.png b/src/WpfEditor/View/Pictures/LogoPictures/repeat.png
new file mode 100644
index 00000000..6ebbf6ae
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/repeat.png differ
diff --git a/src/WpfEditor/View/Pictures/LogoPictures/right.png b/src/WpfEditor/View/Pictures/LogoPictures/right.png
new file mode 100644
index 00000000..bb950cbd
Binary files /dev/null and b/src/WpfEditor/View/Pictures/LogoPictures/right.png differ
diff --git a/src/WpfEditor/View/Templates/EditorTemplate.xaml b/src/WpfEditor/View/Templates/EditorTemplate.xaml
index 198baf4b..23a4d240 100644
--- a/src/WpfEditor/View/Templates/EditorTemplate.xaml
+++ b/src/WpfEditor/View/Templates/EditorTemplate.xaml
@@ -39,7 +39,7 @@
-
+
+ -->
+ -->
\ No newline at end of file
diff --git a/src/WpfEditor/View/Validators/IntValidation.cs b/src/WpfEditor/View/Validators/IntValidation.cs
index 2e025537..98212107 100644
--- a/src/WpfEditor/View/Validators/IntValidation.cs
+++ b/src/WpfEditor/View/Validators/IntValidation.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows.Controls;
namespace WpfEditor.View.Validators
diff --git a/src/WpfEditor/WpfEditor.csproj b/src/WpfEditor/WpfEditor.csproj
index e1461afd..1bab5758 100644
--- a/src/WpfEditor/WpfEditor.csproj
+++ b/src/WpfEditor/WpfEditor.csproj
@@ -116,10 +116,6 @@
MSBuild:Compile
Designer
-
- MSBuild:Compile
- Designer
-
@@ -156,6 +152,17 @@
+
+
+
+
+
+
+
+
+
+
+
{6e5f1b5d-f165-4cec-a240-8887ebd28e3b}
EditorPluginInterfaces
@@ -173,6 +180,9 @@
WpfControlsLib
+
+
+
diff --git a/src/WpfEditor/paket.references b/src/WpfEditor/paket.references
index 8c1ccc03..54b99b6f 100644
--- a/src/WpfEditor/paket.references
+++ b/src/WpfEditor/paket.references
@@ -1,3 +1,3 @@
GraphX
-FSharp.Core
+FSharp.Core redirects:force
System.ValueTuple
\ No newline at end of file
diff --git a/src/plugins/SamplePlugin/SamplePlugin.cs b/src/plugins/SamplePlugin/SamplePlugin.cs
index af1a39c1..07e9bc70 100644
--- a/src/plugins/SamplePlugin/SamplePlugin.cs
+++ b/src/plugins/SamplePlugin/SamplePlugin.cs
@@ -12,12 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License. */
-using System.Linq;
-
namespace SamplePlugin
{
- using System;
using EditorPluginInterfaces;
+ using System;
///
/// This class is a sample plugin and is also used in unit tests to check plugin loading.
diff --git a/src/plugins/SamplePlugin/app.config b/src/plugins/SamplePlugin/app.config
index 6c060a74..10b094f8 100644
--- a/src/plugins/SamplePlugin/app.config
+++ b/src/plugins/SamplePlugin/app.config
@@ -4,6 +4,6 @@
True
-
+
diff --git a/tests/Interpreters.Logo.Tests/App.config b/tests/Interpreters.Logo.Tests/App.config
new file mode 100644
index 00000000..2ff85cbe
--- /dev/null
+++ b/tests/Interpreters.Logo.Tests/App.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+ True
+
+
+
+
\ No newline at end of file
diff --git a/tests/Interpreters.Logo.Tests/AssemblyInfo.fs b/tests/Interpreters.Logo.Tests/AssemblyInfo.fs
new file mode 100644
index 00000000..3325c340
--- /dev/null
+++ b/tests/Interpreters.Logo.Tests/AssemblyInfo.fs
@@ -0,0 +1,41 @@
+namespace Interpreters.Logo.Tests.AssemblyInfo
+
+open System.Reflection
+open System.Runtime.CompilerServices
+open System.Runtime.InteropServices
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+
+// 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.
+[]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[]
+
+// 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:
+// []
+[]
+[]
+
+do
+ ()
\ No newline at end of file
diff --git a/tests/Interpreters.Logo.Tests/Interpreters.Logo.Tests.fsproj b/tests/Interpreters.Logo.Tests/Interpreters.Logo.Tests.fsproj
new file mode 100644
index 00000000..9e112a0d
--- /dev/null
+++ b/tests/Interpreters.Logo.Tests/Interpreters.Logo.Tests.fsproj
@@ -0,0 +1,126 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ f457582f-2ddf-4706-ae22-de7214b88068
+ Library
+ Interpreters.Logo.Tests
+ Interpreters.Logo.Tests
+ true
+ v4.6.1
+ true
+ 3239;$(WarningsAsErrors)
+ Interpreters.Logo.Tests
+
+
+ true
+ full
+ false
+ false
+ bin\$(Configuration)\
+ DEBUG;TRACE
+ 3
+ bin\$(Configuration)\$(AssemblyName).XML
+
+
+ pdbonly
+ true
+ true
+ bin\$(Configuration)\
+ TRACE
+ 3
+ bin\$(Configuration)\$(AssemblyName).XML
+
+
+ 11
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
+
+
+
+
+
+ <__paket__NUnit3TestAdapter_props>net35\NUnit3TestAdapter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll
+ True
+
+
+
+
+ Interpreters
+ {522a914e-b787-43b6-9630-b169c8c3441b}
+ True
+
+
+ Interpreters.Logo
+ {1d57e43c-c29e-4ea5-be01-028d73781637}
+ True
+
+
+ Repo
+ {9e7065a4-ba5e-4752-84bf-54d5c00db60c}
+ True
+
+
+
+
+
+
+ ..\..\packages\tests\FSharp.Core\lib\net45\FSharp.Core.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\packages\tests\FsUnit\lib\net46\FsUnit.NUnit.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\packages\tests\NUnit\lib\net45\nunit.framework.dll
+ True
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Interpreters.Logo.Tests/LogoParserTests.fs b/tests/Interpreters.Logo.Tests/LogoParserTests.fs
new file mode 100644
index 00000000..00ea6ebf
--- /dev/null
+++ b/tests/Interpreters.Logo.Tests/LogoParserTests.fs
@@ -0,0 +1,85 @@
+module LogoParserTests
+
+open NUnit.Framework
+open FsUnit
+
+open Repo
+open Interpreters
+open Interpreters.VariableSet
+open Interpreters.Logo.LogoParser
+open Interpreters.Logo.TurtleCommand
+
+let repo = RepoFactory.Create()
+
+let metamodel = repo.Model "LogoMetamodel"
+
+let model = repo.Model "LogoModel"
+
+let isInitial (element: IElement) = element.Class.Name = "InitialNode"
+
+let isFinal (element: IElement) = element.Class.Name = "FinalNode"
+
+let initialNode = model.Elements |> Seq.filter (fun e -> e.Class.Name = "InitialNode") |> Seq.exactlyOne
+
+let finalNode = model.Elements |> Seq.filter (fun e -> e.Class.Name = "FinalNode") |> Seq.exactlyOne
+
+let findAllEdgesFrom (element: IElement) =
+ model.Edges |> Seq.filter (fun (e: IEdge) -> e.From = element)
+
+let findAllEdgesTo (element: IElement) =
+ model.Edges |> Seq.filter (fun (e: IEdge) -> e.To = element)
+
+let hasAttribute name (element: IElement) =
+ element.Attributes |> Seq.filter (fun x -> x.Name = name) |> Seq.isEmpty |> not
+
+let next (element: IElement) = let edge = findAllEdgesFrom element |> Seq.filter ((hasAttribute "Tag") >> not) |> Seq.exactlyOne in edge.To
+
+let repeat = next initialNode
+
+let firstForward = next repeat
+
+let firstRight = next firstForward
+
+let secondForward = next firstRight
+
+let emtyVariableSet = VariableSetFactory.CreateVariableSet([])
+
+[]
+let ``forward should be parsed correctly``() =
+ let context = {Commands = []}
+ let (parsing: Parsing) = { Variables = emtyVariableSet; Context = context; Model = model; Element = firstForward }
+ let wrapped = Some parsing
+ AvailableParsers.parseForward wrapped |> should not' (equal None)
+ let parsed = (AvailableParsers.parseForward wrapped).Value
+ Parsing.element parsed |> should be (equal firstRight)
+ let newContext = Parsing.context parsed
+ let command = newContext.Commands.Head
+ command |> should be (equal (LForward 100.0))
+
+[]
+let ``right should be parsed correctly``() =
+ let context = {Commands = [LForward 100.0]}
+ let (parsing: Parsing) = { Variables = emtyVariableSet; Context = context; Model = model; Element = firstRight }
+ let wrapped = Some parsing
+ AvailableParsers.parseRight wrapped |> should not' (equal None)
+ let parsed = (AvailableParsers.parseRight wrapped).Value
+ Parsing.element parsed |> should be (equal secondForward)
+ let newContext = Parsing.context parsed
+ let command = newContext.Commands.Head
+ command |> should be (equal (LRight 90.0))
+
+[]
+let ``complex movement parsing``() =
+ let context = {Commands = []}
+ let (parsing: Parsing) = { Variables = emtyVariableSet; Context = context; Model = model; Element = firstForward}
+ let wrapped = Some parsing
+ let parsedOnce = (parseMovement wrapped).Value
+ let parsedTwice = (parseMovement (Some parsedOnce)).Value
+ let newElement = Parsing.element parsedTwice
+ newElement |> should equal secondForward
+ let newContext = Parsing.context parsedTwice
+ newContext.Commands |> should be (equal [LRight 90.0; LForward 100.0])
+
+
+
+
diff --git a/tests/Interpreters.Logo.Tests/paket.references b/tests/Interpreters.Logo.Tests/paket.references
new file mode 100644
index 00000000..9458e732
--- /dev/null
+++ b/tests/Interpreters.Logo.Tests/paket.references
@@ -0,0 +1,5 @@
+group Tests
+FsUnit
+FSharp.Core
+NUnit
+NUnit3TestAdapter
\ No newline at end of file
diff --git a/tests/Interpreters.Tests/App.config b/tests/Interpreters.Tests/App.config
new file mode 100644
index 00000000..10b094f8
--- /dev/null
+++ b/tests/Interpreters.Tests/App.config
@@ -0,0 +1,9 @@
+
+
+
+
+ True
+
+
+
+
diff --git a/tests/Interpreters.Tests/AssemblyInfo.fs b/tests/Interpreters.Tests/AssemblyInfo.fs
new file mode 100644
index 00000000..9061a761
--- /dev/null
+++ b/tests/Interpreters.Tests/AssemblyInfo.fs
@@ -0,0 +1,41 @@
+namespace Interpreters.Tests.AssemblyInfo
+
+open System.Reflection
+open System.Runtime.CompilerServices
+open System.Runtime.InteropServices
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+
+// 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.
+[]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[]
+
+// 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:
+// []
+[]
+[]
+
+do
+ ()
\ No newline at end of file
diff --git a/tests/Interpreters.Tests/Interpreters.Tests.fsproj b/tests/Interpreters.Tests/Interpreters.Tests.fsproj
new file mode 100644
index 00000000..720bf0a5
--- /dev/null
+++ b/tests/Interpreters.Tests/Interpreters.Tests.fsproj
@@ -0,0 +1,119 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ 03a2352f-3c0c-4db2-929f-d822c4964bd5
+ Library
+ Interpreters.Tests
+ Interpreters.Tests
+ true
+ v4.6.1
+ true
+ 3239;$(WarningsAsErrors)
+ Interpreters.Tests
+
+
+ true
+ full
+ false
+ false
+ bin\$(Configuration)\
+ DEBUG;TRACE
+ 3
+ bin\$(Configuration)\$(AssemblyName).XML
+
+
+ pdbonly
+ true
+ true
+ bin\$(Configuration)\
+ TRACE
+ 3
+ bin\$(Configuration)\$(AssemblyName).XML
+
+
+ 11
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
+
+
+
+
+
+ <__paket__NUnit3TestAdapter_props>net35\NUnit3TestAdapter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll
+ True
+
+
+ Interpreters
+ {522a914e-b787-43b6-9630-b169c8c3441b}
+ True
+
+
+ Repo
+ {9e7065a4-ba5e-4752-84bf-54d5c00db60c}
+ True
+
+
+
+
+
+
+ ..\..\packages\tests\FSharp.Core\lib\net45\FSharp.Core.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\packages\tests\FsUnit\lib\net46\FsUnit.NUnit.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\packages\tests\NUnit\lib\net45\nunit.framework.dll
+ True
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Interpreters.Tests/VariableTests.fs b/tests/Interpreters.Tests/VariableTests.fs
new file mode 100644
index 00000000..e10862be
--- /dev/null
+++ b/tests/Interpreters.Tests/VariableTests.fs
@@ -0,0 +1,36 @@
+module VariableTests
+
+open NUnit.Framework
+open FsUnit
+
+open Interpreters
+
+// Regular type & module tests.
+[]
+let ``isTypesEqual for RegularType should be correct``() =
+ RegularType.isTypesEqual (Int 1) (Int 2) |> should be True
+ RegularType.isTypesEqual (Double 1.0) (Double 2.0) |> should be True
+ RegularType.isTypesEqual (Boolean true) (Boolean false) |> should be True
+ RegularType.isTypesEqual (Int 1) (Double 1.0) |> should be False
+
+// VariableValue type & module tests.
+[]
+let ``isTypesEqual for VariableValue should be correct``() =
+ VariableValue.isTypesEqual (Regular (Int 1)) (Regular (Int 2)) |> should be True
+ VariableValue.isTypesEqual (Regular (Int 1)) (Regular (Double 1.0)) |> should be False
+
+[]
+let ``isRegular should be correct``() =
+ VariableValue.isRegular (Regular (Int 1)) |> should be True
+ VariableValue.isRegular (Regular (Double 1.0)) |> should be True
+ VariableValue.isRegular (Complex) |> should be False
+
+// Variable type & module tests.
+[]
+let ``isTypesEqual for Variable sould be correct``() =
+ let doubleVar1 = Variable.createDouble "doubleVar1" 1.0 (None, None)
+ let doubleVar2 = Variable.createDouble "doubleVar2" 2.0 (None, None)
+ let intVar = Variable.createInt "intVar" 1 (None, None)
+ Variable.isTypesEqual doubleVar1 doubleVar2 |> should be True
+ Variable.isTypesEqual doubleVar1 intVar |> should be False
+
diff --git a/tests/Interpreters.Tests/paket.references b/tests/Interpreters.Tests/paket.references
new file mode 100644
index 00000000..9458e732
--- /dev/null
+++ b/tests/Interpreters.Tests/paket.references
@@ -0,0 +1,5 @@
+group Tests
+FsUnit
+FSharp.Core
+NUnit
+NUnit3TestAdapter
\ No newline at end of file
diff --git a/tests/PluginLibrary.Tests/PluginLibraryTests.cs b/tests/PluginLibrary.Tests/PluginLibraryTests.cs
index c2281ffd..894ca2f7 100644
--- a/tests/PluginLibrary.Tests/PluginLibraryTests.cs
+++ b/tests/PluginLibrary.Tests/PluginLibraryTests.cs
@@ -14,13 +14,12 @@
namespace PluginLibrary.Tests
{
- using System.Collections.Generic;
- using System.IO;
- using System.Windows.Controls;
using EditorPluginInterfaces;
using NSubstitute;
using NUnit.Framework;
using PluginManager;
+ using System.Collections.Generic;
+ using System.IO;
[TestFixture]
public class PluginLaunchTest
@@ -30,12 +29,12 @@ public void TestLaunchingSamplePlugin()
{
var libs = new PluginLauncher();
var folder = Path.Combine(
- TestContext.CurrentContext.TestDirectory,
+ TestContext.CurrentContext.TestDirectory,
"../../../../src/plugins/SamplePlugin/bin"
);
var dirs = new List(Directory.GetDirectories(folder));
var console = Substitute.For();
- var model = Substitute.For();
+ var model = Substitute.For();
var config = new PluginConfig(model, null, null, console, null, null);
foreach (var dir in dirs)
{
diff --git a/tests/PluginLibrary.Tests/Properties/AssemblyInfo.cs b/tests/PluginLibrary.Tests/Properties/AssemblyInfo.cs
index 01814721..a1ef4c2b 100644
--- a/tests/PluginLibrary.Tests/Properties/AssemblyInfo.cs
+++ b/tests/PluginLibrary.Tests/Properties/AssemblyInfo.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("PluginLibraryTests")]
diff --git a/tests/PluginLibrary.Tests/app.config b/tests/PluginLibrary.Tests/app.config
index 8ae16eed..10b094f8 100644
--- a/tests/PluginLibrary.Tests/app.config
+++ b/tests/PluginLibrary.Tests/app.config
@@ -4,11 +4,6 @@
True
-
-
-
- True
-
-
+
diff --git a/tests/Repo.CSharp.Tests/Properties/AssemblyInfo.cs b/tests/Repo.CSharp.Tests/Properties/AssemblyInfo.cs
index b327f744..cf2dc507 100644
--- a/tests/Repo.CSharp.Tests/Properties/AssemblyInfo.cs
+++ b/tests/Repo.CSharp.Tests/Properties/AssemblyInfo.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Repo.CSharp.Tests")]
diff --git a/tests/Repo.CSharp.Tests/RepoTests.cs b/tests/Repo.CSharp.Tests/RepoTests.cs
index 0b9b0ed4..c94a83e8 100644
--- a/tests/Repo.CSharp.Tests/RepoTests.cs
+++ b/tests/Repo.CSharp.Tests/RepoTests.cs
@@ -14,9 +14,8 @@
namespace Repo.CSharp.Tests
{
- using System.Collections.Generic;
- using System.Linq;
using NUnit.Framework;
+ using System.Linq;
[TestFixture]
public class PluginLaunchTest
diff --git a/tests/Repo.CSharp.Tests/app.config b/tests/Repo.CSharp.Tests/app.config
index 8ae16eed..10b094f8 100644
--- a/tests/Repo.CSharp.Tests/app.config
+++ b/tests/Repo.CSharp.Tests/app.config
@@ -4,11 +4,6 @@
True
-
-
-
- True
-
-
+
diff --git a/tests/Repo.Tests/App.config b/tests/Repo.Tests/App.config
index 1cd5fb12..2ff85cbe 100644
--- a/tests/Repo.Tests/App.config
+++ b/tests/Repo.Tests/App.config
@@ -7,11 +7,6 @@
True
-
-
-
- True
-
-
+
\ No newline at end of file
diff --git a/tests/Repo.Tests/CoreMetametamodelBuilderTests.fs b/tests/Repo.Tests/CoreMetametamodelBuilderTests.fs
index 3ea11004..c52b84cd 100644
--- a/tests/Repo.Tests/CoreMetametamodelBuilderTests.fs
+++ b/tests/Repo.Tests/CoreMetametamodelBuilderTests.fs
@@ -41,9 +41,9 @@ let ``Every model element shall have correct type`` () =
Seq.length repo.Models |> should equal 1
let model = repo.Models |> Seq.head
- let node = model.Nodes |> Seq.find (fun n -> n.Name = "Node") :> IElement
- let generalization = model.Nodes |> Seq.find (fun n -> n.Name = "Generalization") :> IElement
- let association = model.Nodes |> Seq.find (fun n -> n.Name = "Association") :> IElement
+ let node = model.Nodes |> Seq.find (fun n -> n.Name = "Node") :> IDataElement
+ let generalization = model.Nodes |> Seq.find (fun n -> n.Name = "Generalization") :> IDataElement
+ let association = model.Nodes |> Seq.find (fun n -> n.Name = "Association") :> IDataElement
model |> (fun m -> m.Nodes) |> Seq.iter (fun e -> e.Class |> should equal node)
model |> (fun m -> m.Edges) |> Seq.iter (fun e -> (e.Class = generalization || e.Class = association) |> should be True)
diff --git a/tests/Repo.Tests/DataElementTests.fs b/tests/Repo.Tests/DataElementTests.fs
index a4f5ec21..860fc18e 100644
--- a/tests/Repo.Tests/DataElementTests.fs
+++ b/tests/Repo.Tests/DataElementTests.fs
@@ -21,8 +21,8 @@ open Repo.DataLayer
[]
let ``DataElement shall have class and name`` () =
- let model = new DataModel("") :> IModel
- let node = DataNode("node1", None, model) :> INode
+ let model = new DataModel("") :> IDataModel
+ let node = DataNode("node1", None, model) :> IDataNode
node.Name |> should equal "node1"
node.Name <- "changedName"
@@ -30,6 +30,6 @@ let ``DataElement shall have class and name`` () =
node.Class |> should equal node
- let node2 = DataNode("node2", node, model) :> INode
+ let node2 = DataNode("node2", node, model) :> IDataNode
node2.Class |> should equal node
diff --git a/tests/Repo.Tests/DataModelTests.fs b/tests/Repo.Tests/DataModelTests.fs
index bc3eeb51..e2205d06 100644
--- a/tests/Repo.Tests/DataModelTests.fs
+++ b/tests/Repo.Tests/DataModelTests.fs
@@ -21,8 +21,8 @@ open Repo.DataLayer
[]
let ``Data model shall have name and metamodel`` () =
- let metamodel = DataModel("metamodel") :> IModel
- let model = DataModel("model", metamodel) :> IModel
+ let metamodel = DataModel("metamodel") :> IDataModel
+ let model = DataModel("model", metamodel) :> IDataModel
metamodel.Name |> should equal "metamodel"
model.Name |> should equal "model"
@@ -32,8 +32,8 @@ let ``Data model shall have name and metamodel`` () =
[]
let ``Data model shall allow changing name`` () =
- let metamodel = DataModel("metamodel") :> IModel
- let model = DataModel("model", metamodel) :> IModel
+ let metamodel = DataModel("metamodel") :> IDataModel
+ let model = DataModel("model", metamodel) :> IDataModel
metamodel.Name |> should equal "metamodel"
model.Name |> should equal "model"
@@ -45,7 +45,7 @@ let ``Data model shall allow changing name`` () =
[]
let ``Data model shall allow creating nodes`` () =
- let model = DataModel("model") :> IModel
+ let model = DataModel("model") :> IDataModel
let node = model.CreateNode("node1", None)
model.Nodes |> should contain node
@@ -56,7 +56,7 @@ let ``Data model shall allow creating nodes`` () =
[]
let ``Data model shall allow creating edges`` () =
- let model = DataModel("model") :> IModel
+ let model = DataModel("model") :> IDataModel
let node1 = model.CreateNode("node1", None)
let node2 = model.CreateNode("node2", None)
@@ -71,13 +71,13 @@ let ``Data model shall allow creating edges`` () =
Seq.length model.Edges |> should equal 2
- Seq.append (model.Nodes |> Seq.cast) (model.Edges |> Seq.cast) |> should equal model.Elements
+ Seq.append (model.Nodes |> Seq.cast) (model.Edges |> Seq.cast) |> should equal model.Elements
[]
let ``Data model shall allow creating unconnected associations`` () =
- let model = DataModel("model") :> IModel
- let node1 = model.CreateNode("node1", None) :> IElement
- let node2 = model.CreateNode("node2", None) :> IElement
+ let model = DataModel("model") :> IDataModel
+ let node1 = model.CreateNode("node1", None) :> IDataElement
+ let node2 = model.CreateNode("node2", None) :> IDataElement
let associationClass = model.CreateNode("association", None)
@@ -93,9 +93,9 @@ let ``Data model shall allow creating unconnected associations`` () =
[]
let ``Data model shall allow creating unconnected generalizations`` () =
- let model = DataModel("model") :> IModel
- let node1 = model.CreateNode("node1", None) :> IElement
- let node2 = model.CreateNode("node2", None) :> IElement
+ let model = DataModel("model") :> IDataModel
+ let node1 = model.CreateNode("node1", None) :> IDataElement
+ let node2 = model.CreateNode("node2", None) :> IDataElement
let generalizationClass = model.CreateNode("generalization", None)
@@ -111,7 +111,7 @@ let ``Data model shall allow creating unconnected generalizations`` () =
[]
let ``Data model shall allow deleting elements`` () =
- let model = DataModel("model") :> IModel
+ let model = DataModel("model") :> IDataModel
let node1 = model.CreateNode("node1", None)
model.Nodes |> should contain node1
@@ -123,12 +123,12 @@ let ``Data model shall allow deleting elements`` () =
let generalization = model.CreateGeneralization(generalizationClass, node1, node2)
model.Edges |> should contain generalization
- model.MarkElementDeleted generalization
+ model.RemoveElement generalization
model.Edges |> should not' (contain generalization)
- model.MarkElementDeleted node1
+ model.RemoveElement node1
model.Nodes |> should not' (contain node1)
model.Nodes |> should contain node2
- model.MarkElementDeleted node2
+ model.RemoveElement node2
model.Nodes |> should not' (contain node2)
diff --git a/tests/Repo.Tests/DataRepoTest.fs b/tests/Repo.Tests/DataRepoTests.fs
similarity index 98%
rename from tests/Repo.Tests/DataRepoTest.fs
rename to tests/Repo.Tests/DataRepoTests.fs
index 5c8e3727..d8453d55 100644
--- a/tests/Repo.Tests/DataRepoTest.fs
+++ b/tests/Repo.Tests/DataRepoTests.fs
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License. *)
-module DataRepoTest
+module DataRepoTests
open NUnit.Framework
open FsUnit
diff --git a/tests/Repo.Tests/FacadeAttributeTests.fs b/tests/Repo.Tests/FacadeAttributeTests.fs
index 71b29bbd..b4784f33 100644
--- a/tests/Repo.Tests/FacadeAttributeTests.fs
+++ b/tests/Repo.Tests/FacadeAttributeTests.fs
@@ -27,7 +27,7 @@ let getAttributeType nodeName name =
let attributeRepository = AttributeRepository()
let dataLayerModel = (model :?> Model).UnderlyingModel
- let dataLayerElement = dataLayerModel.Nodes |> Seq.find (fun n -> n.Name = nodeName) :> DataLayer.IElement
+ let dataLayerElement = dataLayerModel.Nodes |> Seq.find (fun n -> n.Name = nodeName) :> DataLayer.IDataElement
let dataLayerAttribute = CoreSemanticLayer.Element.attribute dataLayerElement name
@@ -43,8 +43,8 @@ let getAttributeInstance nodeName name =
let dataLayerModel = (model :?> Model).UnderlyingModel
let dataLayerMetamodel = (model.Metamodel :?> Model).UnderlyingModel
- let dataLayerClass = dataLayerMetamodel.Nodes |> Seq.find (fun n -> n.Name = nodeName) :> DataLayer.IElement
- let dataLayerElement = dataLayerModel.Nodes |> Seq.find (fun n -> n.Class = dataLayerClass) :> DataLayer.IElement
+ let dataLayerClass = dataLayerMetamodel.Nodes |> Seq.find (fun n -> n.Name = nodeName) :> DataLayer.IDataElement
+ let dataLayerElement = dataLayerModel.Nodes |> Seq.find (fun n -> n.Class = dataLayerClass) :> DataLayer.IDataElement
let dataLayerAttribute =
CoreSemanticLayer.Element.attribute dataLayerElement name
diff --git a/tests/Repo.Tests/FacadeModelTests.fs b/tests/Repo.Tests/FacadeModelTests.fs
index cfc755ff..e53bc1cf 100644
--- a/tests/Repo.Tests/FacadeModelTests.fs
+++ b/tests/Repo.Tests/FacadeModelTests.fs
@@ -78,30 +78,20 @@ let ``Model shall allow to delete elements``() =
let ``type`` = model.Metamodel.Nodes |> Seq.find (fun n -> n.Name = "Node")
let node = model.CreateElement ``type``
node.AddAttribute ("Attribute1", AttributeKind.String, "default") |> ignore
- let unwrapped = (node :?> Element).UnderlyingElement
- let attribute = node.Attributes |> Seq.find (fun u -> u.Name = "Attribute1")
- let unwrappedAttribute = (attribute :?> Attribute).UnderlyingNode
- model.DeleteElement node
+ model.RemoveElement node
model.Nodes |> should not' (contain node)
- unwrapped.IsMarkedDeleted |> should be True
- unwrappedAttribute.IsMarkedDeleted |> should be True
[]
-let ``Model shall allow to restore elements``() =
+let ``Model shall allow to add or restore elements``() =
let model = init()
let ``type`` = model.Metamodel.Nodes |> Seq.find (fun n -> n.Name = "Node")
let node = model.CreateElement ``type``
node.AddAttribute ("Attribute1", AttributeKind.String, "default") |> ignore
node.AddAttribute ("Attribute2", AttributeKind.Int, "0") |> ignore
- let unwrapped = (node :?> Element).UnderlyingElement
- let attributes = node.Attributes |> Seq.filter (fun a -> a.Name = "Attribute1" || a.Name = "Attribute2")
- |> Seq.map (fun a -> (a :?> Attribute).UnderlyingNode)
- model.DeleteElement node
+ model.RemoveElement node
model.Nodes |> should not' (contain node)
model.RestoreElement node
model.Nodes |> should contain node
- unwrapped.IsMarkedDeleted |> should be False
- attributes |> Seq.map (fun a -> a |> should be False) |> ignore
[]
let ``Model shall allow to list its nodes`` () =
diff --git a/tests/Repo.Tests/FacadeNodeTests.fs b/tests/Repo.Tests/FacadeNodeTests.fs
index 9c819233..50d8df75 100644
--- a/tests/Repo.Tests/FacadeNodeTests.fs
+++ b/tests/Repo.Tests/FacadeNodeTests.fs
@@ -31,7 +31,7 @@ let ``Node in a model shall have metatype`` () =
let metamodel = repo.Models |> Seq.find (fun m -> m.Name = "RobotsMetamodel")
let dataLayerMetamodel = (metamodel :?> Model).UnderlyingModel
- let dataLayerClass = dataLayerMetamodel.Nodes |> Seq.find (fun n -> n.Name = "MotorsForward") :> DataLayer.IElement
+ let dataLayerClass = dataLayerMetamodel.Nodes |> Seq.find (fun n -> n.Name = "MotorsForward") :> DataLayer.IDataElement
let dataLayerElement = dataLayerModel.Nodes |> Seq.find (fun n -> n.Class = dataLayerClass)
let infrastructure = InfrastructureSemanticLayer.InfrastructureSemantic(underlyingRepo)
@@ -54,7 +54,7 @@ let ``Timer block shall have a picture`` () =
let metamodel = repo.Models |> Seq.find (fun m -> m.Name = "RobotsMetamodel")
let dataLayerMetamodel = (metamodel :?> Model).UnderlyingModel
- let dataLayerClass = dataLayerMetamodel.Nodes |> Seq.find (fun n -> n.Name = "Timer") :> DataLayer.IElement
+ let dataLayerClass = dataLayerMetamodel.Nodes |> Seq.find (fun n -> n.Name = "Timer") :> DataLayer.IDataElement
let dataLayerElement = dataLayerModel.Nodes |> Seq.find (fun n -> n.Class = dataLayerClass)
let infrastructure = InfrastructureSemanticLayer.InfrastructureSemantic(underlyingRepo)
diff --git a/tests/Repo.Tests/InfrastructureSemanticLayerTests.fs b/tests/Repo.Tests/InfrastructureSemanticLayerTests.fs
index a182e413..7b7fa063 100644
--- a/tests/Repo.Tests/InfrastructureSemanticLayerTests.fs
+++ b/tests/Repo.Tests/InfrastructureSemanticLayerTests.fs
@@ -55,7 +55,7 @@ let ``Instantiation shall preserve linguistic attributes`` () =
let repo, infrastructure, model, _, element = initForModel ()
let outgoingAssociations = CoreSemanticLayer.Element.outgoingAssociations element
- outgoingAssociations |> Seq.map (fun a -> (a.Target.Value :?> INode).Name) |> should contain "shape"
+ outgoingAssociations |> Seq.map (fun a -> (a.Target.Value :?> IDataNode).Name) |> should contain "shape"
let attributes = infrastructure.Element.Attributes element
attributes |> should not' (be Empty)
infrastructure.Element.AttributeValue element "shape" |> should equal "View/Pictures/vertex.png"
diff --git a/tests/Repo.Tests/Repo.Tests.fsproj b/tests/Repo.Tests/Repo.Tests.fsproj
index 097498ca..38921f97 100644
--- a/tests/Repo.Tests/Repo.Tests.fsproj
+++ b/tests/Repo.Tests/Repo.Tests.fsproj
@@ -77,7 +77,7 @@
Always
-
+
@@ -87,6 +87,7 @@
+
diff --git a/tests/Repo.Tests/RobotsTestModelsTests.fs b/tests/Repo.Tests/RobotsTestModelsTests.fs
index a9b64dcd..6552ca3a 100644
--- a/tests/Repo.Tests/RobotsTestModelsTests.fs
+++ b/tests/Repo.Tests/RobotsTestModelsTests.fs
@@ -31,7 +31,7 @@ let ``Generalizations shall be listed as edges in metamodel`` () =
let generalization = infrastructureModel.Nodes |> Seq.find (fun n -> n.Name = "Generalization")
let model = repo.Model "RobotsMetamodel"
- let rawEdges = model.Edges |> Seq.map (fun e -> (e :?> FacadeLayer.Element).UnderlyingElement :?> DataLayer.IEdge)
+ let rawEdges = model.Edges |> Seq.map (fun e -> (e :?> FacadeLayer.Element).UnderlyingElement :?> DataLayer.IDataEdge)
let rawGeneralization = (generalization :?> FacadeLayer.Element).UnderlyingElement
let rawGeneralizations = rawEdges |> Seq.filter (fun e -> e.Class = rawGeneralization)
let someRawGeneralization = rawGeneralizations |> Seq.head
@@ -44,7 +44,7 @@ let ``Generalizations shall be listed as edges in metamodel`` () =
let someWrappedGeneralization =
model.Edges
|> Seq.find
- (fun e -> (e :?> FacadeLayer.Edge).UnderlyingElement = (someRawGeneralization :> DataLayer.IElement))
+ (fun e -> (e :?> FacadeLayer.Edge).UnderlyingElement = (someRawGeneralization :> DataLayer.IDataElement))
someWrappedGeneralization.Class |> should sameAs generalization
diff --git a/tests/Repo.Tests/VisualInfoTests.fs b/tests/Repo.Tests/VisualInfoTests.fs
new file mode 100644
index 00000000..6308ccda
--- /dev/null
+++ b/tests/Repo.Tests/VisualInfoTests.fs
@@ -0,0 +1,27 @@
+module Repo.Tests.VisualInfoTests
+
+open NUnit.Framework
+open FsUnit
+
+open Repo
+open Repo.Visual
+
+// VisualPoint tests
+[]
+let ``construct should create correct point``() =
+ let point = new VisualPoint(100.0, 200.0)
+ point.X |> should be (equal 100.0)
+ point.Y |> should be (equal 200.0)
+
+[]
+let ``default should return zero point``() = VisualPoint.Default |> should be (equal (new VisualPoint(0.0, 0.0)))
+
+// VisualNodeInfo tests
+let getNodeinfo() = new VisualNodeInfo() :> IVisualNodeInfo
+
+[]
+let ``position should be correct``() =
+ let info = getNodeinfo()
+ info.Position <- new VisualPoint(1.0, 2.0)
+ info.Position |> should be (equal (new VisualPoint(1.0, 2.0)))
+
\ No newline at end of file
diff --git a/tests/WpfControlsLib.Tests/ControllerTests/ControllerTests.cs b/tests/WpfControlsLib.Tests/ControllerTests/ControllerTests.cs
index 8b76abd4..f4db7861 100644
--- a/tests/WpfControlsLib.Tests/ControllerTests/ControllerTests.cs
+++ b/tests/WpfControlsLib.Tests/ControllerTests/ControllerTests.cs
@@ -14,9 +14,9 @@
namespace WpfControlsLib.Tests
{
- using System;
- using NUnit.Framework;
using EditorPluginInterfaces;
+ using NUnit.Framework;
+ using System;
using WpfControlsLib.Controller;
[TestFixture]
diff --git a/tests/WpfControlsLib.Tests/ControlsTests/SceneTests/SceneCommandsTests.cs b/tests/WpfControlsLib.Tests/ControlsTests/SceneTests/SceneCommandsTests.cs
index cc87a8be..04c32b33 100644
--- a/tests/WpfControlsLib.Tests/ControlsTests/SceneTests/SceneCommandsTests.cs
+++ b/tests/WpfControlsLib.Tests/ControlsTests/SceneTests/SceneCommandsTests.cs
@@ -14,16 +14,16 @@
namespace WpfControlsLib.Tests.ControlsTests.SceneTests
{
- using NUnit.Framework;
- using WpfControlsLib.Model;
- using WpfControlsLib.Controls.Scene.Commands;
using EditorPluginInterfaces;
+ using NUnit.Framework;
using System.Linq;
+ using WpfControlsLib.Controls.Scene.Commands;
+ using WpfControlsLib.Model;
[TestFixture]
public class SceneCommandsTests
{
- private Model model;
+ private SceneModel model;
private Repo.IModel testModel;
private Repo.INode testNodeType;
private Repo.IEdge testEdgeType;
@@ -31,7 +31,7 @@ public class SceneCommandsTests
[SetUp]
public void Init()
{
- model = new Model();
+ model = new SceneModel();
testModel = model.Repo.CreateModel("testModel", "RobotsMetamodel");
model.ModelName = testModel.Name;
testNodeType = testModel.Metamodel.FindElement("FinalNode") as Repo.INode;
@@ -41,7 +41,7 @@ public void Init()
[Test]
public void AddingNodeOnSceneShouldResultInAddingNodeInRepo()
{
- ICommand command = new CreateNodeCommand(model, testNodeType);
+ ICommand command = new CreateNodeCommand(model, testNodeType, new Repo.VisualPoint(0, 0));
command.Execute();
diff --git a/tests/WpfControlsLib.Tests/Properties/AssemblyInfo.cs b/tests/WpfControlsLib.Tests/Properties/AssemblyInfo.cs
index a9bf4c00..69f62e9f 100644
--- a/tests/WpfControlsLib.Tests/Properties/AssemblyInfo.cs
+++ b/tests/WpfControlsLib.Tests/Properties/AssemblyInfo.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
diff --git a/tests/WpfControlsLib.Tests/app.config b/tests/WpfControlsLib.Tests/app.config
index 8ae16eed..10b094f8 100644
--- a/tests/WpfControlsLib.Tests/app.config
+++ b/tests/WpfControlsLib.Tests/app.config
@@ -4,11 +4,6 @@
True
-
-
-
- True
-
-
+