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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 - - +