diff --git a/SuperMemoAssistant.sln b/SuperMemoAssistant.sln
index 7c6cada..799970c 100644
--- a/SuperMemoAssistant.sln
+++ b/SuperMemoAssistant.sln
@@ -108,224 +108,146 @@ Global
src\Core\SuperMemoAssistant.PluginHost.Shared\SuperMemoAssistant.PluginHost.Shared.projitems*{fe47a14f-9157-4917-82fb-7861a57b1822}*SharedItemsImports = 13
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
- Debug-InProd|Any CPU = Debug-InProd|Any CPU
Debug-InProd|x86 = Debug-InProd|x86
- Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Debug|Any CPU.ActiveCfg = Debug|x86
{C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Debug|x86.ActiveCfg = Debug|x86
{C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Debug|x86.Build.0 = Debug|x86
- {C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Release|Any CPU.ActiveCfg = Release|x86
{C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Release|x86.ActiveCfg = Release|x86
{C57D9489-0A27-4B18-818C-7CBB379ACFD8}.Release|x86.Build.0 = Release|x86
- {7550628D-0630-4A42-B0B7-55D26F981365}.Debug|Any CPU.ActiveCfg = Debug|x86
{7550628D-0630-4A42-B0B7-55D26F981365}.Debug|x86.ActiveCfg = Debug|x86
{7550628D-0630-4A42-B0B7-55D26F981365}.Debug|x86.Build.0 = Debug|x86
- {7550628D-0630-4A42-B0B7-55D26F981365}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{7550628D-0630-4A42-B0B7-55D26F981365}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{7550628D-0630-4A42-B0B7-55D26F981365}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {7550628D-0630-4A42-B0B7-55D26F981365}.Release|Any CPU.ActiveCfg = Release|x86
{7550628D-0630-4A42-B0B7-55D26F981365}.Release|x86.ActiveCfg = Release|x86
{7550628D-0630-4A42-B0B7-55D26F981365}.Release|x86.Build.0 = Release|x86
- {FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Debug|Any CPU.ActiveCfg = Debug|x86
{FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Debug|x86.ActiveCfg = Debug|x86
{FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Debug|x86.Build.0 = Debug|x86
- {FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Release|Any CPU.ActiveCfg = Release|x86
{FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Release|x86.ActiveCfg = Release|x86
{FD0E1BE8-BED3-4AB0-A9C8-022A2DBC8450}.Release|x86.Build.0 = Release|x86
- {D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Debug|Any CPU.ActiveCfg = Debug|x86
{D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Debug|x86.ActiveCfg = Debug|x86
{D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Debug|x86.Build.0 = Debug|x86
- {D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Release|Any CPU.ActiveCfg = Release|x86
{D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Release|x86.ActiveCfg = Release|x86
{D5086D5E-84A6-4C0D-B6F2-D1B82C5FB487}.Release|x86.Build.0 = Release|x86
- {CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Debug|Any CPU.ActiveCfg = Debug|x86
{CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Debug|x86.ActiveCfg = Debug|x86
{CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Debug|x86.Build.0 = Debug|x86
- {CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Release|Any CPU.ActiveCfg = Release|x86
{CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Release|x86.ActiveCfg = Release|x86
{CD2988DA-B610-40AD-995A-AA5A28FBBBFE}.Release|x86.Build.0 = Release|x86
- {FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Debug|Any CPU.ActiveCfg = Debug|x86
{FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Debug|x86.ActiveCfg = Debug|x86
{FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Debug|x86.Build.0 = Debug|x86
- {FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Release|Any CPU.ActiveCfg = Release|x86
{FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Release|x86.ActiveCfg = Release|x86
{FAECF9BB-9FD5-4FB1-A3A8-9F7CAA57A1FE}.Release|x86.Build.0 = Release|x86
- {677647E4-F052-41D0-915A-AD76DA72463E}.Debug|Any CPU.ActiveCfg = Debug|x86
{677647E4-F052-41D0-915A-AD76DA72463E}.Debug|x86.ActiveCfg = Debug|x86
{677647E4-F052-41D0-915A-AD76DA72463E}.Debug|x86.Build.0 = Debug|x86
- {677647E4-F052-41D0-915A-AD76DA72463E}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{677647E4-F052-41D0-915A-AD76DA72463E}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{677647E4-F052-41D0-915A-AD76DA72463E}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {677647E4-F052-41D0-915A-AD76DA72463E}.Release|Any CPU.ActiveCfg = Release|x86
{677647E4-F052-41D0-915A-AD76DA72463E}.Release|x86.ActiveCfg = Release|x86
{677647E4-F052-41D0-915A-AD76DA72463E}.Release|x86.Build.0 = Release|x86
- {2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Debug|Any CPU.ActiveCfg = Debug|x86
{2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Debug|x86.ActiveCfg = Debug|x86
{2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Debug|x86.Build.0 = Debug|x86
- {2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Debug-InProd|Any CPU.ActiveCfg = Release|x86
- {2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Debug-InProd|Any CPU.Build.0 = Release|x86
{2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Debug-InProd|x86.ActiveCfg = Debug|x86
- {2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Release|Any CPU.ActiveCfg = Release|x86
{2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Release|x86.ActiveCfg = Release|x86
{2E3DF5C2-8A38-4A03-86D7-8D463C917E47}.Release|x86.Build.0 = Release|x86
- {88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Debug|Any CPU.ActiveCfg = Debug|x86
{88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Debug|x86.ActiveCfg = Debug|x86
{88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Debug|x86.Build.0 = Debug|x86
- {88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Release|Any CPU.ActiveCfg = Release|x86
{88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Release|x86.ActiveCfg = Release|x86
{88E22B47-FCF2-489F-B70F-EB0925E8AF87}.Release|x86.Build.0 = Release|x86
- {F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Debug|Any CPU.ActiveCfg = Debug|x86
{F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Debug|x86.ActiveCfg = Debug|x86
{F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Debug|x86.Build.0 = Debug|x86
- {F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Release|Any CPU.ActiveCfg = Release|x86
{F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Release|x86.ActiveCfg = Release|x86
{F8BB6993-25DF-4173-BB3D-ACEE15C5A2B9}.Release|x86.Build.0 = Release|x86
- {FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Debug|Any CPU.ActiveCfg = Debug|Win32
{FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Debug|x86.ActiveCfg = Release|Win32
{FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Debug|x86.Build.0 = Release|Win32
- {FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|Win32
{FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Debug-InProd|x86.ActiveCfg = Release|Win32
{FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Debug-InProd|x86.Build.0 = Release|Win32
- {FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Release|Any CPU.ActiveCfg = Release|Win32
{FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Release|x86.ActiveCfg = Release|Win32
{FFFE85EF-4719-4F7F-AB5F-A63D2E184BD2}.Release|x86.Build.0 = Release|Win32
- {501257D3-F788-4A5D-B990-16C01FF71926}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {501257D3-F788-4A5D-B990-16C01FF71926}.Debug|Any CPU.Build.0 = Debug|Any CPU
{501257D3-F788-4A5D-B990-16C01FF71926}.Debug|x86.ActiveCfg = Debug|x86
{501257D3-F788-4A5D-B990-16C01FF71926}.Debug|x86.Build.0 = Debug|x86
- {501257D3-F788-4A5D-B990-16C01FF71926}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|Any CPU
- {501257D3-F788-4A5D-B990-16C01FF71926}.Debug-InProd|Any CPU.Build.0 = Debug-InProd|Any CPU
{501257D3-F788-4A5D-B990-16C01FF71926}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{501257D3-F788-4A5D-B990-16C01FF71926}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {501257D3-F788-4A5D-B990-16C01FF71926}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {501257D3-F788-4A5D-B990-16C01FF71926}.Release|Any CPU.Build.0 = Release|Any CPU
{501257D3-F788-4A5D-B990-16C01FF71926}.Release|x86.ActiveCfg = Release|x86
{501257D3-F788-4A5D-B990-16C01FF71926}.Release|x86.Build.0 = Release|x86
- {C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Debug|Any CPU.ActiveCfg = Debug|x86
{C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Debug|x86.ActiveCfg = Debug|x86
{C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Debug|x86.Build.0 = Debug|x86
- {C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Release|Any CPU.ActiveCfg = Release|x86
{C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Release|x86.ActiveCfg = Release|x86
{C76CFA78-F820-4F05-9429-4A3A3C9C1414}.Release|x86.Build.0 = Release|x86
- {AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Debug|Any CPU.ActiveCfg = Debug|x86
{AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Debug|x86.ActiveCfg = Debug|x86
{AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Debug|x86.Build.0 = Debug|x86
- {AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Release|Any CPU.ActiveCfg = Release|x86
{AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Release|x86.ActiveCfg = Release|x86
{AA97C5AA-CA1A-4988-AE2E-E5A292B63C12}.Release|x86.Build.0 = Release|x86
- {CC5B9485-9EF1-4133-9242-719D263700AE}.Debug|Any CPU.ActiveCfg = Debug|x86
{CC5B9485-9EF1-4133-9242-719D263700AE}.Debug|x86.ActiveCfg = Debug|x86
{CC5B9485-9EF1-4133-9242-719D263700AE}.Debug|x86.Build.0 = Debug|x86
- {CC5B9485-9EF1-4133-9242-719D263700AE}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{CC5B9485-9EF1-4133-9242-719D263700AE}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{CC5B9485-9EF1-4133-9242-719D263700AE}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {CC5B9485-9EF1-4133-9242-719D263700AE}.Release|Any CPU.ActiveCfg = Release|x86
{CC5B9485-9EF1-4133-9242-719D263700AE}.Release|x86.ActiveCfg = Release|x86
{CC5B9485-9EF1-4133-9242-719D263700AE}.Release|x86.Build.0 = Release|x86
- {149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Debug|Any CPU.ActiveCfg = Debug|x86
{149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Debug|x86.ActiveCfg = Debug|x86
{149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Debug|x86.Build.0 = Debug|x86
- {149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Release|Any CPU.ActiveCfg = Release|x86
{149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Release|x86.ActiveCfg = Release|x86
{149C5A9B-0588-41B9-8F77-C5D17A1CDFBE}.Release|x86.Build.0 = Release|x86
- {380A4F46-413D-49B4-884F-21C7683F093C}.Debug|Any CPU.ActiveCfg = Debug|x86
{380A4F46-413D-49B4-884F-21C7683F093C}.Debug|x86.ActiveCfg = Debug|x86
{380A4F46-413D-49B4-884F-21C7683F093C}.Debug|x86.Build.0 = Debug|x86
- {380A4F46-413D-49B4-884F-21C7683F093C}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{380A4F46-413D-49B4-884F-21C7683F093C}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{380A4F46-413D-49B4-884F-21C7683F093C}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {380A4F46-413D-49B4-884F-21C7683F093C}.Release|Any CPU.ActiveCfg = Release|x86
{380A4F46-413D-49B4-884F-21C7683F093C}.Release|x86.ActiveCfg = Release|x86
{380A4F46-413D-49B4-884F-21C7683F093C}.Release|x86.Build.0 = Release|x86
- {7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Debug|Any CPU.ActiveCfg = Debug|x86
{7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Debug|x86.ActiveCfg = Debug|x86
{7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Debug|x86.Build.0 = Debug|x86
- {7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Release|Any CPU.ActiveCfg = Release|x86
{7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Release|x86.ActiveCfg = Release|x86
{7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}.Release|x86.Build.0 = Release|x86
- {F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Debug|Any CPU.ActiveCfg = Debug|x86
{F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Debug|x86.ActiveCfg = Debug|x86
{F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Debug|x86.Build.0 = Debug|x86
- {F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Release|Any CPU.ActiveCfg = Release|x86
{F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Release|x86.ActiveCfg = Release|x86
{F8BB6993-B610-40AD-995A-AA5A28FBBBFE}.Release|x86.Build.0 = Release|x86
- {A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Debug|Any CPU.ActiveCfg = Debug|x86
{A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Debug|x86.ActiveCfg = Debug|x86
{A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Debug|x86.Build.0 = Debug|x86
- {A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Release|Any CPU.ActiveCfg = Release|x86
{A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Release|x86.ActiveCfg = Release|x86
{A95DA3C0-54C5-4BB9-84CB-E8B69E712A62}.Release|x86.Build.0 = Release|x86
- {CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Debug|Any CPU.ActiveCfg = Debug|x86
{CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Debug|x86.ActiveCfg = Debug|x86
{CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Debug|x86.Build.0 = Debug|x86
- {CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|Any CPU.ActiveCfg = Debug-InProd|x86
{CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|x86.ActiveCfg = Debug-InProd|x86
{CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Debug-InProd|x86.Build.0 = Debug-InProd|x86
- {CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Release|Any CPU.ActiveCfg = Release|x86
{CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Release|x86.ActiveCfg = Release|x86
{CD1238DA-B610-40AD-995A-AA5A28FBBBFE}.Release|x86.Build.0 = Release|x86
- {390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Debug|Any CPU.ActiveCfg = Debug|x86
{390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Debug|x86.ActiveCfg = Debug|x86
{390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Debug|x86.Build.0 = Debug|x86
- {390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Debug-InProd|Any CPU.ActiveCfg = Release|x86
- {390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Debug-InProd|Any CPU.Build.0 = Release|x86
{390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Debug-InProd|x86.ActiveCfg = Debug|x86
{390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Debug-InProd|x86.Build.0 = Debug|x86
- {390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Release|Any CPU.ActiveCfg = Release|x86
{390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Release|x86.ActiveCfg = Release|x86
{390A9FF0-4B34-4869-AF15-7EF7960D5D56}.Release|x86.Build.0 = Release|x86
- {1B4B5809-4108-4C73-B3FB-3A7609D97704}.Debug|Any CPU.ActiveCfg = Debug|x86
{1B4B5809-4108-4C73-B3FB-3A7609D97704}.Debug|x86.ActiveCfg = Debug|x86
{1B4B5809-4108-4C73-B3FB-3A7609D97704}.Debug|x86.Build.0 = Debug|x86
- {1B4B5809-4108-4C73-B3FB-3A7609D97704}.Debug-InProd|Any CPU.ActiveCfg = Release|x86
- {1B4B5809-4108-4C73-B3FB-3A7609D97704}.Debug-InProd|Any CPU.Build.0 = Release|x86
{1B4B5809-4108-4C73-B3FB-3A7609D97704}.Debug-InProd|x86.ActiveCfg = Debug|x86
{1B4B5809-4108-4C73-B3FB-3A7609D97704}.Debug-InProd|x86.Build.0 = Debug|x86
- {1B4B5809-4108-4C73-B3FB-3A7609D97704}.Release|Any CPU.ActiveCfg = Release|x86
{1B4B5809-4108-4C73-B3FB-3A7609D97704}.Release|x86.ActiveCfg = Release|x86
{1B4B5809-4108-4C73-B3FB-3A7609D97704}.Release|x86.Build.0 = Release|x86
EndGlobalSection
@@ -364,15 +286,4 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF31D6F5-6E93-461B-8C5F-348439D19C6D}
EndGlobalSection
- GlobalSection(AutomaticVersions) = postSolution
- UpdateAssemblyVersion = True
- UpdateAssemblyFileVersion = True
- UpdateAssemblyInfoVersion = True
- AssemblyVersionSettings = IncrementOnDemand.IncrementOnDemand.IncrementOnDemand.IncrementWithResetOnIncrease
- AssemblyFileVersionSettings = IncrementOnDemand.IncrementOnDemand.IncrementOnDemand.IncrementWithResetOnIncrease
- AssemblyInfoVersionSettings = IncrementOnDemand.IncrementOnDemand.IncrementOnDemand.None
- UpdatePackageVersion = False
- AssemblyInfoVersionType = SettingsVersion
- InheritWinAppVersionFrom = None
- EndGlobalSection
EndGlobal
diff --git a/SuperMemoAssistant.sln.DotSettings b/SuperMemoAssistant.sln.DotSettings
index 6344117..196e9fa 100644
--- a/SuperMemoAssistant.sln.DotSettings
+++ b/SuperMemoAssistant.sln.DotSettings
@@ -752,4 +752,5 @@ public static $name$ Instance { get; } = new $name$();
True
True
True
+ True
True
\ No newline at end of file
diff --git a/src/AppHosts/SuperMemoAssistant/App.xaml.cs b/src/AppHosts/SuperMemoAssistant/App.xaml.cs
index 7adbf8a..18978f9 100644
--- a/src/AppHosts/SuperMemoAssistant/App.xaml.cs
+++ b/src/AppHosts/SuperMemoAssistant/App.xaml.cs
@@ -21,8 +21,7 @@
// DEALINGS IN THE SOFTWARE.
//
//
-// Created On: 2020/01/22 09:58
-// Modified On: 2020/01/22 17:31
+// Modified On: 2020/02/03 16:41
// Modified By: Alexis
#endregion
@@ -36,14 +35,17 @@
using System.Windows;
using Anotar.Serilog;
using CommandLine;
-using Forge.Forms;
using Hardcodet.Wpf.TaskbarNotification;
+using SuperMemoAssistant.Exceptions;
using SuperMemoAssistant.Interop;
using SuperMemoAssistant.Interop.SuperMemo.Core;
using SuperMemoAssistant.PluginHost;
+using SuperMemoAssistant.Services.UI.Extensions;
+using SuperMemoAssistant.SMA.Configs;
using SuperMemoAssistant.SMA.Utils;
using SuperMemoAssistant.Sys.IO;
using SuperMemoAssistant.Sys.IO.Devices;
+using SuperMemoFinderUtil = SuperMemoAssistant.SMA.Utils.SuperMemoFinder;
namespace SuperMemoAssistant
{
@@ -65,8 +67,10 @@ protected override void OnExit(ExitEventArgs e)
{
_taskbarIcon?.Dispose();
- SuperMemoAssistant.SMA.Core.Logger?.Shutdown();
+ SMA.Core.Logger?.Shutdown();
+#pragma warning disable CS0436 // Type conflicts with imported type
ModuleInitializer.SentryInstance?.Dispose();
+#pragma warning restore CS0436 // Type conflicts with imported type
base.OnExit(e);
}
@@ -85,27 +89,54 @@ private async void Application_Startup(object o,
await LoadApp(parsed.Value);
else
- Environment.Exit(HostConst.ExitParameters);
+ Shutdown(HostConst.ExitParameters);
}
private async Task LoadApp(SMAParameters args)
{
_taskbarIcon = (TaskbarIcon)FindResource("TbIcon");
+ //
+ // Make sure assemblies are available, and SMA is installed in "%AppData%\SuperMemoAssistant"
if (CheckAssemblies(out var errMsg) == false || CheckSMALocation(out errMsg) == false)
{
LogTo.Warning(errMsg);
- await Show.Window().For(new Alert(errMsg, "Error"));
+ await errMsg.ErrorMsgBox();
- Shutdown();
+ Shutdown(1);
return;
}
+ //
+ // Load system configs
+ if (await LoadConfigs(out var nativeDataCfg, out var startupCfg) == false)
+ return;
+
+ //
+ // Make sure SuperMemo exe path is correct. Prompt user to input the path otherwise.
+ if (ShouldFindSuperMemo(startupCfg, nativeDataCfg))
+ {
+ var smFinder = new SuperMemoFinder(nativeDataCfg, startupCfg);
+ smFinder.ShowDialog();
+
+ if (smFinder.DialogResult == null || smFinder.DialogResult == false)
+ {
+ LogTo.Warning("No valid SM executable file path defined. SMA cannot run.");
+
+ Shutdown(1);
+ return;
+ }
+ }
+
+ //
+ // (Optional) Start the debug Key logger (logs key strokes with modifiers, e.g. ctrl, alt, ..)
if (args.KeyLogger)
- SuperMemoAssistant.SMA.Core.KeyboardHotKey.MainCallback = LogHotKeys;
+ SMA.Core.KeyboardHotKey.MainCallback = LogHotKeys;
+ //
+ // Determine which collection to open
SMCollection smCollection = null;
- var selectionWdw = new CollectionSelectionWindow();
+ var selectionWdw = new CollectionSelectionWindow(startupCfg);
// Try to open command line collection, if one was passed
if (args.CollectionKnoPath != null && selectionWdw.ValidateSuperMemoPath())
@@ -124,18 +155,15 @@ private async Task LoadApp(SMAParameters args)
smCollection = selectionWdw.Collection;
}
- // If a collection was selected, start SMA
+ //
+ // If a collection was defined, start SMA
if (smCollection != null)
{
- SuperMemoAssistant.SMA.Core.SMA.OnSMStoppedEvent += Instance_OnSMStoppedEvent;
+ SMA.Core.SMA.OnSMStoppedEvent += Instance_OnSMStoppedEvent;
- if (await SuperMemoAssistant.SMA.Core.SMA.Start(smCollection).ConfigureAwait(true) == false)
+ if (await SMA.Core.SMA.Start(nativeDataCfg, startupCfg, smCollection).ConfigureAwait(true) == false)
{
- await Show.Window().For(
- new Alert(
- $"SMA failed to start. Please check the logs in '{SMAFileSystem.LogDir.FullPath}' for details.",
- "Error")
- );
+ await $"SMA failed to start. Please check the logs in '{SMAFileSystem.LogDir.FullPath}' for details.".ErrorMsgBox();
Shutdown();
}
}
@@ -151,6 +179,16 @@ private Task Instance_OnSMStoppedEvent(object sender,
return Dispatcher.InvokeAsync(Shutdown).Task;
}
+ private bool ShouldFindSuperMemo(StartupCfg startupCfg, NativeDataCfg nativeDataCfg)
+ {
+ return string.IsNullOrWhiteSpace(startupCfg.SMBinPath)
+ || SuperMemoFinderUtil.CheckSuperMemoExecutable(
+ nativeDataCfg,
+ startupCfg.SMBinPath,
+ out _,
+ out _) == false;
+ }
+
private bool CheckSMALocation(out string error)
{
var smaExeFile = new FilePath(Assembly.GetExecutingAssembly().Location);
@@ -179,6 +217,50 @@ private void LogHotKeys(HotKey hk)
LogTo.Debug($"Key pressed: {hk}");
}
+ private Task LoadConfigs(out NativeDataCfg nativeDataCfg, out StartupCfg startupCfg)
+ {
+ nativeDataCfg = LoadNativeDataConfig().Result;
+ startupCfg = LoadStartupConfig().Result;
+
+ if (nativeDataCfg == null || startupCfg == null)
+ {
+ Shutdown(1);
+ return Task.FromResult(false);
+ }
+
+ return Task.FromResult(true);
+ }
+
+ private async Task LoadStartupConfig()
+ {
+ try
+ {
+ return await SMA.Core.Configuration.Load()
+ .ConfigureAwait(false) ?? new StartupCfg();
+ }
+ catch (SMAException)
+ {
+ await "Failed to open StartupCfg.json. Make sure file is unlocked and try again.".ErrorMsgBox();
+
+ return null;
+ }
+ }
+
+ private async Task LoadNativeDataConfig()
+ {
+ try
+ {
+ return await SMA.Core.Configuration.Load(SMAFileSystem.AppRootDir)
+ .ConfigureAwait(false);
+ }
+ catch (SMAException)
+ {
+ await "Failed to load native data config file.".ErrorMsgBox();
+
+ return null;
+ }
+ }
+
#endregion
}
}
diff --git a/src/AppHosts/SuperMemoAssistant/CollectionSelectionWindow.xaml b/src/AppHosts/SuperMemoAssistant/CollectionSelectionWindow.xaml
index 822156c..c84673b 100644
--- a/src/AppHosts/SuperMemoAssistant/CollectionSelectionWindow.xaml
+++ b/src/AppHosts/SuperMemoAssistant/CollectionSelectionWindow.xaml
@@ -23,7 +23,6 @@
KeyDown="Window_KeyDown">
-
@@ -72,6 +71,23 @@
+
+
+
diff --git a/src/AppHosts/SuperMemoAssistant/CollectionSelectionWindow.xaml.cs b/src/AppHosts/SuperMemoAssistant/CollectionSelectionWindow.xaml.cs
index ddf7923..77982a3 100644
--- a/src/AppHosts/SuperMemoAssistant/CollectionSelectionWindow.xaml.cs
+++ b/src/AppHosts/SuperMemoAssistant/CollectionSelectionWindow.xaml.cs
@@ -39,7 +39,6 @@
using Forge.Forms;
using MahApps.Metro.Controls;
using Microsoft.Win32;
-using SuperMemoAssistant.Exceptions;
using SuperMemoAssistant.Extensions;
using SuperMemoAssistant.Interop.SuperMemo.Core;
using SuperMemoAssistant.SMA.Configs;
@@ -53,7 +52,7 @@ public partial class CollectionSelectionWindow : MetroWindow
{
#region Properties & Fields - Non-Public
- private readonly StartupCfg _config;
+ private readonly StartupCfg _startupCfg;
#endregion
@@ -62,21 +61,10 @@ public partial class CollectionSelectionWindow : MetroWindow
#region Constructors
- public CollectionSelectionWindow()
+ public CollectionSelectionWindow(StartupCfg startupCfg)
{
- try
- {
- _config = SuperMemoAssistant.SMA.Core.Configuration.Load().Result ?? new StartupCfg();
- }
- catch (SMAException)
- {
- Forge.Forms.Show.Window().For(new Alert("Failed to open StartupCfg.json. Make sure file is unlocked and try again.", "Error"));
-
- Environment.Exit(1);
- return;
- }
-
- SavedCollections = _config.Collections;
+ _startupCfg = startupCfg;
+ SavedCollections = startupCfg.Collections;
InitializeComponent();
@@ -107,11 +95,11 @@ public CollectionSelectionWindow()
public bool ValidateSuperMemoPath()
{
- if (new FilePath(_config.SMBinPath).Exists() == false)
+ if (new FilePath(_startupCfg.SMBinPath).Exists() == false)
{
Forge.Forms.Show.Window().For(
new Alert(
- $"Invalid file path for sm executable file: '{_config.SMBinPath}' could not be found.",
+ $"Invalid file path for sm executable file: '{_startupCfg.SMBinPath}' could not be found.",
"Error")
);
return false;
@@ -162,7 +150,7 @@ private void DeleteCollection(SMCollection collection)
private void SaveConfig()
{
- SuperMemoAssistant.SMA.Core.Configuration.Save(_config).Wait();
+ SuperMemoAssistant.SMA.Core.Configuration.Save(_startupCfg).Wait();
}
private void OpenSelectedCollection()
@@ -205,13 +193,13 @@ private void btnBrowse_Click(object sender,
if (filePath != null)
{
var newCollection = CreateCollection(filePath);
- var duplicate = _config.Collections.FirstOrDefault(c => c == newCollection);
+ var duplicate = _startupCfg.Collections.FirstOrDefault(c => c == newCollection);
if (duplicate != null)
duplicate.LastOpen = DateTime.Now;
else
- _config.Collections.Add(newCollection);
+ _startupCfg.Collections.Add(newCollection);
SaveConfig();
@@ -220,6 +208,11 @@ private void btnBrowse_Click(object sender,
}
}
+ private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
+ {
+ OpenSelectedCollection();
+ }
+
private void btnOpen_Click(object sender,
RoutedEventArgs e)
{
@@ -229,7 +222,7 @@ private void btnOpen_Click(object sender,
private void BtnOptions_Click(object sender,
RoutedEventArgs e)
{
- Forge.Forms.Show.Window().For(_config).Wait();
+ Forge.Forms.Show.Window().For(_startupCfg).Wait();
SaveConfig();
}
@@ -251,11 +244,6 @@ private void CollectionSelectionWindow_Loaded(object sender,
lbCollections.SelectFirstItem();
}
- private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
- {
- OpenSelectedCollection();
- }
-
#endregion
}
}
diff --git a/src/AppHosts/SuperMemoAssistant/FodyWeavers.xml b/src/AppHosts/SuperMemoAssistant/FodyWeavers.xml
index 76dcf1e..3473f82 100644
--- a/src/AppHosts/SuperMemoAssistant/FodyWeavers.xml
+++ b/src/AppHosts/SuperMemoAssistant/FodyWeavers.xml
@@ -2,4 +2,5 @@
+
\ No newline at end of file
diff --git a/src/AppHosts/SuperMemoAssistant/FodyWeavers.xsd b/src/AppHosts/SuperMemoAssistant/FodyWeavers.xsd
index 8b42339..0f2523c 100644
--- a/src/AppHosts/SuperMemoAssistant/FodyWeavers.xsd
+++ b/src/AppHosts/SuperMemoAssistant/FodyWeavers.xsd
@@ -4,6 +4,35 @@
+
+
+
+
+ Used to control if the On_PropertyName_Changed feature is enabled.
+
+
+
+
+ Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.
+
+
+
+
+ Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.
+
+
+
+
+ Used to control if equality checks should use the Equals method resolved from the base class.
+
+
+
+
+ Used to control if equality checks should use the static Equals method resolved from the base class.
+
+
+
+
diff --git a/src/AppHosts/SuperMemoAssistant/Properties/AssemblyInfo.cs b/src/AppHosts/SuperMemoAssistant/Properties/AssemblyInfo.cs
index 2b6d1ea..0ea43f1 100644
--- a/src/AppHosts/SuperMemoAssistant/Properties/AssemblyInfo.cs
+++ b/src/AppHosts/SuperMemoAssistant/Properties/AssemblyInfo.cs
@@ -81,7 +81,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.17")]
-[assembly: AssemblyFileVersion("2.0.2.17")]
+[assembly: AssemblyVersion("2.0.2.67")]
+[assembly: AssemblyFileVersion("2.0.2.67")]
[assembly: AssemblyInformationalVersion("2.0.2")]
diff --git a/src/AppHosts/SuperMemoAssistant/SMATaskbarIcon.cs b/src/AppHosts/SuperMemoAssistant/SMATaskbarIcon.cs
index b5e7e65..8297abb 100644
--- a/src/AppHosts/SuperMemoAssistant/SMATaskbarIcon.cs
+++ b/src/AppHosts/SuperMemoAssistant/SMATaskbarIcon.cs
@@ -134,7 +134,7 @@ private void PreviewTrayContextMenuOpen(object sender,
.ToList();
// ReSharper disable once PossibleNullReferenceException
- while (tbIcon.ContextMenu.Items.Count > 0 && ((Control)tbIcon.ContextMenu.Items.GetItemAt(0)).Tag.Equals(MenuPluginTag))
+ while (tbIcon.ContextMenu.Items.Count > 0 && MenuPluginTag.Equals(((Control)tbIcon.ContextMenu.Items.GetItemAt(0)).Tag))
tbIcon.ContextMenu.Items.RemoveAt(0);
if (runningPlugins.Any())
diff --git a/src/AppHosts/SuperMemoAssistant/SuperMemoAssistant.csproj b/src/AppHosts/SuperMemoAssistant/SuperMemoAssistant.csproj
index 07bc1cf..a1e372a 100644
--- a/src/AppHosts/SuperMemoAssistant/SuperMemoAssistant.csproj
+++ b/src/AppHosts/SuperMemoAssistant/SuperMemoAssistant.csproj
@@ -1,5 +1,6 @@
+
@@ -93,6 +94,12 @@
..\..\..\packages\MahApps.Metro.1.6.5\lib\net47\MahApps.Metro.dll
+
+ ..\..\..\packages\Markdig.0.18.0\lib\net40\Markdig.dll
+
+
+ ..\..\..\packages\Markdig.Wpf.0.3.1\lib\net452\Markdig.Wpf.dll
+
..\..\..\packages\MaterialDesignColors.1.1.3\lib\net45\MaterialDesignColors.dll
@@ -109,17 +116,20 @@
..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
-
- ..\..\..\packages\Sentry.1.2.0\lib\net461\Sentry.dll
+
+ ..\..\..\packages\PropertyChanged.Fody.3.2.5\lib\net40\PropertyChanged.dll
+
+
+ ..\..\..\packages\Sentry.2.0.1\lib\net461\Sentry.dll
-
- ..\..\..\packages\Sentry.PlatformAbstractions.1.0.0\lib\net471\Sentry.PlatformAbstractions.dll
+
+ ..\..\..\packages\Sentry.PlatformAbstractions.1.1.0\lib\net471\Sentry.PlatformAbstractions.dll
-
- ..\..\..\packages\Sentry.Protocol.1.0.6\lib\net46\Sentry.Protocol.dll
+
+ ..\..\..\packages\Sentry.Protocol.2.0.0\lib\net46\Sentry.Protocol.dll
-
- ..\..\..\packages\Sentry.Serilog.1.2.0\lib\net461\Sentry.Serilog.dll
+
+ ..\..\..\packages\Sentry.Serilog.2.0.1\lib\net461\Sentry.Serilog.dll
..\..\..\packages\Serilog.2.9.0\lib\net46\Serilog.dll
@@ -164,6 +174,10 @@
+
+
+ SuperMemoFinder.xaml
+
Designer
MSBuild:Compile
@@ -180,6 +194,10 @@
XamlIntelliSenseFileGenerator
SMATaskbarIcon.cs
+
+ Designer
+ MSBuild:Compile
+
@@ -218,10 +236,18 @@
{7550628d-0630-4a42-b0b7-55d26f981365}
SuperMemoAssistant.Core
+
+ {CC5B9485-9EF1-4133-9242-719D263700AE}
+ SuperMemoAssistant.Hooks.Common
+
{fd0e1be8-bed3-4ab0-a9c8-022a2dbc8450}
SuperMemoAssistant.Interop
+
+ {7F7B4A1F-01E1-440E-89DB-08F7D1D5A128}
+ SuperMemoAssistant.Services.UI
+
@@ -243,7 +269,8 @@
-
+
+
-
+
\ No newline at end of file
diff --git a/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.SuperMemoFilePath.cs b/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.SuperMemoFilePath.cs
new file mode 100644
index 0000000..3fb85d4
--- /dev/null
+++ b/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.SuperMemoFilePath.cs
@@ -0,0 +1,127 @@
+#region License & Metadata
+
+// The MIT License (MIT)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//
+// Modified On: 2020/02/03 16:21
+// Modified By: Alexis
+
+#endregion
+
+
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using SuperMemoAssistant.Exceptions;
+using SuperMemoAssistant.SMA.Configs;
+using SuperMemoAssistant.Sys.IO;
+
+namespace SuperMemoAssistant
+{
+ public partial class SuperMemoFinder
+ {
+ public class SuperMemoFilePath : INotifyDataErrorInfo
+ {
+ #region Properties & Fields - Non-Public
+
+ private readonly SMAException _ex;
+
+ #endregion
+
+
+
+
+ #region Constructors
+
+ public SuperMemoFilePath(FilePath filePath, NativeDataCfg nativeDataCfg)
+ {
+ FilePath = filePath;
+
+ HasErrors = SMA.Utils.SuperMemoFinder.CheckSuperMemoExecutable(nativeDataCfg, filePath, out _, out var ex) == false;
+ _ex = ex;
+ }
+
+ #endregion
+
+
+
+
+ #region Properties & Fields - Public
+
+ public FilePath FilePath { get; }
+
+ #endregion
+
+
+
+
+ #region Properties Impl - Public
+
+ ///
+ public bool HasErrors { get; }
+
+ #endregion
+
+
+
+
+ #region Methods Impl
+
+ public override string ToString()
+ {
+ return FilePath.FullPathWin;
+ }
+
+ ///
+ public IEnumerable GetErrors(string propertyName)
+ {
+ return new List { _ex.Message };
+ }
+
+ #endregion
+
+
+
+
+ #region Methods
+
+ public static implicit operator string(SuperMemoFilePath smFilePath)
+ {
+ return smFilePath.ToString();
+ }
+
+ #endregion
+
+
+
+
+ #region Events
+
+ ///
+ public event EventHandler ErrorsChanged;
+
+ #endregion
+ }
+ }
+}
diff --git a/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.xaml b/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.xaml
new file mode 100644
index 0000000..08ec66c
--- /dev/null
+++ b/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.xaml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.xaml.cs b/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.xaml.cs
new file mode 100644
index 0000000..b36cfae
--- /dev/null
+++ b/src/AppHosts/SuperMemoAssistant/SuperMemoFinder.xaml.cs
@@ -0,0 +1,192 @@
+#region License & Metadata
+
+// The MIT License (MIT)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//
+// Modified On: 2020/02/03 16:21
+// Modified By: Alexis
+
+#endregion
+
+
+
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using MahApps.Metro.Controls;
+using Microsoft.Win32;
+using PropertyChanged;
+using SuperMemoAssistant.Extensions;
+using SuperMemoAssistant.SMA.Configs;
+using SuperMemoAssistant.Sys.Windows.Input;
+using SuperMemoFinderUtil = SuperMemoAssistant.SMA.Utils.SuperMemoFinder;
+
+// ReSharper disable RedundantNameQualifier
+
+namespace SuperMemoAssistant
+{
+ /// Interaction logic for SuperMemoFinder.xaml
+ public partial class SuperMemoFinder : MetroWindow, INotifyPropertyChanged
+ {
+ #region Properties & Fields - Non-Public
+
+ private readonly StartupCfg _startupCfg;
+ private readonly NativeDataCfg _nativeDataCfg;
+
+ #endregion
+
+
+
+
+ #region Constructors
+
+ public SuperMemoFinder(NativeDataCfg nativeDataCfg, StartupCfg startupCfg)
+ {
+ _nativeDataCfg = nativeDataCfg;
+ _startupCfg = startupCfg;
+
+ SMExeFilePath = new SuperMemoFilePath(startupCfg.SMBinPath, nativeDataCfg);
+ SMExeSuggestedFilePaths = SuperMemoFinderUtil.SearchSuperMemoInDefaultLocations()
+ .Select(fp => fp.FullPathWin)
+ .ToHashSet();
+
+ AcceptCommand = new RelayCommand(Accept, CanAcceptExecute);
+ BrowseCommand = new RelayCommand(Browse);
+
+ BuildDescriptionText();
+
+ Task.Run(SearchForSuperMemo).RunAsync();
+
+ InitializeComponent();
+ }
+
+ #endregion
+
+
+
+
+ #region Properties & Fields - Public
+
+ public string DescriptionText { get; set; }
+ public SuperMemoFilePath SMExeFilePath { get; private set; }
+ public HashSet SMExeSuggestedFilePaths { get; }
+
+ [DependsOn(nameof(SMExeFilePath))]
+ public ICommand AcceptCommand { get; }
+ public ICommand BrowseCommand { get; }
+
+ #endregion
+
+
+
+
+ #region Methods
+
+ private bool CanAcceptExecute()
+ {
+ return (SMExeFilePath?.HasErrors ?? true) == false;
+ }
+
+ private void Accept()
+ {
+ _startupCfg.SMBinPath = SMExeFilePath;
+ SuperMemoAssistant.SMA.Core.Configuration.Save(_startupCfg).Wait();
+
+ DialogResult = true;
+
+ Close();
+ }
+
+ private void Browse()
+ {
+ OpenFileDialog dlg = new OpenFileDialog
+ {
+ DefaultExt = ".exe",
+ Filter = "Executable (*.exe)|*.exe|All files (*.*)|*.*"
+ };
+
+ var filePath = dlg.ShowDialog().GetValueOrDefault(false)
+ ? dlg.FileName
+ : null;
+
+ if (filePath != null)
+ SMExeFilePath = new SuperMemoFilePath(filePath, _nativeDataCfg);
+ }
+
+ private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
+ {
+ if (lbPaths.SelectedItem is string filePath)
+ SMExeFilePath = new SuperMemoFilePath(filePath, _nativeDataCfg);
+ }
+
+ private void BuildDescriptionText()
+ {
+ var versions = _nativeDataCfg.Values
+ .Select(nd => nd.SMVersion)
+ .OrderBy(v => v);
+ var versionStr = string.Join("*, *", versions);
+
+ DescriptionText = @$"Select your **SuperMemo executable** (.exe). You can:
+- Use the Browse button,
+- Double click on one of the suggested item from the list below.
+
+If you need help, visit https://www.supermemo.wiki/sma
+> **Supported versions**: *{versionStr}*";
+ }
+
+ private async Task SearchForSuperMemo()
+ {
+ var smFilePaths = await SuperMemoFinderUtil.SearchSuperMemoInWindowsIndex();
+
+ SMExeSuggestedFilePaths.UnionWith(smFilePaths.Where(fp => fp.Exists())
+ .Select(fp => fp.FullPathWin));
+ }
+
+ private void MetroWindow_Loaded(object sender, EventArgs e)
+ {
+ //DialogResult = false;
+ }
+
+ private void MetroWindow_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter && AcceptCommand.CanExecute(null))
+ AcceptCommand.Execute(null);
+
+ else if (e.Key == Key.Escape)
+ Close();
+ }
+
+ #endregion
+
+
+
+
+ #region Events
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+ }
+}
diff --git a/src/AppHosts/SuperMemoAssistant/packages.config b/src/AppHosts/SuperMemoAssistant/packages.config
index 0b1e2d5..2e965d7 100644
--- a/src/AppHosts/SuperMemoAssistant/packages.config
+++ b/src/AppHosts/SuperMemoAssistant/packages.config
@@ -6,21 +6,24 @@
-
+
+
+
-
-
-
-
+
+
+
+
+
diff --git a/src/Core/SuperMemoAssistant.Core/NativeDataCfg.json b/src/Core/SuperMemoAssistant.Core/NativeDataCfg.json
index 3e42958..1172be4 100644
--- a/src/Core/SuperMemoAssistant.Core/NativeDataCfg.json
+++ b/src/Core/SuperMemoAssistant.Core/NativeDataCfg.json
@@ -1,6 +1,6 @@
{
"7EDE24CE": {
- "SMVersion": "17.4",
+ "SMVersion": "17.40",
"Pointers": {
"ElWdw_InstancePtr": "0x00BC00F0",
"ElWdw_ElementIdPtr": "0x0D81",
@@ -138,7 +138,7 @@
},
"5BA7F64F": {
- "SMVersion": "18.3",
+ "SMVersion": "18.03",
"Pointers": {
"ElWdw_InstancePtr": "0x00CA36D0",
"ElWdw_ElementIdPtr": "0x0DB1",
diff --git a/src/Core/SuperMemoAssistant.Core/Plugins/PackageManager/NuGet/Project/NuGetInstalledPluginRepository.cs b/src/Core/SuperMemoAssistant.Core/Plugins/PackageManager/NuGet/Project/NuGetInstalledPluginRepository.cs
index 7947485..1effe08 100644
--- a/src/Core/SuperMemoAssistant.Core/Plugins/PackageManager/NuGet/Project/NuGetInstalledPluginRepository.cs
+++ b/src/Core/SuperMemoAssistant.Core/Plugins/PackageManager/NuGet/Project/NuGetInstalledPluginRepository.cs
@@ -36,7 +36,6 @@
using System.Linq;
using System.Threading.Tasks;
using Anotar.Serilog;
-using JetBrains.Annotations;
using Newtonsoft.Json;
using NuGet.Packaging.Core;
using SuperMemoAssistant.Extensions;
@@ -102,7 +101,7 @@ public void Dispose()
#region Methods
public static async Task> LoadAsync(
- [NotNull] FilePath filePath)
+ FilePath filePath)
{
NuGetInstalledPluginRepository repo = null;
diff --git a/src/Core/SuperMemoAssistant.Core/Plugins/PackageManager/PluginPackageManager.cs b/src/Core/SuperMemoAssistant.Core/Plugins/PackageManager/PluginPackageManager.cs
index a971fcd..84e0e92 100644
--- a/src/Core/SuperMemoAssistant.Core/Plugins/PackageManager/PluginPackageManager.cs
+++ b/src/Core/SuperMemoAssistant.Core/Plugins/PackageManager/PluginPackageManager.cs
@@ -37,7 +37,6 @@
using System.Threading;
using System.Threading.Tasks;
using Anotar.Serilog;
-using JetBrains.Annotations;
using NuGet.Configuration;
using NuGet.Frameworks;
using NuGet.PackageManagement;
@@ -69,10 +68,10 @@ public class PluginPackageManager
#region Constructors
- internal PluginPackageManager([NotNull] DirectoryPath pluginDirPath,
- [NotNull] DirectoryPath pluginHomeDirPath,
- [NotNull] DirectoryPath packageDirPath,
- [NotNull] FilePath configFilePath,
+ internal PluginPackageManager(DirectoryPath pluginDirPath,
+ DirectoryPath pluginHomeDirPath,
+ DirectoryPath packageDirPath,
+ FilePath configFilePath,
Func providerCreator = null)
{
pluginDirPath = pluginDirPath.Collapse();
diff --git a/src/Core/SuperMemoAssistant.Core/Plugins/PluginManager.cs b/src/Core/SuperMemoAssistant.Core/Plugins/PluginManager.cs
index 7fab920..54c986d 100644
--- a/src/Core/SuperMemoAssistant.Core/Plugins/PluginManager.cs
+++ b/src/Core/SuperMemoAssistant.Core/Plugins/PluginManager.cs
@@ -6,7 +6,7 @@
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
+// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
@@ -21,8 +21,7 @@
// DEALINGS IN THE SOFTWARE.
//
//
-// Created On: 2019/02/13 13:55
-// Modified On: 2019/02/24 20:00
+// Modified On: 2020/02/03 10:35
// Modified By: Alexis
#endregion
@@ -42,7 +41,7 @@
using SuperMemoAssistant.Interop.SuperMemo.Core;
using SuperMemoAssistant.SMA;
using SuperMemoAssistant.Sys;
-using static MoreLinq.Extensions.DistinctByExtension;
+using DistinctBy = MoreLinq.Extensions.DistinctByExtension;
// ReSharper disable RedundantTypeArgumentsOfMethod
@@ -200,7 +199,10 @@ private void OnPluginStopped(PluginInstance pluginInstance)
if (pluginInstance.Process?.HasExited ?? false)
crashed = pluginInstance.Process.ExitCode != 0;
}
- catch { /* ignored */ }
+ catch
+ {
+ /* ignored */
+ }
LogTo.Information($"{pluginInstance.Denomination.CapitalizeFirst()} {pluginInstance.Metadata.PackageName} "
+ $"has {(crashed ? "crashed" : "stopped")}");
diff --git a/src/Core/SuperMemoAssistant.Core/Properties/AssemblyInfo.cs b/src/Core/SuperMemoAssistant.Core/Properties/AssemblyInfo.cs
index 3944509..03be3fd 100644
--- a/src/Core/SuperMemoAssistant.Core/Properties/AssemblyInfo.cs
+++ b/src/Core/SuperMemoAssistant.Core/Properties/AssemblyInfo.cs
@@ -63,7 +63,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.15")]
-[assembly: AssemblyFileVersion("2.0.2.15")]
+[assembly: AssemblyVersion("2.0.2.31")]
+[assembly: AssemblyFileVersion("2.0.2.31")]
[assembly: AssemblyInformationalVersion("2.0.2")]
diff --git a/src/Core/SuperMemoAssistant.Core/SMA/Configs/StartupCfg.cs b/src/Core/SuperMemoAssistant.Core/SMA/Configs/StartupCfg.cs
index 023fa80..ed8ce51 100644
--- a/src/Core/SuperMemoAssistant.Core/SMA/Configs/StartupCfg.cs
+++ b/src/Core/SuperMemoAssistant.Core/SMA/Configs/StartupCfg.cs
@@ -58,7 +58,7 @@ public class StartupCfg : IActionHandler, INotifyPropertyChangedEx
[Action("BrowseFile",
"Browse",
Placement = Placement.Inline)]
- public string SMBinPath { get; set; } = SMConst.BinPath;
+ public string SMBinPath { get; set; }
[Field(Name = "Skip procedures pattern scanning (trust hint addresses)")]
public bool TrustHintAddresses { get; set; } = false;
diff --git a/src/Core/SuperMemoAssistant.Core/SMA/SuperMemoAssistant.Config.cs b/src/Core/SuperMemoAssistant.Core/SMA/SuperMemoAssistant.Config.cs
index abb9576..4462f8f 100644
--- a/src/Core/SuperMemoAssistant.Core/SMA/SuperMemoAssistant.Config.cs
+++ b/src/Core/SuperMemoAssistant.Core/SMA/SuperMemoAssistant.Config.cs
@@ -36,7 +36,6 @@
using Anotar.Serilog;
using Process.NET.Windows;
using SuperMemoAssistant.Extensions;
-using SuperMemoAssistant.Interop;
using SuperMemoAssistant.Interop.SuperMemo.Core;
using SuperMemoAssistant.SMA.Configs;
@@ -75,28 +74,13 @@ private void ApplySuperMemoWindowStyles()
}).RunAsync();
}
- private NativeDataCfg LoadNativeDataConfig()
- {
- var nativeDataCfg =
- Core.Configuration.Load(SMAFileSystem.AppRootDir).Result
- ?? new NativeDataCfg();
-
- if (nativeDataCfg == null)
- throw new InvalidOperationException("Failed to load native data config file.");
-
- return nativeDataCfg;
- }
-
- private void LoadConfig(SMCollection collection)
+ private void LoadConfig(SMCollection collection, StartupCfg startupCfg)
{
var knoPath = collection.GetKnoFilePath();
- // StartupCfg
-
- StartupConfig = Core.Configuration.Load().Result ?? new StartupCfg();
+ StartupConfig = startupCfg;
// CollectionsCfg
-
_collectionsCfg = Core.Configuration.Load().Result ?? new CollectionsCfg();
CollectionConfig = _collectionsCfg.CollectionsConfig.SafeGet(knoPath);
diff --git a/src/Core/SuperMemoAssistant.Core/SMA/SuperMemoAssistant.cs b/src/Core/SuperMemoAssistant.Core/SMA/SuperMemoAssistant.cs
index 8fc8ff6..51e4764 100644
--- a/src/Core/SuperMemoAssistant.Core/SMA/SuperMemoAssistant.cs
+++ b/src/Core/SuperMemoAssistant.Core/SMA/SuperMemoAssistant.cs
@@ -32,17 +32,16 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.Linq;
-using System.Security.Permissions;
using System.Threading.Tasks;
using Anotar.Serilog;
using AsyncEvent;
using Process.NET;
using SuperMemoAssistant.Exceptions;
-using SuperMemoAssistant.Extensions;
using SuperMemoAssistant.Interop.SuperMemo;
using SuperMemoAssistant.Interop.SuperMemo.Core;
+using SuperMemoAssistant.SMA.Configs;
+using SuperMemoAssistant.SMA.Utils;
using SuperMemoAssistant.SuperMemo;
using SuperMemoAssistant.SuperMemo.Common;
using SuperMemoAssistant.SuperMemo.Common.Content.Layout;
@@ -131,15 +130,19 @@ public virtual void Dispose()
//
// Collection loading management
- public async Task Start(SMCollection collection)
+ public async Task Start(
+ NativeDataCfg nativeDataCfg,
+ StartupCfg startupCfg,
+ SMCollection collection)
{
try
{
if (_sm != null)
throw new InvalidOperationException("_sm is already instantiated");
- LoadConfig(collection);
- var nativeData = CheckSuperMemoExecutable();
+ LoadConfig(collection, startupCfg);
+
+ var nativeData = CheckSuperMemoExecutable(nativeDataCfg);
_sm = InstantiateSuperMemo(collection, nativeData.SMVersion);
@@ -163,13 +166,11 @@ public async Task Start(SMCollection collection)
try
{
if (OnSMStoppedEvent != null)
- await OnSMStoppedEvent.InvokeAsync(this,
- new SMProcessArgs(_sm, null)).ConfigureAwait(true);
+ await OnSMStoppedEvent.InvokeAsync(this, new SMProcessArgs(_sm, null)).ConfigureAwait(true);
}
catch (Exception pluginEx)
{
- LogTo.Error(pluginEx,
- "Exception while notifying plugins OnSMStoppedEvent.");
+ LogTo.Error(pluginEx, "Exception while notifying plugins OnSMStoppedEvent.");
}
// TODO: Handle exception
@@ -184,32 +185,17 @@ private SuperMemoCore InstantiateSuperMemo(SMCollection collection,
Version smVersion)
{
if (SM17.Versions.Contains(smVersion))
- return new SM17(collection,
- StartupConfig.SMBinPath);
+ return new SM17(collection, StartupConfig.SMBinPath);
throw new SMAException($"Unsupported SM version {smVersion}");
}
- private NativeData CheckSuperMemoExecutable()
+ private NativeData CheckSuperMemoExecutable(NativeDataCfg nativeDataCfg)
{
- var nativeDataCfg = LoadNativeDataConfig();
var smFile = new FilePath(StartupConfig.SMBinPath);
- if (smFile.Exists() == false)
- throw new SMAException(
- $"Invalid file path for sm executable file: '{StartupConfig.SMBinPath}' could not be found. SMA cannot continue.");
-
- if (smFile.HasPermission(FileIOPermissionAccess.Read) == false)
- throw new SMAException($"SMA needs read access to execute SM executable at {smFile.FullPath}.");
-
- if (smFile.IsLocked())
- throw new SMAException($"{smFile.FullPath} is locked. Make sure it isn't already running.");
-
- var smFileCrc32 = FileEx.GetCrc32(smFile.FullPath);
- var nativeData = nativeDataCfg.SafeGet(smFileCrc32.ToUpper(CultureInfo.InvariantCulture));
-
- if (nativeData == null)
- throw new SMAException($"Unknown SM executable version with crc32 {smFileCrc32}.");
+ if (SuperMemoFinder.CheckSuperMemoExecutable(nativeDataCfg, smFile, out var nativeData, out var ex) == false)
+ throw ex;
LogTo.Information($"SuperMemo version {nativeData.SMVersion} detected");
diff --git a/src/Core/SuperMemoAssistant.Core/SMA/UI/Settings/Settings.Plugins.Installed.xaml.cs b/src/Core/SuperMemoAssistant.Core/SMA/UI/Settings/Settings.Plugins.Installed.xaml.cs
index e18f072..f40dcf7 100644
--- a/src/Core/SuperMemoAssistant.Core/SMA/UI/Settings/Settings.Plugins.Installed.xaml.cs
+++ b/src/Core/SuperMemoAssistant.Core/SMA/UI/Settings/Settings.Plugins.Installed.xaml.cs
@@ -32,12 +32,14 @@
using System;
using System.Collections.ObjectModel;
+using System.Runtime.Remoting;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using Anotar.Serilog;
using Forge.Forms;
using SuperMemoAssistant.Plugins;
+using SuperMemoAssistant.Services.UI.Extensions;
using SuperMemoAssistant.Sys.Windows.Input;
namespace SuperMemoAssistant.SMA.UI.Settings
@@ -72,7 +74,7 @@ public InstalledPluginSettings()
public ReadOnlyObservableCollection Plugins => PluginManager.Instance.AllPlugins;
- public ICommand PluginShowSettingsCommand => new RelayCommand(PluginShowSettings);
+ public ICommand PluginShowSettingsCommand => new AsyncRelayCommand(PluginShowSettings);
public ICommand PluginPlayPauseCommand => new AsyncRelayCommand(PluginPlayPause, CanPluginPlayPause, HandleException);
@@ -89,12 +91,16 @@ public InstalledPluginSettings()
#region Methods
- private void PluginShowSettings(PluginInstance pluginInstance)
+ private async Task PluginShowSettings(PluginInstance pluginInstance)
{
try
{
pluginInstance.Plugin.ShowSettings();
}
+ catch (RemotingException)
+ {
+ await "Remote plugin unreachable. Try restarting SMA.".ErrorMsgBox();
+ }
catch (Exception ex)
{
HandleException(ex);
diff --git a/src/Core/SuperMemoAssistant.Core/SMA/Utils/SuperMemoFinder.cs b/src/Core/SuperMemoAssistant.Core/SMA/Utils/SuperMemoFinder.cs
new file mode 100644
index 0000000..ee0feb3
--- /dev/null
+++ b/src/Core/SuperMemoAssistant.Core/SMA/Utils/SuperMemoFinder.cs
@@ -0,0 +1,191 @@
+#region License & Metadata
+
+// The MIT License (MIT)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//
+// Modified On: 2020/02/03 00:24
+// Modified By: Alexis
+
+#endregion
+
+
+
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Management;
+using System.Security.Permissions;
+using System.Threading.Tasks;
+using Anotar.Serilog;
+using SuperMemoAssistant.Exceptions;
+using SuperMemoAssistant.Extensions;
+using SuperMemoAssistant.SMA.Configs;
+using SuperMemoAssistant.SuperMemo;
+using SuperMemoAssistant.Sys.IO;
+using SuperMemoAssistant.Sys.Windows.Search;
+
+namespace SuperMemoAssistant.SMA.Utils
+{
+ public static class SuperMemoFinder
+ {
+ #region Constants & Statics
+
+ private static readonly DirectoryPath[] SuperMemoFolderNames = { "SuperMemo", "SuperMemo17", "SuperMemo18" };
+ private static readonly string[] SuperMemoExeFileNames = { "sm17.exe", "sm18.exe" };
+
+ #endregion
+
+
+
+
+ #region Methods
+
+ public static List SearchSuperMemoInDefaultLocations()
+ {
+ try
+ {
+ var smExePaths = new List();
+
+ foreach (var rootDirPath in ListRootDirPaths())
+ foreach (var smFolderName in SuperMemoFolderNames)
+ foreach (var smExeFileName in SuperMemoExeFileNames)
+ try
+ {
+ var smExePath = rootDirPath.Combine(smFolderName).CombineFile(smExeFileName);
+
+ if (smExePath.Exists())
+ smExePaths.Add(smExePath);
+ }
+ catch (Exception ex)
+ {
+ LogTo.Error(ex, "Exception thrown while checking existence of a SuperMemo executable path");
+ }
+
+ return smExePaths;
+ }
+ catch (Exception ex)
+ {
+ LogTo.Error(ex, "Exception thrown while searching for SuperMemo executables");
+
+ return null;
+ }
+ }
+
+ public static async Task> SearchSuperMemoInWindowsIndex()
+ {
+ if (WindowsSearch.Instance.IsAvailable == false)
+ {
+ LogTo.Warning("Windows search is unavailable. Searching for SuperMemo executable aborted");
+ return new List();
+ }
+
+ var wsRes = await WindowsSearch.Instance.Search("sm1%.exe", WindowsSearchKind.Program);
+
+ return wsRes.Select(wsr => new FilePath(wsr.FilePath))
+ .ToList();
+ }
+
+ public static bool CheckSuperMemoExecutable(
+ NativeDataCfg nativeDataCfg,
+ FilePath smFile,
+ out NativeData nativeData,
+ out SMAException ex)
+ {
+ nativeData = null;
+
+ if (smFile.Exists() == false)
+ {
+ ex = new SMAException(
+ $"Invalid file path for sm executable file: '{smFile}' could not be found. SMA cannot continue.");
+ return false;
+ }
+
+ if (smFile.HasPermission(FileIOPermissionAccess.Read) == false)
+ {
+ ex = new SMAException($"SMA needs read access to execute SM executable at {smFile.FullPath}.");
+ return false;
+ }
+
+ if (smFile.IsLocked())
+ {
+ ex = new SMAException($"{smFile.FullPath} is locked. Make sure it isn't already running.");
+ return false;
+ }
+
+ var smFileCrc32 = FileEx.GetCrc32(smFile.FullPath);
+ nativeData = nativeDataCfg.SafeGet(smFileCrc32.ToUpper(CultureInfo.InvariantCulture));
+
+ if (nativeData == null)
+ {
+ ex = new SMAException($"Unknown SM executable version with crc32 {smFileCrc32}.");
+ return false;
+ }
+
+ ex = null;
+
+ return true;
+ }
+
+ private static IEnumerable ListRootDirPaths()
+ {
+ var userRootDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
+
+ var folderPaths = new[]
+ {
+ Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
+ Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
+ Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
+ Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
+ Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ userRootDir,
+ Path.Combine(userRootDir, "Google Drive"),
+ Path.Combine(userRootDir, "Dropbox"),
+ Path.Combine(userRootDir, "OneDrive"),
+ };
+
+ return folderPaths.Concat(ListDrives())
+ .Select(fp => new DirectoryPath(fp));
+ }
+
+
+ public static List ListDrives()
+ {
+ var drives = new List();
+
+ using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Volume"))
+ {
+ ManagementObjectCollection collection = searcher.Get();
+
+ foreach (var mbo in collection)
+ if (mbo is ManagementObject mo)
+ drives.Add((string)mo["DriveLetter"]);
+ }
+
+ return drives.Where(d => string.IsNullOrWhiteSpace(d) == false)
+ .ToList();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Core/SuperMemoAssistant.Core/SuperMemo/Common/UI/WdwBase.cs b/src/Core/SuperMemoAssistant.Core/SuperMemo/Common/UI/WdwBase.cs
index 78bf2c4..f1afa39 100644
--- a/src/Core/SuperMemoAssistant.Core/SuperMemo/Common/UI/WdwBase.cs
+++ b/src/Core/SuperMemoAssistant.Core/SuperMemo/Common/UI/WdwBase.cs
@@ -67,6 +67,8 @@ public abstract class WdwBase : /*UIAutomationBase,*/ MarshalByRefObject, IWdw
///
public IntPtr Handle => WindowHandle;
+ ///
+ public bool IsAvailable { get; protected set; }
#endregion
diff --git a/src/Core/SuperMemoAssistant.Core/SuperMemo/Hooks/SMHookEngine.cs b/src/Core/SuperMemoAssistant.Core/SuperMemo/Hooks/SMHookEngine.cs
index 9bd954e..fda788c 100644
--- a/src/Core/SuperMemoAssistant.Core/SuperMemo/Hooks/SMHookEngine.cs
+++ b/src/Core/SuperMemoAssistant.Core/SuperMemo/Hooks/SMHookEngine.cs
@@ -106,8 +106,7 @@ public override bool OnHookInstalled(bool success,
Exception hookEx = null)
{
if (hookEx != null)
- LogTo.Error(hookEx,
- "InjectionLib threw an error during initialization.");
+ OnException(hookEx);
try
{
@@ -122,8 +121,7 @@ public override bool OnHookInstalled(bool success,
}
catch (Exception ex)
{
- LogTo.Error(ex,
- "Failed to Signal InitEvent for Hook Install Success");
+ LogTo.Error(ex, "Failed to Signal InitEvent for Hook Install Success");
return false;
}
@@ -134,8 +132,7 @@ public override void KeepAlive() { }
public override void Debug(string msg,
params object[] args)
{
- LogTo.Debug(msg,
- args);
+ LogTo.Debug(msg, args);
}
diff --git a/src/Core/SuperMemoAssistant.Core/SuperMemo/SuperMemo17/UI/ElementWdw.cs b/src/Core/SuperMemoAssistant.Core/SuperMemo/SuperMemo17/UI/ElementWdw.cs
index 9abeb1d..d40167a 100644
--- a/src/Core/SuperMemoAssistant.Core/SuperMemo/SuperMemo17/UI/ElementWdw.cs
+++ b/src/Core/SuperMemoAssistant.Core/SuperMemo/SuperMemo17/UI/ElementWdw.cs
@@ -74,6 +74,8 @@ public class ElementWdw : WdwBase, IElementWdw
public ElementWdw()
{
+ IsAvailable = false;
+
Core.SMA.OnSMStartedEvent += OnSMStartedEvent;
Core.SMA.OnSMStoppedEvent += OnSMStoppedEvent;
}
@@ -95,7 +97,7 @@ public bool ActivateWindow()
}
catch (ApplicationException ex)
{
- LogTo.Error(ex, "Windows API call failed.");
+ LogTo.Warning(ex, "Windows API call failed (ActivateWindow).");
return false;
}
catch (Exception ex)
@@ -530,6 +532,8 @@ private bool OnWindowCreated(byte[] newVal)
// CurrentElement,
// null));
+ IsAvailable = true;
+
OnAvailable?.Invoke();
return true;
diff --git a/src/Core/SuperMemoAssistant.Core/SuperMemoAssistant.Core.csproj b/src/Core/SuperMemoAssistant.Core/SuperMemoAssistant.Core.csproj
index 98b9158..3f8f625 100644
--- a/src/Core/SuperMemoAssistant.Core/SuperMemoAssistant.Core.csproj
+++ b/src/Core/SuperMemoAssistant.Core/SuperMemoAssistant.Core.csproj
@@ -1,6 +1,6 @@
-
+
@@ -105,9 +105,6 @@
..\..\..\packages\FlaUI.UIA3.2.0.0-rc1\lib\net45\Interop.UIAutomationClient.dll
False
-
- ..\..\..\packages\JetBrains.Annotations.2019.1.3\lib\net20\JetBrains.Annotations.dll
-
..\..\..\packages\MahApps.Metro.1.6.5\lib\net47\MahApps.Metro.dll
@@ -196,8 +193,8 @@
-
- ..\..\..\packages\PropertyChanged.Fody.3.2.4\lib\net40\PropertyChanged.dll
+
+ ..\..\..\packages\PropertyChanged.Fody.3.2.5\lib\net40\PropertyChanged.dll
..\..\..\packages\Serilog.2.9.0\lib\net46\Serilog.dll
@@ -216,6 +213,7 @@
+
..\..\..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll
@@ -304,6 +302,7 @@
+
@@ -547,8 +546,8 @@
-
-
+
+
-
+
\ No newline at end of file
diff --git a/src/Core/SuperMemoAssistant.Core/packages.config b/src/Core/SuperMemoAssistant.Core/packages.config
index 2e5b8a1..dae4e54 100644
--- a/src/Core/SuperMemoAssistant.Core/packages.config
+++ b/src/Core/SuperMemoAssistant.Core/packages.config
@@ -9,12 +9,11 @@
-
+
-
@@ -50,7 +49,7 @@
-
+
diff --git a/src/Core/SuperMemoAssistant.Hooks.Common/Properties/AssemblyInfo.cs b/src/Core/SuperMemoAssistant.Hooks.Common/Properties/AssemblyInfo.cs
index 078cc14..64e16d5 100644
--- a/src/Core/SuperMemoAssistant.Hooks.Common/Properties/AssemblyInfo.cs
+++ b/src/Core/SuperMemoAssistant.Hooks.Common/Properties/AssemblyInfo.cs
@@ -63,7 +63,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.2")]
-[assembly: AssemblyFileVersion("2.0.2.2")]
+[assembly: AssemblyVersion("2.0.2.5")]
+[assembly: AssemblyFileVersion("2.0.2.5")]
[assembly: AssemblyInformationalVersion("2.0.2")]
\ No newline at end of file
diff --git a/src/Core/SuperMemoAssistant.Hooks.InjectLib/Properties/AssemblyInfo.cs b/src/Core/SuperMemoAssistant.Hooks.InjectLib/Properties/AssemblyInfo.cs
index 81ad2b1..3240e46 100644
--- a/src/Core/SuperMemoAssistant.Hooks.InjectLib/Properties/AssemblyInfo.cs
+++ b/src/Core/SuperMemoAssistant.Hooks.InjectLib/Properties/AssemblyInfo.cs
@@ -63,7 +63,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.5")]
-[assembly: AssemblyFileVersion("2.0.2.5")]
+[assembly: AssemblyVersion("2.0.2.9")]
+[assembly: AssemblyFileVersion("2.0.2.9")]
[assembly: AssemblyInformationalVersion("2.0.2")]
diff --git a/src/Core/SuperMemoAssistant.Hooks.InjectLib/SMInject.SM.cs b/src/Core/SuperMemoAssistant.Hooks.InjectLib/SMInject.SM.cs
index 232abbc..2cdd167 100644
--- a/src/Core/SuperMemoAssistant.Hooks.InjectLib/SMInject.SM.cs
+++ b/src/Core/SuperMemoAssistant.Hooks.InjectLib/SMInject.SM.cs
@@ -33,8 +33,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Linq;
using System.Runtime.InteropServices;
+using System.Runtime.Remoting;
using Process.NET;
using Process.NET.Marshaling;
using Process.NET.Memory;
@@ -113,7 +113,11 @@ private unsafe void WndProc(int _,
{
try
{
- SMA.Debug($"Received WndProc message {msgPtr->msg} with wParam {msgPtr->wParam}.");
+ try
+ {
+ SMA.Debug($"Received WndProc message {msgPtr->msg} with wParam {msgPtr->wParam}.");
+ }
+ catch (RemotingException) {}
if (msgPtr == null
|| msgPtr->msg == (int)WindowsMessages.Quit
@@ -167,11 +171,29 @@ protected int CallNativeMethod(NativeMethod method,
{
SMA.Debug($"Executing native method {Enum.GetName(typeof(NativeMethod), method)}.");
+ if (parameters == null)
+ {
+ OnException(new ArgumentNullException(nameof(parameters), $"CallNativeMethod: Called with null 'parameters' for method {method}"));
+ return -1;
+ }
+
// Possible null reference on parameters
- var marshalledParameters =
- parameters.Select(p => MarshalValue.Marshal(_smProcess, p))
- .Cast()
- .ToArray();
+ var marshalledParameters = new IMarshalledValue[parameters.Length];
+
+ for (var i = 0; i < parameters.Length; i++)
+ {
+ var p = parameters[i];
+ var dynMarshalled = MarshalValue.Marshal(_smProcess, p);
+
+ if (dynMarshalled is IMarshalledValue marshalled)
+ marshalledParameters[i] = marshalled;
+
+ else
+ {
+ OnException(new ArgumentException($"CallNativeMethod: Parameter n°{i} '{p}' could not be marshalled for method {method}", nameof(p)));
+ return -1;
+ }
+ }
try
{
diff --git a/src/Core/SuperMemoAssistant.Hooks.InjectLib/SMInject.Services.cs b/src/Core/SuperMemoAssistant.Hooks.InjectLib/SMInject.Services.cs
index fb8a693..bcdf752 100644
--- a/src/Core/SuperMemoAssistant.Hooks.InjectLib/SMInject.Services.cs
+++ b/src/Core/SuperMemoAssistant.Hooks.InjectLib/SMInject.Services.cs
@@ -75,31 +75,38 @@ private void DispatchMessages()
private void ProcessData(HookedFunction func,
object[] data)
{
- switch (func)
+ try
{
- case HookedFunction.CreateFile:
- SMA.OnFileCreate((string)data[0],
- (IntPtr)data[1]);
- break;
+ switch (func)
+ {
+ case HookedFunction.CreateFile:
+ SMA.OnFileCreate((string)data[0],
+ (IntPtr)data[1]);
+ break;
- case HookedFunction.SetFilePointer:
- SMA.OnFileSeek((IntPtr)data[0],
- (UInt32)data[1]);
- break;
+ case HookedFunction.SetFilePointer:
+ SMA.OnFileSeek((IntPtr)data[0],
+ (UInt32)data[1]);
+ break;
- case HookedFunction.WriteFile:
- var byteArr = (byte[])data[1];
+ case HookedFunction.WriteFile:
+ var byteArr = (byte[])data[1];
- SMA.OnFileWrite((IntPtr)data[0],
- byteArr,
- (UInt32)data[2]);
+ SMA.OnFileWrite((IntPtr)data[0],
+ byteArr,
+ (UInt32)data[2]);
- ArrayPool.Shared.Return(byteArr);
- break;
+ ArrayPool.Shared.Return(byteArr);
+ break;
- case HookedFunction.CloseHandle:
- SMA.OnFileClose((IntPtr)data[0]);
- break;
+ case HookedFunction.CloseHandle:
+ SMA.OnFileClose((IntPtr)data[0]);
+ break;
+ }
+ }
+ catch (Exception ex)
+ {
+ OnException(ex);
}
}
diff --git a/src/Core/SuperMemoAssistant.Hooks.InjectLib/SuperMemoAssistant.Hooks.InjectLib.csproj b/src/Core/SuperMemoAssistant.Hooks.InjectLib/SuperMemoAssistant.Hooks.InjectLib.csproj
index 0a874df..d678876 100644
--- a/src/Core/SuperMemoAssistant.Hooks.InjectLib/SuperMemoAssistant.Hooks.InjectLib.csproj
+++ b/src/Core/SuperMemoAssistant.Hooks.InjectLib/SuperMemoAssistant.Hooks.InjectLib.csproj
@@ -60,14 +60,14 @@
..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
-
- ..\..\..\packages\Sentry.1.2.0\lib\net461\Sentry.dll
+
+ ..\..\..\packages\Sentry.2.0.1\lib\net461\Sentry.dll
-
- ..\..\..\packages\Sentry.PlatformAbstractions.1.0.0\lib\net471\Sentry.PlatformAbstractions.dll
+
+ ..\..\..\packages\Sentry.PlatformAbstractions.1.1.0\lib\net471\Sentry.PlatformAbstractions.dll
-
- ..\..\..\packages\Sentry.Protocol.1.0.6\lib\net46\Sentry.Protocol.dll
+
+ ..\..\..\packages\Sentry.Protocol.2.0.0\lib\net46\Sentry.Protocol.dll
@@ -146,12 +146,12 @@
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
xcopy /h /i /d /c /k /r /y $(TargetPath) %25AppData%25\SuperMemoAssistant\
xcopy /h /i /d /c /k /r /y $(TargetDir)EasyHook32.dll %25AppData%25\SuperMemoAssistant\
xcopy /h /i /d /c /k /r /y $(TargetDir)EasyLoad32.dll %25AppData%25\SuperMemoAssistant\
-
+
\ No newline at end of file
diff --git a/src/Core/SuperMemoAssistant.Hooks.InjectLib/packages.config b/src/Core/SuperMemoAssistant.Hooks.InjectLib/packages.config
index 8ed73dc..cd56a12 100644
--- a/src/Core/SuperMemoAssistant.Hooks.InjectLib/packages.config
+++ b/src/Core/SuperMemoAssistant.Hooks.InjectLib/packages.config
@@ -2,11 +2,11 @@
-
+
-
-
-
+
+
+
diff --git a/src/Core/SuperMemoAssistant.Hooks.NativeLib/registercallwrapper.cpp b/src/Core/SuperMemoAssistant.Hooks.NativeLib/registercallwrapper.cpp
index a5b7d73..00fe29a 100644
--- a/src/Core/SuperMemoAssistant.Hooks.NativeLib/registercallwrapper.cpp
+++ b/src/Core/SuperMemoAssistant.Hooks.NativeLib/registercallwrapper.cpp
@@ -1,70 +1,3 @@
-#if false
-using namespace System;
-
-namespace SuperMemoAssistantHooksNativeLib {
- void __stdcall wndProcNativeWrapper();
-
- public ref class WndProcWrapper
- {
- public:
- WndProcWrapper() {}
-
- static WndProcWrapper^ Instance()
- {
- if (instance == nullptr)
- instance = gcnew WndProcWrapper();
-
- return instance;
- }
-
- void SetCallback(Action^ callback)
- {
- Callback = callback;
- }
-
- void WndProc(int smMain, int msg)
- {
- System::Diagnostics::Debugger::Launch();
- Callback(smMain, msg);
- }
-
- int GetWndProcNativeWrapperAddr()
- {
- return (int)(&wndProcNativeWrapper);
- }
-
- private:
- Action^ Callback;
- static WndProcWrapper^ instance;
-
- };
-
- void callManaged(int smMain, int msg)
- {
- return WndProcWrapper::Instance()->WndProc(smMain, msg);
- }
-
- void __stdcall wndProcNativeWrapper()
- {
- int smMain;
- int msg;
-
- _asm {
- mov smMain, eax
- mov msg, edx
- }
-
- callManaged(smMain, msg);
- /*
- _asm {
- mov eax, test
- }*/
- }
-}
-
-#endif
-//#if false
-
#pragma managed
using namespace System;
@@ -114,44 +47,4 @@ namespace SuperMemoAssistantHooksNativeLib {
/* WM_USER */ (msgId == 2345 && msgParam > 9000000))
callback(smMain, msgAddr, handled);
}
- /*
- public class WndProcWrapper
- {
- public:
- WndProcWrapper(void* callback)
- {
- Callback = static_cast(callback);
- }
-
- void WndProc(int smMain, int msg)
- {
- //System::Diagnostics::Debugger::Launch();
- Callback(smMain, msg);
- }
-
- int GetWndProcNativeWrapperAddr()
- {
- void (__stdcall WndProcWrapper::*pFunc)(void) = &(WndProcWrapper::wndProcNativeWrapper);
- return System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(pFunc).ToInt32();
- }
-
- private:
- static void __stdcall wndProcNativeWrapper()
- {
- int smMain;
- int msg;
-
- _asm {
- mov smMain, eax
- mov msg, edx
- }
-
- Callback(smMain, msg);
- }
-
- private:
- wndProcCallback Callback;
- };
- */
}
-//#endif
\ No newline at end of file
diff --git a/src/Core/SuperMemoAssistant.Interop.Shared/Sys/IO/NormalizedPath.cs b/src/Core/SuperMemoAssistant.Interop.Shared/Sys/IO/NormalizedPath.cs
index 3e62653..774c8a3 100644
--- a/src/Core/SuperMemoAssistant.Interop.Shared/Sys/IO/NormalizedPath.cs
+++ b/src/Core/SuperMemoAssistant.Interop.Shared/Sys/IO/NormalizedPath.cs
@@ -170,6 +170,10 @@ private NormalizedPath(Tuple providerAndPath,
/// The full path.
public string FullPath { get; }
+ /// Gets the full path.
+ /// The full path.
+ public string FullPathWin => FullPath.Replace('/', '\\');
+
/// Gets a value indicating whether this path is relative.
/// true if this path is relative; otherwise, false.
public bool IsRelative => !IsAbsolute;
diff --git a/src/Core/SuperMemoAssistant.Interop/Extensions/IEnumerableEx.cs b/src/Core/SuperMemoAssistant.Interop/Extensions/IEnumerableEx.cs
index 4622860..9d38536 100644
--- a/src/Core/SuperMemoAssistant.Interop/Extensions/IEnumerableEx.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Extensions/IEnumerableEx.cs
@@ -6,7 +6,7 @@
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
+// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
@@ -21,8 +21,7 @@
// DEALINGS IN THE SOFTWARE.
//
//
-// Created On: 2018/05/31 13:45
-// Modified On: 2018/12/13 13:04
+// Modified On: 2020/02/02 23:00
// Modified By: Alexis
#endregion
@@ -56,6 +55,15 @@ public static IEnumerable ForEach(this IEnumerable elements,
return elements;
}
+ public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector)
+ {
+ HashSet seenKeys = new HashSet();
+
+ foreach (TSource element in source)
+ if (seenKeys.Add(keySelector(element)))
+ yield return element;
+ }
+
#endregion
}
}
diff --git a/src/Core/SuperMemoAssistant.Interop/Extensions/RemotingServicesEx.cs b/src/Core/SuperMemoAssistant.Interop/Extensions/RemotingServicesEx.cs
index b0d8542..919fb70 100644
--- a/src/Core/SuperMemoAssistant.Interop/Extensions/RemotingServicesEx.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Extensions/RemotingServicesEx.cs
@@ -152,6 +152,10 @@ public static void InvokeRemote(
LogTo.Warning(remoteEx, $"{eventName}: Remoting exception while notifying remote service - forcing unsubscribe");
unsubscribeDelegate?.Invoke(handler);
}
+ catch (NullReferenceException)
+ {
+ LogTo.Warning($"Null handler called for event {eventName}.");
+ }
catch (Exception ex)
{
LogTo.Error(ex, $"{eventName}: Exception while notifying remote service");
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SMConst.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SMConst.cs
index 60ea79b..1fc1be1 100644
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SMConst.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Interop/SMConst.cs
@@ -41,8 +41,6 @@ public static class SMConst
{
#region Constants & Statics
- public const string BinPath = "C:\\SuperMemo\\sm17.exe";
-
public const string AppName = "SuperMemoAssistant";
#endregion
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Builders/LayoutBuilder.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Builders/LayoutBuilder.cs
deleted file mode 100644
index 5983cdd..0000000
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Builders/LayoutBuilder.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-#region License & Metadata
-
-// The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
-//
-// Created On: 2019/01/16 14:54
-// Modified On: 2019/01/16 17:28
-// Modified By: Alexis
-
-#endregion
-
-
-
-
-using System.Drawing;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Contents;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Grid;
-
-// ReSharper disable UnusedMember.Global
-// ReSharper disable UnassignedGetOnlyAutoProperty
-
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Builders
-{
- public static class LayoutBuilder
- {
- #region Constants & Statics
-
- private const string ComponentsSkeleton = @"ComponentNo={0}
-{1}";
- private static readonly Rectangle CorsFull = new Rectangle(100,
- 100,
- 9780,
- 9600);
-
- #endregion
-
-
-
-
- #region Methods
-
- public static LayoutBase Stack(bool orientation,
- ContentTypeFlag acceptedContent,
- Rectangle? rootCors = null)
- {
- return null;
- }
-
- public static LayoutGrid Grid(ContentTypeFlag acceptedContent,
- Rectangle? rootCors = null)
- {
- return new LayoutGrid(acceptedContent,
- rootCors ?? CorsFull);
- }
-
- public static LayoutBase Auto(Rectangle? rootCors = null)
- {
- return null;
- }
-
- #endregion
- }
-}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.GridContent.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.GridContent.cs
deleted file mode 100644
index d3a9d1e..0000000
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.GridContent.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-#region License & Metadata
-
-// The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
-//
-// Created On: 2019/01/17 14:35
-// Modified On: 2019/01/17 20:48
-// Modified By: Alexis
-
-#endregion
-
-
-
-
-using System;
-using System.Drawing;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Contents;
-using SuperMemoAssistant.Sys;
-
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Grid
-{
- public class GridContent : LayoutBase
- {
- #region Constructors
-
- public GridContent(Index2D idx,
- GridSize widthDefinition,
- GridSize heightDefinition)
- : base(ContentTypeFlag.All)
- {
- Index = idx;
- WidthDef = widthDefinition;
- HeightDef = heightDefinition;
- }
-
- public GridContent(ContentBase content,
- Index2D idx,
- GridSize widthDefinition,
- GridSize heightDefinition)
- : this(idx, widthDefinition, heightDefinition)
- {
- Content = content;
-
- MinSize = ComputeMinSize();
- }
-
- public GridContent(LayoutBase container,
- Index2D idx,
- GridSize widthDefinition,
- GridSize heightDefinition)
- : this(idx, widthDefinition, heightDefinition)
- {
- Container = container;
-
- MinSize = ComputeMinSize();
- }
-
- #endregion
-
-
-
-
- #region Properties & Fields - Public
-
- public Index2D Index { get; }
- public GridSize WidthDef { get; }
- public GridSize HeightDef { get; }
- public bool HasSize => MinSize.IsEmpty == false;
-
- public LayoutBase Container { get; }
- public ContentBase Content { get; }
- public bool IsContent => Content != null;
-
- #endregion
-
-
-
-
- #region Properties Impl - Public
-
- public override Size MinSize { get; }
-
- #endregion
-
-
-
-
- #region Methods Impl
-
- ///
- public override void InitializeLayout() { }
-
- ///
- public override void CalculateLayout(Rectangle cors) { }
-
- #endregion
-
-
-
-
- #region Methods
-
- private Size ComputeMinSize()
- {
- int width = IsContent
- ? Content.MinSize.Width
- : 0;
- int height = IsContent
- ? Content.MinSize.Height
- : 0;
-
- width = Math.Max(width, WidthDef);
- height = Math.Max(height, HeightDef);
-
- return new Size(width,
- height);
- }
-
- #endregion
- }
-}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.GridSize.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.GridSize.cs
deleted file mode 100644
index 06b488d..0000000
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.GridSize.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-#region License & Metadata
-
-// The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
-//
-// Created On: 2019/01/16 15:36
-// Modified On: 2019/01/16 21:50
-// Modified By: Alexis
-
-#endregion
-
-
-
-
-using System;
-
-// ReSharper disable InconsistentNaming
-
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Grid
-{
- public class GridSize
- {
-
- #region Constructors
-
- public GridSize(int size,
- int span = 1)
- {
- if (span < 1)
- throw new ArgumentException($"Span must be at least 1, value is {span}");
-
- Size = size;
- Span = span;
- }
-
- #endregion
-
-
-
-
- #region Properties & Fields - Public
-
- public int Size { get; }
- public int Span { get; }
-
- #endregion
-
-
-
-
- #region Methods Impl
-
- ///
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null,
- obj))
- return false;
- if (ReferenceEquals(this,
- obj))
- return true;
- if (obj.GetType() != GetType())
- return false;
-
- return Equals((GridSize)obj);
- }
-
- ///
- public override int GetHashCode()
- {
- unchecked
- {
- return (Size * 397) ^ Span;
- }
- }
-
- #endregion
-
-
-
-
- #region Methods
-
- protected bool Equals(GridSize other)
- {
- return Size == other.Size && Span == other.Span;
- }
-
- public static bool operator ==(GridSize left,
- GridSize right)
- {
- return Equals(left,
- right);
- }
-
- public static bool operator !=(GridSize left,
- GridSize right)
- {
- return !Equals(left,
- right);
- }
-
- public static implicit operator int(GridSize size) => size.Size;
-
- public static implicit operator GridSize(int size) => new GridSize(size);
-
- #endregion
- }
-}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.Layout.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.Layout.cs
deleted file mode 100644
index 4a2ad73..0000000
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.Layout.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-#region License & Metadata
-
-// The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
-//
-// Created On: 2019/01/17 14:35
-// Modified On: 2019/01/17 20:54
-// Modified By: Alexis
-
-#endregion
-
-
-
-
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using SuperMemoAssistant.Extensions;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Contents;
-using SuperMemoAssistant.Sys;
-
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Grid
-{
- public partial class LayoutGrid
- {
- #region Methods Impl
-
- public override void InitializeLayout() { }
-
- public override void CalculateLayout(Rectangle cors)
- {
- RowsData.ForEach(d => d.Reset());
- ColumnsData.ForEach(d => d.Reset());
-
- HashSet visitedContent = new HashSet();
-
- for (int i = 0; i < RowCount; i++)
- for (int j = 0; j < ColumnCount; j++)
- {
- var content = Grid[i, j];
-
- // If no content, create an Auto container
- if (content == null)
- {
- AddAuto(AcceptedContents,
- (i, j),
- 1, 1);
- content = Grid[i, j];
-
- if (content == null)
- throw new InvalidOperationException("Content should not be null.");
- }
-
- var visited = visitedContent.Contains(content);
- var rowSize = Rows[i];
- var columnSize = Columns[j];
-
- // Compute new free size for row + column & Increment counters
- if (columnSize.IsFill)
- {
- if (visited == false)
- RowsData[i].UsedSize += content.MinSize.Width;
- }
- else
- {
- RowsData[i].FillBlockCount++;
- }
-
- if (rowSize.IsFill)
- {
- if (visited == false)
- ColumnsData[j].UsedSize += content.MinSize.Height;
- }
- else
- {
- ColumnsData[j].FillBlockCount++;
- }
-
- ColumnsData[j].BlockCount++;
- RowsData[i].BlockCount++;
-
- visitedContent.Add(content);
- }
- }
-
- #endregion
-
-
-
-
- #region Methods
-
- private void InitializeGrid()
- {
- Grid = new GridContent[RowCount, ColumnCount];
- RowsData = Enumerable.Repeat(new VectorData(), RowCount).ToArray();
- ColumnsData = Enumerable.Repeat(new VectorData(), ColumnCount).ToArray();
- }
-
- private void UpdateGrid(GridContent content,
- Index2D idx)
- {
- var widthDef = content.WidthDef;
- var heightDef = content.HeightDef;
-
- // Validate Spans
- if (idx.X + widthDef.Span > ColumnCount)
- throw new ArgumentException("Column span is out of bound");
-
- if (idx.Y + heightDef.Span > RowCount)
- throw new ArgumentException("Row span is out of bound");
-
- // Insert content
- for (int i = idx.X; i < idx.X + widthDef.Span; i++)
- for (int j = idx.Y; j < idx.Y + heightDef.Span; j++)
- {
- // TODO: Implement auto for containers
- if (content.IsContent == false &&
- (Columns[i].IsAuto || Rows[j].IsAuto))
- throw new NotImplementedException("Auto not implemented for containers");
-
- Grid[i, j] = content;
- }
- }
-
- public string Build(List contents)
- {
- if (Root)
- {
- // TODO
- }
- }
-
- protected void GetCors(ContentBase content,
- int idxComp,
- int totalCompCount,
- out int compLeft,
- out int compTop,
- out int compWidth,
- out int compHeight)
- {
- if (content.Cors != null)
- {
- compLeft = content.Cors.Value.Left;
- compTop = content.Cors.Value.Top;
- compWidth = content.Cors.Value.Width;
- compHeight = content.Cors.Value.Height;
- return;
- }
-
- if (totalCompCount == 1)
- {
- compLeft = Left;
- compTop = Top;
- compWidth = Width;
- compHeight = Height;
- return;
- }
-
- if (totalCompCount == 2)
- {
- int comp2Height = (int)(totalHeight / 2.0);
-
- compLeft = left;
- compTop = top + (idxComp == 0 ? 0 : comp2Height);
- compWidth = totalWidth;
- compHeight = comp2Height;
- return;
- }
-
- double nbRowAndCol = Math.Floor(Math.Log(totalCompCount,
- 2));
- int compRow = (int)Math.Floor(idxComp / nbRowAndCol);
- int compCol = idxComp % (int)nbRowAndCol;
-
- compWidth = (int)(totalWidth / nbRowAndCol);
- compHeight = (int)(totalHeight / nbRowAndCol);
-
- compLeft = left + compCol * compWidth;
- compTop = top + compRow * compHeight;
- }
-
- #endregion
- }
-}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.VectorSize.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.VectorSize.cs
deleted file mode 100644
index aa06701..0000000
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.VectorSize.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-#region License & Metadata
-
-// The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
-//
-// Created On: 2019/01/17 15:40
-// Modified On: 2019/01/17 20:42
-// Modified By: Alexis
-
-#endregion
-
-
-
-
-// ReSharper disable InconsistentNaming
-
-using System;
-using System.Text.RegularExpressions;
-using JetBrains.Annotations;
-
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Grid
-{
- public class VectorSize
- {
- #region Constants & Statics
-
- public const string StrAuto = "auto";
- public static readonly Regex RE_Fill = new Regex("([\\d]?)\\*");
-
-
- public const int Auto = 0;
- public const string Fill1x = "*";
- public const string Fill2x = "2*";
- public const string Fill3x = "3*";
- public const string Fill5x = "5*";
- public const string Fill10x = "10*";
-
- #endregion
-
-
-
-
- #region Constructors
-
- public VectorSize(int size)
- {
- Size = size;
- }
-
- public VectorSize([NotNull] string sizeStr)
- {
- if (sizeStr is StrAuto)
- {
- Size = Auto;
- return;
- }
-
- var match = RE_Fill.Match(sizeStr);
-
- if (match.Success)
- {
- int n = match.Groups.Count == 2 && string.IsNullOrWhiteSpace(match.Groups[1].Value) == false
- ? int.Parse(match.Groups[1].Value)
- : 1;
- Size = -n;
-
- return;
- }
-
- if (int.TryParse(sizeStr, out int size))
- {
- Size = size;
- return;
- }
-
- throw new ArgumentException($"Invalid size {sizeStr}");
- }
-
- #endregion
-
-
-
-
- #region Properties & Fields - Public
-
- public int Size { get; }
-
- public bool IsFill => Size < 0;
- public bool IsAuto => Size == 0;
-
- #endregion
-
-
-
-
- #region Methods Impl
-
- ///
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null,
- obj))
- return false;
- if (ReferenceEquals(this,
- obj))
- return true;
- if (obj.GetType() != GetType())
- return false;
-
- return Equals((VectorSize)obj);
- }
-
- ///
- public override int GetHashCode()
- {
- return Size;
- }
-
- #endregion
-
-
-
-
- #region Methods
-
- protected bool Equals(VectorSize other)
- {
- return Size == other.Size;
- }
-
- public static bool operator ==(VectorSize left,
- VectorSize right)
- {
- return Equals(left,
- right);
- }
-
- public static bool operator !=(VectorSize left,
- VectorSize right)
- {
- return !Equals(left,
- right);
- }
-
- public static implicit operator int(VectorSize size) => size.Size;
-
- public static implicit operator VectorSize(int size) => new VectorSize(size);
-
- public static implicit operator VectorSize(string sizeStr) => new VectorSize(sizeStr);
-
- #endregion
- }
-}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.cs
deleted file mode 100644
index ce8f09b..0000000
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.cs
+++ /dev/null
@@ -1,239 +0,0 @@
-#region License & Metadata
-
-// The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
-//
-// Created On: 2019/01/17 14:35
-// Modified On: 2019/01/17 18:22
-// Modified By: Alexis
-
-#endregion
-
-
-
-
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Contents;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Auto;
-using SuperMemoAssistant.Sys;
-
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Grid
-{
- public partial class LayoutGrid : LayoutBase
- {
- #region Properties & Fields - Non-Public
-
- //protected Dictionary AssignedIndexBlockMap { get; } = new Dictionary();
-
- protected HashSet<(ContentBase content, bool allowPlacementInChild)> UnassignedContents { get; } = new HashSet<(ContentBase, bool)>();
-
- protected GridContent[,] Grid { get; set; }
- protected VectorData[] RowsData { get; set; }
- protected VectorData[] ColumnsData { get; set; }
-
- protected List Columns { get; } = new List();
- protected List Rows { get; } = new List();
-
- protected int ColumnCount => Columns.Count;
- protected int RowCount => Rows.Count;
-
-
- protected GridContent this[Index2D idx] => Grid[idx.X, idx.Y];
-
- #endregion
-
-
-
-
- #region Constructors
-
- public LayoutGrid(ContentTypeFlag acceptedContents,
- Action buildMethod = null)
- : this(acceptedContents,
- new VectorSize[] { "*" },
- new VectorSize[] { "*" },
- buildMethod) { }
-
- public LayoutGrid(ContentTypeFlag acceptedContents,
- VectorSize[] rows,
- VectorSize[] columns,
- Action buildMethod = null)
- : base(acceptedContents)
- {
- if (rows == null)
- throw new NullReferenceException(nameof(rows));
-
- if (columns == null)
- throw new NullReferenceException(nameof(columns));
-
- Rows.AddRange(rows);
- Columns.AddRange(columns);
-
- InitializeGrid();
-
- buildMethod?.Invoke(this);
- }
-
- #endregion
-
-
-
-
- #region Properties Impl - Public
-
- public override Size MinSize { get; }
-
- #endregion
-
-
-
-
- #region Methods
-
- public LayoutGrid AddContent(ContentBase content,
- bool allowPlacementInChild = true)
- {
- UnassignedContents.Add((content, allowPlacementInChild));
-
- return this;
- }
-
- public LayoutGrid AddContent(ContentBase content,
- int row,
- int column,
- int rowSpan = 1,
- int columnSpan = 1)
- {
- return AddContent(content, (row, column));
- }
-
- public LayoutGrid AddContent(ContentBase content,
- Index2D idx,
- int rowSpan = 1,
- int columnSpan = 1)
- {
- // RebaseIndex
- ThrowIfInvalid(idx);
-
- var gridContent = new GridContent(
- content,
- idx,
- new GridSize(content.Size.Width, columnSpan),
- new GridSize(content.Size.Height, rowSpan));
-
- UpdateGrid(gridContent, idx);
-
- return this;
- }
-
- public LayoutGrid AddGrid(ContentTypeFlag acceptedContents,
- int row,
- int column,
- int rowSpan,
- int columnSpan,
- VectorSize[] rows,
- VectorSize[] columns,
- Action buildMethod = null)
- {
- return AddGrid(acceptedContents,
- (row, column),
- rowSpan, columnSpan,
- rows, columns,
- buildMethod);
- }
-
- public LayoutGrid AddGrid(ContentTypeFlag acceptedContents,
- Index2D idx,
- int rowSpan,
- int columnSpan,
- VectorSize[] rows,
- VectorSize[] columns,
- Action buildMethod = null)
- {
- ThrowIfInvalid(idx);
-
- var container = new LayoutGrid(
- acceptedContents,
- rows, columns,
- buildMethod);
- var gridContent = new GridContent(
- container,
- idx,
- new GridSize(0, columnSpan),
- new GridSize(0, rowSpan));
-
- UpdateGrid(gridContent, idx);
-
- return this;
- }
-
- public LayoutGrid AddAuto(ContentTypeFlag acceptedContents,
- int row,
- int column,
- int rowSpan,
- int columnSpan,
- Action buildMethod = null)
- {
- return AddAuto(acceptedContents,
- (row, column),
- rowSpan, columnSpan,
- buildMethod);
- }
-
- public LayoutGrid AddAuto(ContentTypeFlag acceptedContents,
- Index2D idx,
- int rowSpan,
- int columnSpan,
- Action buildMethod = null)
- {
- ThrowIfInvalid(idx);
-
- var container = new LayoutAuto(
- acceptedContents,
- buildMethod);
- var gridContent = new GridContent(
- container,
- idx,
- new GridSize(0, columnSpan),
- new GridSize(0, rowSpan));
-
- UpdateGrid(gridContent, idx);
-
- return this;
- }
-
- private void ThrowIfInvalid(Index2D idx)
- {
- if (idx.X >= Columns.Count)
- throw new ArgumentException($"Invalid column index {idx.X}, of total count {Columns.Count}");
-
- if (idx.Y >= Rows.Count)
- throw new ArgumentException($"Invalid row index {idx.Y}, of total count {Rows.Count}");
-
- if (this[idx] != null)
- throw new ArgumentException($"Block {idx} isn't empty.");
- }
-
- #endregion
- }
-}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/LayoutBase.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/LayoutBase.cs
deleted file mode 100644
index 5c94461..0000000
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/LayoutBase.cs
+++ /dev/null
@@ -1,373 +0,0 @@
-#region License & Metadata
-
-// The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
-//
-// Created On: 2019/01/16 14:54
-// Modified On: 2019/01/16 15:32
-// Modified By: Alexis
-
-#endregion
-
-
-
-
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-using Anotar.Serilog;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Components;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Components.Builders;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Contents;
-using SuperMemoAssistant.Services;
-
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy
-{
- public abstract class LayoutBase
- {
-
- #region Constructors
-
- protected LayoutBase(ContentTypeFlag acceptedContents)
- {
- AcceptedContents = acceptedContents;
- }
-
-
- #endregion
-
-
-
-
- #region Properties & Fields - Public
-
- public Rectangle Bounds { get; set; }
- public int Left => Bounds.Left;
- public int Right => Bounds.Right;
- public int Top => Bounds.Top;
- public int Bottom => Bounds.Bottom;
- public int Width => Bounds.Width;
- public int Height => Bounds.Height;
- public abstract Size MinSize { get; }
-
- public ContentTypeFlag AcceptedContents { get; set; }
-
- #endregion
-
-
-
-
- public abstract void InitializeLayout();
- public abstract void CalculateLayout(Rectangle cors);
-
- public string Build(List contents)
- {
- var components = new List();
-
- var corsCount = Contents.Count(c => c.Cors != null);
-
- if (corsCount > 0 && corsCount != Contents.Count())
- throw new ArgumentException("CORS must be set for all contents, or none.");
-
- var txtContents = GetTextContents();
- var imgContents = GetImageContents();
- var soundContents = GetSoundContents();
-
- switch (ElemBuilder.ContentType)
- {
- case ContentTypeFlag.Html:
- case ContentTypeFlag.RawText:
- if (imgContents.Any())
- throw new InvalidCastException("ElementBuilder ContentTypeFlag.Text contains non-text IContent");
-
- if (txtContents.Any() == false)
- throw new InvalidCastException("ElementBuilder ContentTypeFlag.Text does not contain any text IContent");
-
- BuildTextComponents(0,
- txtContents.Count,
- CorsFull.Left,
- CorsFull.Top,
- CorsFull.Right,
- CorsFull.Bottom,
- txtContents,
- components);
- break;
-
- case ContentTypeFlag.Image:
- if (txtContents.Any())
- throw new InvalidCastException("ElementBuilder ContentTypeFlag.Image contains non-image IContent");
-
- if (imgContents.Any() == false)
- throw new InvalidCastException("ElementBuilder ContentTypeFlag.Image does not contain any image IContent");
-
- BuildImageComponents(0,
- imgContents.Count,
- CorsFull.Left,
- CorsFull.Top,
- CorsFull.Right,
- CorsFull.Bottom,
- imgContents,
- components);
- break;
-
- case ContentTypeFlag.Sound:
- if (txtContents.Any())
- throw new InvalidCastException("ElementBuilder ContentTypeFlag.Image contains non-image IContent");
-
- if (imgContents.Any() == false)
- throw new InvalidCastException("ElementBuilder ContentTypeFlag.Image does not contain any image IContent");
-
- BuildImageComponents(0,
- imgContents.Count,
- CorsFull.Left,
- CorsFull.Top,
- CorsFull.Right,
- CorsFull.Bottom,
- imgContents,
- components);
- break;
-
- case ContentTypeFlag.ImageAndRawText:
- case ContentTypeFlag.ImageAndHtml:
- if (txtContents.Any() == false)
- throw new InvalidCastException("ElementBuilder ContentTypeFlag.ImageAndText does not contain any text IContent");
-
- if (imgContents.Any() == false)
- throw new InvalidCastException("ElementBuilder ContentTypeFlag.ImageAndText does not contain any image IContent");
-
- BuildTextComponents(0,
- txtContents.Count,
- CorsVSplitLeft.Left,
- CorsVSplitLeft.Top,
- CorsVSplitLeft.Right,
- CorsVSplitLeft.Bottom,
- txtContents,
- components);
-
- BuildImageComponents(components.Count,
- imgContents.Count,
- CorsVSplitRight.Left,
- CorsVSplitRight.Top,
- CorsVSplitRight.Right,
- CorsVSplitRight.Bottom,
- imgContents,
- components);
- break;
-
- default:
- throw new NotImplementedException();
- }
-
- var compsText = components.Select(c => c.ToString())
- .ToList();
-
- return string.Format(ComponentsSkeleton,
- compsText.Count,
- string.Join("\n",
- compsText));
- }
-
-
-
-
-
- #region Methods
-
- protected void BuildTextComponents(int startingIdx,
- int totalCompCount,
- int left,
- int top,
- int right,
- int bottom,
- IEnumerable contents,
- List outComps)
- {
- int idx = 0;
-
- foreach (var content in contents)
- {
- GetCors(content,
- idx,
- totalCompCount,
- left,
- top,
- right,
- bottom,
- out int compLeft,
- out int compTop,
- out int compWidth,
- out int compHeight);
-
- var comp = new ComponentHtmlBuilder(startingIdx + idx++,
- content.Text,
- compLeft,
- compTop,
- compWidth,
- compHeight,
- content.DisplayAt);
- outComps.Add(comp);
- }
- }
-
- protected void BuildImageComponents(int startingIdx,
- int totalCompCount,
- int left,
- int top,
- int right,
- int bottom,
- IEnumerable contents,
- List outComps)
- {
- int idx = 0;
-
- foreach (var content in contents)
- {
- var img = Svc.SMA.Registry.Image[content.RegistryId];
-
- if (img == null) // || imgMember.Empty) // TODO: Why is Empty always true ?
- {
- LogTo.Error($"Error while building ImageComponent: IImage {content.RegistryId} is null. Skipping");
- continue;
- }
-
- var filePath = img.GetFilePath();
-
- if (File.Exists(filePath) == false)
- {
- LogTo.Error("Error while building ImageComponent: IImage {0} file {1} does not exist. Skipping",
- img,
- filePath);
- continue;
- }
-
- GetCors(content,
- idx,
- totalCompCount,
- left,
- top,
- right,
- bottom,
- out int compLeft,
- out int compTop,
- out int compWidth,
- out int compHeight);
-
- var comp = new ComponentImageBuilder(startingIdx + idx++,
- img,
- compLeft,
- compTop,
- compWidth,
- compHeight,
- content.DisplayAt)
- {
- Stretch = content.StretchType
- };
-
-
- outComps.Add(comp);
- }
- }
-
- protected void BuildSoundComponents(int startingIdx,
- int totalCompCount,
- int left,
- int top,
- int right,
- int bottom,
- IEnumerable contents,
- List outComps)
- {
- int idx = 0;
-
- foreach (var content in contents)
- {
- var sound = Svc.SMA.Registry.Sound[content.RegistryId];
-
- if (sound == null) // || imgMember.Empty) // TODO: Why is Empty always true ?
- {
- LogTo.Error($"Error while building SoundComponent: ISound {content.RegistryId} is null. Skipping");
- continue;
- }
-
- var filePath = sound.GetFilePath();
-
- if (File.Exists(filePath) == false)
- {
- LogTo.Error("Error while building SoundComponent: ISound {0} file {1} does not exist. Skipping",
- sound,
- filePath);
- continue;
- }
-
- GetCors(content,
- idx,
- totalCompCount,
- left,
- top,
- right,
- bottom,
- out int compLeft,
- out int compTop,
- out int compWidth,
- out int compHeight);
-
- var comp = new ComponentSoundBuilder(startingIdx + idx++,
- sound,
- content.Text,
- compLeft,
- compTop,
- compWidth,
- compHeight,
- content.PanelType,
- content.PlayAt,
- content.DisplayAt);
-
-
- outComps.Add(comp);
- }
- }
-
- protected List GetTextContents()
- {
- return Contents.Where(c => (c.ContentType & ContentTypeFlag.Text) != ContentTypeFlag.None)
- .Cast()
- .ToList();
- }
-
- protected List GetImageContents()
- {
- return Contents.Where(c => c.ContentType == ContentTypeFlag.Image)
- .Cast()
- .ToList();
- }
-
- protected List GetSoundContents()
- {
- return Contents.Where(c => c.ContentType == ContentTypeFlag.Sound)
- .Cast()
- .ToList();
- }
-
- #endregion
- }
-}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/UI/IWdw.cs b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/UI/IWdw.cs
index ca3d8b3..f02c363 100644
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/UI/IWdw.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/UI/IWdw.cs
@@ -6,7 +6,7 @@
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
+// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
@@ -21,8 +21,7 @@
// DEALINGS IN THE SOFTWARE.
//
//
-// Created On: 2018/07/27 12:55
-// Modified On: 2019/01/19 04:55
+// Modified On: 2020/02/03 18:52
// Modified By: Alexis
#endregion
@@ -36,7 +35,8 @@ namespace SuperMemoAssistant.Interop.SuperMemo.UI
{
public interface IWdw
{
- IntPtr Handle { get; }
+ IntPtr Handle { get; }
+ bool IsAvailable { get; }
event Action OnAvailable;
}
diff --git a/src/Core/SuperMemoAssistant.Interop/Properties/AssemblyInfo.cs b/src/Core/SuperMemoAssistant.Interop/Properties/AssemblyInfo.cs
index ab130c3..6e637f6 100644
--- a/src/Core/SuperMemoAssistant.Interop/Properties/AssemblyInfo.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Properties/AssemblyInfo.cs
@@ -31,7 +31,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.4")]
-[assembly: AssemblyFileVersion("2.0.2.4")]
+[assembly: AssemblyVersion("2.0.2.17")]
+[assembly: AssemblyFileVersion("2.0.2.17")]
[assembly: AssemblyInformationalVersion("2.0.2")]
\ No newline at end of file
diff --git a/src/Core/SuperMemoAssistant.Interop/Services/IO/Keyboard/KeyboardHook.cs b/src/Core/SuperMemoAssistant.Interop/Services/IO/Keyboard/KeyboardHook.cs
index b521a93..52bf491 100644
--- a/src/Core/SuperMemoAssistant.Interop/Services/IO/Keyboard/KeyboardHook.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Services/IO/Keyboard/KeyboardHook.cs
@@ -258,7 +258,11 @@ private IntPtr LowLevelKeyboardProc(int nCode,
private void OnSMAAvailable(Interop.SuperMemo.ISuperMemoAssistant sma)
{
- sma.SM.UI.ElementWdw.OnAvailable += new ActionProxy(OnElementWindowAvailable);
+ if (sma.SM.UI.ElementWdw.IsAvailable)
+ OnElementWindowAvailable();
+
+ else
+ sma.SM.UI.ElementWdw.OnAvailable += new ActionProxy(OnElementWindowAvailable);
}
private void OnElementWindowAvailable()
diff --git a/src/Core/SuperMemoAssistant.Interop/SuperMemoAssistant.Interop.csproj b/src/Core/SuperMemoAssistant.Interop/SuperMemoAssistant.Interop.csproj
index 66a9b77..9231b9c 100644
--- a/src/Core/SuperMemoAssistant.Interop/SuperMemoAssistant.Interop.csproj
+++ b/src/Core/SuperMemoAssistant.Interop/SuperMemoAssistant.Interop.csproj
@@ -1,6 +1,6 @@
-
+
@@ -88,8 +88,8 @@
-
- ..\..\..\packages\PropertyChanged.Fody.3.2.4\lib\net40\PropertyChanged.dll
+
+ ..\..\..\packages\PropertyChanged.Fody.3.2.5\lib\net40\PropertyChanged.dll
..\..\..\packages\Serilog.2.9.0\lib\net46\Serilog.dll
@@ -120,6 +120,7 @@
..\..\..\packages\System.Collections.Immutable.1.7.0\lib\netstandard2.0\System.Collections.Immutable.dll
+
@@ -209,6 +210,7 @@
+
@@ -316,6 +318,9 @@
+
+
+
@@ -360,8 +365,6 @@
-
-
@@ -372,8 +375,8 @@
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
+
+
-
+
\ No newline at end of file
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Auto/LayoutAuto.cs b/src/Core/SuperMemoAssistant.Interop/Sys/Net/UriEx.cs
similarity index 54%
rename from src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Auto/LayoutAuto.cs
rename to src/Core/SuperMemoAssistant.Interop/Sys/Net/UriEx.cs
index 80dd0f5..2e5bc63 100644
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Auto/LayoutAuto.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Sys/Net/UriEx.cs
@@ -6,7 +6,7 @@
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
+// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
@@ -21,8 +21,7 @@
// DEALINGS IN THE SOFTWARE.
//
//
-// Created On: 2019/01/17 14:35
-// Modified On: 2019/01/17 14:35
+// Modified On: 2020/02/08 15:15
// Modified By: Alexis
#endregion
@@ -30,44 +29,28 @@
-using System;
-using System.Drawing;
-using SuperMemoAssistant.Interop.SuperMemo.Content.Contents;
-
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Auto
+namespace SuperMemoAssistant.Sys.Net
{
- public partial class LayoutAuto : LayoutBase
+ public static class UriEx
{
- #region Constructors
-
- public LayoutAuto(ContentTypeFlag acceptedContents,
- Action buildMethod) : base(acceptedContents) { }
-
- #endregion
-
-
-
-
- #region Properties Impl - Public
-
- public override Size MinSize { get; }
-
- #endregion
-
-
-
-
- #region Methods Impl
-
- public override void InitializeLayout()
- {
- throw new NotImplementedException();
- }
-
- public override void CalculateLayout(Rectangle cors)
- {
- throw new NotImplementedException();
- }
+ #region Constants & Statics
+
+ public const string UriSchemeHttp = "http";
+ public const string UriSchemeHttps = "https";
+ public const string UriSchemeWs = "ws";
+ public const string UriSchemeWss = "wss";
+ public const string UriSchemeFtp = "ftp";
+ public const string UriSchemeFile = "file";
+ public const string UriSchemeGopher = "gopher";
+ public const string UriSchemeNntp = "nntp";
+ public const string UriSchemeNews = "news";
+ public const string UriSchemeMailTo = "mailto";
+ public const string UriSchemeUuid = "uuid";
+ public const string UriSchemeTelnet = "telnet";
+ public const string UriSchemeLdap = "ldap";
+ public const string UriSchemeNetTcp = "net.tcp";
+ public const string UriSchemeNetPipe = "net.pipe";
+ public const string UriSchemeVsMacros = "vsmacros";
#endregion
}
diff --git a/src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearch.cs b/src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearch.cs
new file mode 100644
index 0000000..2bf9c60
--- /dev/null
+++ b/src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearch.cs
@@ -0,0 +1,201 @@
+#region License & Metadata
+
+// The MIT License (MIT)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//
+// Modified On: 2020/02/02 23:02
+// Modified By: Alexis
+
+#endregion
+
+
+
+
+using System;
+using System.Collections.Generic;
+using System.Data.OleDb;
+using System.Linq;
+using System.Threading.Tasks;
+using SuperMemoAssistant.Extensions;
+
+namespace SuperMemoAssistant.Sys.Windows.Search
+{
+ ///
+ /// https://github.com/shellscape/Lumen/blob/master/Application/Search/WindowsSearchProvider.cs
+ ///
+ public class WindowsSearch
+ {
+ #region Constants & Statics
+
+ // Shared connection used for any search index queries
+
+ private readonly OleDbConnection _connection;
+
+ /// Indicates if Winders Desktop Search is installed and enabled.
+ public bool IsAvailable => _connection != null;
+
+ #endregion
+
+
+
+
+ public static WindowsSearch Instance { get; } = new WindowsSearch();
+
+
+
+
+ #region Constructors
+
+ protected WindowsSearch()
+ {
+ try
+ {
+ _connection = new OleDbConnection("Provider=Search.CollatorDSO;Extended Properties='Application=Windows';");
+ _connection.Open();
+ }
+ catch
+ {
+ // fails if desktop search is disabled or not installed
+ _connection = null;
+ }
+ }
+
+ #endregion
+
+
+
+
+ #region Methods
+
+ public async Task> Search(
+ string term,
+ WindowsSearchKind kind = WindowsSearchKind.All,
+ int limit = 1000)
+ {
+ var list = new List();
+
+ // prevent hidden (0x2) and system (0x4) files
+ var sql = @$"select top {limit}
+ System.ItemNameDisplay, System.ItemPathDisplay, System.Kind, System.Search.Rank, System.FileAttributes
+ from systemindex
+ where CONTAINS(""System.ItemNameDisplay"", '""*{term.Trim()}*""')";
+
+ if (kind != WindowsSearchKind.All)
+ sql += $"and System.Kind = '{kind.ToString().ToLower()}'";
+
+ sql += @"and System.FileAttributes <> ALL BITWISE 0x4 and System.FileAttributes <> ALL BITWISE 0x2
+ order by System.Search.Rank";
+
+ using (OleDbCommand command = new OleDbCommand())
+ {
+ command.Connection = _connection;
+ command.CommandText = sql;
+
+ using (var reader = await command.ExecuteReaderAsync())
+ while (await reader.ReadAsync())
+ {
+ var result = new WindowsSearchResult()
+ {
+ FileName = reader["System.ItemNameDisplay"].ToString(),
+ FilePath = reader["System.ItemPathDisplay"].ToString(),
+ Rank = (int)reader["System.Search.Rank"]
+ };
+
+ if (reader["System.Kind"] is string[] kinds && kinds.Length >= 1)
+ foreach (var k in reader["System.Kind"] as string[])
+ result.Kind |= (WindowsSearchKind)Enum.Parse(typeof(WindowsSearchKind), k, true);
+
+ else
+ result.Kind = WindowsSearchKind.File;
+
+ list.Add(result);
+ }
+ }
+
+ var results = list.DistinctBy(p => p.FileName).ToList();
+
+ return results;
+ }
+
+ ///
+ /// Returns values from the search index for the given filename based on the supplied
+ /// list of columns/properties
+ ///
+ ///
+ /// Comma-separated list of columns/properties
+ /// (http://msdn2.microsoft.com/en-us/library/ms788673.aspx)
+ ///
+ /// Filename about which to retrieve data
+ /// Key/value pairs for all requested columns/properties
+ ///
+ public Dictionary GetProperties(string columns, string filename)
+ {
+ Dictionary items = new Dictionary();
+
+ // The search provider does not support SQL parameters
+ filename = filename.Replace("'", "''");
+
+ OleDbCommand cmd = new OleDbCommand
+ {
+ Connection = _connection, CommandText = $"SELECT {columns} from systemindex WHERE System.ItemNameDisplay = '{filename}'"
+ };
+
+ OleDbDataReader results = cmd.ExecuteReader();
+
+ if (results.Read())
+ {
+ int i = 0;
+
+ while (i < results.FieldCount)
+ {
+ if (!results.IsDBNull(i))
+ {
+ var key = results.GetName(i);
+ string value;
+
+ if (results.GetValue(i) is string[])
+ {
+ string[] arrayValue = results.GetValue(i) as string[];
+
+ value = arrayValue.GetLength(0) == 1 ? arrayValue[0] : string.Join(", ", arrayValue);
+ }
+ else
+ {
+ value = results.GetValue(i).ToString();
+ }
+
+ if (key.StartsWith("System."))
+ key = key.Substring(7);
+ items.Add(key, value);
+ }
+
+ i = i + 1;
+ }
+ }
+
+ results.Close();
+
+ return items;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Models/HorizontalAlignment.cs b/src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearchKind.cs
similarity index 54%
rename from src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Models/HorizontalAlignment.cs
rename to src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearchKind.cs
index 38dc054..445f1f1 100644
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Models/HorizontalAlignment.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearchKind.cs
@@ -6,7 +6,7 @@
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
+// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
@@ -21,8 +21,7 @@
// DEALINGS IN THE SOFTWARE.
//
//
-// Created On: 2019/01/17 00:41
-// Modified On: 2019/01/17 00:41
+// Modified On: 2020/02/02 22:51
// Modified By: Alexis
#endregion
@@ -32,14 +31,58 @@
using System;
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Models
+namespace SuperMemoAssistant.Sys.Windows.Search
{
+ [Flags]
[Serializable]
- public enum HorizontalAlignment
+ public enum WindowsSearchKind
{
- Left,
- Center,
- Right,
- Stretch,
+ // KIND_CALENDAR
+ Calendar = 1,
+ // KIND_COMMUNICATION
+ Communication = 2,
+ // KIND_CONTACT
+ Contact = 4,
+ // KIND_DOCUMENT
+ Document = 8,
+ // KIND_EMAIL
+ Email = 16,
+ // KIND_FEED
+ Feed = 32,
+ // KIND_FOLDER
+ Folder = 64,
+ // KIND_GAME
+ Game = 128,
+ // KIND_INSTANTMESSAGE
+ InstantMessage = 256,
+ // KIND_JOURNAL
+ Journal = 512,
+ // KIND_LINK
+ Link = 1024,
+ // KIND_MOVIE
+ Movie = 2048,
+ // KIND_MUSIC
+ Music = 4096,
+ // KIND_NOTE
+ Note = 8192,
+ // KIND_PICTURE
+ Picture = 16384,
+ // KIND_PROGRAM
+ Program = 32768,
+ // KIND_RECORDEDTV
+ RecordedTv = 131072,
+ // KIND_SEARCHFOLDER
+ SearchFolder = 262144,
+ // KIND_TASK
+ Task = 524288,
+ // KIND_VIDEO
+ Video = 1048576,
+ // KIND_WEBHISTORY
+ WebHistory = 2097152,
+
+ // other
+ File = 4194304,
+
+ All = int.MaxValue
}
}
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Models/VerticalAlignment.cs b/src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearchResult.cs
similarity index 70%
rename from src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Models/VerticalAlignment.cs
rename to src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearchResult.cs
index 2b7c853..bd0ee85 100644
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Models/VerticalAlignment.cs
+++ b/src/Core/SuperMemoAssistant.Interop/Sys/Windows/Search/WindowsSearchResult.cs
@@ -6,7 +6,7 @@
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
+// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
@@ -21,8 +21,7 @@
// DEALINGS IN THE SOFTWARE.
//
//
-// Created On: 2019/01/17 00:32
-// Modified On: 2019/01/17 00:41
+// Modified On: 2020/02/02 22:51
// Modified By: Alexis
#endregion
@@ -32,14 +31,29 @@
using System;
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Models
+namespace SuperMemoAssistant.Sys.Windows.Search
{
[Serializable]
- public enum VerticalAlignment
+ public class WindowsSearchResult
{
- Top,
- Center,
- Bottom,
- Stretch,
+ #region Constructors
+
+ public WindowsSearchResult() { }
+
+ #endregion
+
+
+
+
+ #region Properties & Fields - Public
+
+ public String FileName { get; set; }
+ public String FilePath { get; set; }
+ public WindowsSearchKind Kind { get; set; }
+ public int Rank { get; set; }
+
+ public bool Touched { get; set; }
+
+ #endregion
}
}
diff --git a/src/Core/SuperMemoAssistant.Interop/packages.config b/src/Core/SuperMemoAssistant.Interop/packages.config
index 7573219..c9803aa 100644
--- a/src/Core/SuperMemoAssistant.Interop/packages.config
+++ b/src/Core/SuperMemoAssistant.Interop/packages.config
@@ -2,7 +2,7 @@
-
+
@@ -13,7 +13,7 @@
-
+
diff --git a/src/Core/SuperMemoAssistant.PluginHost/Properties/AssemblyInfo.cs b/src/Core/SuperMemoAssistant.PluginHost/Properties/AssemblyInfo.cs
index 4190499..6992313 100644
--- a/src/Core/SuperMemoAssistant.PluginHost/Properties/AssemblyInfo.cs
+++ b/src/Core/SuperMemoAssistant.PluginHost/Properties/AssemblyInfo.cs
@@ -81,7 +81,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.1")]
-[assembly: AssemblyFileVersion("2.0.2.1")]
+[assembly: AssemblyVersion("2.0.2.5")]
+[assembly: AssemblyFileVersion("2.0.2.5")]
[assembly: AssemblyInformationalVersion("2.0.2")]
\ No newline at end of file
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.Dictionary b/src/Plugins/SuperMemoAssistant.Plugins.Dictionary
index 7b54c38..2dcdf3b 160000
--- a/src/Plugins/SuperMemoAssistant.Plugins.Dictionary
+++ b/src/Plugins/SuperMemoAssistant.Plugins.Dictionary
@@ -1 +1 @@
-Subproject commit 7b54c38eaa1597b4d0fd515da9759b031d89d029
+Subproject commit 2dcdf3b931824a77db730ec1b21694d4d9da3649
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.ImageOcclusion b/src/Plugins/SuperMemoAssistant.Plugins.ImageOcclusion
index dad984d..377fc70 160000
--- a/src/Plugins/SuperMemoAssistant.Plugins.ImageOcclusion
+++ b/src/Plugins/SuperMemoAssistant.Plugins.ImageOcclusion
@@ -1 +1 @@
-Subproject commit dad984d99457c95df629ee2e6eaa1b98eb41a85a
+Subproject commit 377fc7023930351f3c34976581989d4d357cd0e1
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.Import b/src/Plugins/SuperMemoAssistant.Plugins.Import
index 375b8c6..8a0387c 160000
--- a/src/Plugins/SuperMemoAssistant.Plugins.Import
+++ b/src/Plugins/SuperMemoAssistant.Plugins.Import
@@ -1 +1 @@
-Subproject commit 375b8c67fed7992d9d2574b3f78b5844029a4f24
+Subproject commit 8a0387c4a18db2b42abe251e955cff446bc0ff3b
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.LateX b/src/Plugins/SuperMemoAssistant.Plugins.LateX
index 4f4e6e8..b0db27f 160000
--- a/src/Plugins/SuperMemoAssistant.Plugins.LateX
+++ b/src/Plugins/SuperMemoAssistant.Plugins.LateX
@@ -1 +1 @@
-Subproject commit 4f4e6e8a80882bb4d204f51d49779a3a411299de
+Subproject commit b0db27f5af3430e3d719812742765c33d7399086
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.MediaPlayer b/src/Plugins/SuperMemoAssistant.Plugins.MediaPlayer
index d3b0f7d..7780038 160000
--- a/src/Plugins/SuperMemoAssistant.Plugins.MediaPlayer
+++ b/src/Plugins/SuperMemoAssistant.Plugins.MediaPlayer
@@ -1 +1 @@
-Subproject commit d3b0f7de32d077b725fd3a91c0abe871af443cba
+Subproject commit 7780038b2d2a46a9d5ea70f21979076edf512f00
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.PDF b/src/Plugins/SuperMemoAssistant.Plugins.PDF
index dd564d0..8f0fb4e 160000
--- a/src/Plugins/SuperMemoAssistant.Plugins.PDF
+++ b/src/Plugins/SuperMemoAssistant.Plugins.PDF
@@ -1 +1 @@
-Subproject commit dd564d04da13a49adb0e3b74ab2c0264c110351a
+Subproject commit 8f0fb4ed737c798280a76815fac55540e1b172e9
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.Template/Properties/AssemblyInfo.cs b/src/Plugins/SuperMemoAssistant.Plugins.Template/Properties/AssemblyInfo.cs
index 38613f5..99e70cc 100644
--- a/src/Plugins/SuperMemoAssistant.Plugins.Template/Properties/AssemblyInfo.cs
+++ b/src/Plugins/SuperMemoAssistant.Plugins.Template/Properties/AssemblyInfo.cs
@@ -31,7 +31,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.0")]
-[assembly: AssemblyFileVersion("2.0.2.0")]
+[assembly: AssemblyVersion("2.0.2.1")]
+[assembly: AssemblyFileVersion("2.0.2.1")]
[assembly: AssemblyInformationalVersion("2.0.2")]
\ No newline at end of file
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.Template/SuperMemoAssistant.Plugins.Template.csproj b/src/Plugins/SuperMemoAssistant.Plugins.Template/SuperMemoAssistant.Plugins.Template.csproj
index e009e48..f3add2e 100644
--- a/src/Plugins/SuperMemoAssistant.Plugins.Template/SuperMemoAssistant.Plugins.Template.csproj
+++ b/src/Plugins/SuperMemoAssistant.Plugins.Template/SuperMemoAssistant.Plugins.Template.csproj
@@ -1,6 +1,6 @@
-
+
@@ -82,20 +82,20 @@
-
- ..\..\..\packages\PropertyChanged.Fody.3.2.4\lib\net40\PropertyChanged.dll
+
+ ..\..\..\packages\PropertyChanged.Fody.3.2.5\lib\net40\PropertyChanged.dll
-
- ..\..\..\packages\Sentry.1.2.0\lib\net461\Sentry.dll
+
+ ..\..\..\packages\Sentry.2.0.1\lib\net461\Sentry.dll
-
- ..\..\..\packages\Sentry.PlatformAbstractions.1.0.0\lib\net471\Sentry.PlatformAbstractions.dll
+
+ ..\..\..\packages\Sentry.PlatformAbstractions.1.1.0\lib\net471\Sentry.PlatformAbstractions.dll
-
- ..\..\..\packages\Sentry.Protocol.1.0.6\lib\net46\Sentry.Protocol.dll
+
+ ..\..\..\packages\Sentry.Protocol.2.0.0\lib\net46\Sentry.Protocol.dll
-
- ..\..\..\packages\Sentry.Serilog.1.2.0\lib\net461\Sentry.Serilog.dll
+
+ ..\..\..\packages\Sentry.Serilog.2.0.1\lib\net461\Sentry.Serilog.dll
..\..\..\packages\Serilog.2.9.0\lib\net46\Serilog.dll
@@ -172,8 +172,8 @@
-
-
+
+
-
+
\ No newline at end of file
diff --git a/src/Plugins/SuperMemoAssistant.Plugins.Template/packages.config b/src/Plugins/SuperMemoAssistant.Plugins.Template/packages.config
index d260746..467c3f6 100644
--- a/src/Plugins/SuperMemoAssistant.Plugins.Template/packages.config
+++ b/src/Plugins/SuperMemoAssistant.Plugins.Template/packages.config
@@ -4,18 +4,18 @@
-
+
-
-
-
-
-
+
+
+
+
+
diff --git a/src/Services/SuperMemoAssistant.Services.HTML/Properties/AssemblyInfo.cs b/src/Services/SuperMemoAssistant.Services.HTML/Properties/AssemblyInfo.cs
index 88e4e97..262acbc 100644
--- a/src/Services/SuperMemoAssistant.Services.HTML/Properties/AssemblyInfo.cs
+++ b/src/Services/SuperMemoAssistant.Services.HTML/Properties/AssemblyInfo.cs
@@ -63,7 +63,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.4")]
-[assembly: AssemblyFileVersion("2.0.2.4")]
+[assembly: AssemblyVersion("2.0.2.17")]
+[assembly: AssemblyFileVersion("2.0.2.17")]
[assembly: AssemblyInformationalVersion("2.0.2")]
\ No newline at end of file
diff --git a/src/Services/SuperMemoAssistant.Services.HTML/SuperMemoAssistant.Services.HTML.csproj b/src/Services/SuperMemoAssistant.Services.HTML/SuperMemoAssistant.Services.HTML.csproj
index 4b7759d..f50c185 100644
--- a/src/Services/SuperMemoAssistant.Services.HTML/SuperMemoAssistant.Services.HTML.csproj
+++ b/src/Services/SuperMemoAssistant.Services.HTML/SuperMemoAssistant.Services.HTML.csproj
@@ -1,11 +1,11 @@
-
+
+
+
+
+
-
-
-
-
Debug
@@ -93,8 +93,8 @@
-
- ..\..\..\packages\PropertyChanged.Fody.3.2.4\lib\net40\PropertyChanged.dll
+
+ ..\..\..\packages\PropertyChanged.Fody.3.2.5\lib\net40\PropertyChanged.dll
..\..\..\packages\Serilog.2.9.0\lib\net46\Serilog.dll
@@ -158,21 +158,21 @@
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/src/Services/SuperMemoAssistant.Services.HTML/packages.config b/src/Services/SuperMemoAssistant.Services.HTML/packages.config
index cf49088..d7fbb90 100644
--- a/src/Services/SuperMemoAssistant.Services.HTML/packages.config
+++ b/src/Services/SuperMemoAssistant.Services.HTML/packages.config
@@ -1,14 +1,14 @@
-
-
-
-
+
+
+
+
-
+
@@ -17,7 +17,7 @@
-
+
\ No newline at end of file
diff --git a/src/Services/SuperMemoAssistant.Services.Medias.Images/Properties/AssemblyInfo.cs b/src/Services/SuperMemoAssistant.Services.Medias.Images/Properties/AssemblyInfo.cs
index 242be0e..e41a313 100644
--- a/src/Services/SuperMemoAssistant.Services.Medias.Images/Properties/AssemblyInfo.cs
+++ b/src/Services/SuperMemoAssistant.Services.Medias.Images/Properties/AssemblyInfo.cs
@@ -63,7 +63,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.0")]
-[assembly: AssemblyFileVersion("2.0.2.0")]
+[assembly: AssemblyVersion("2.0.2.1")]
+[assembly: AssemblyFileVersion("2.0.2.1")]
[assembly: AssemblyInformationalVersion("2.0.2")]
diff --git a/src/Services/SuperMemoAssistant.Services.UI/Properties/AssemblyInfo.cs b/src/Services/SuperMemoAssistant.Services.UI/Properties/AssemblyInfo.cs
index a8706fc..5e716af 100644
--- a/src/Services/SuperMemoAssistant.Services.UI/Properties/AssemblyInfo.cs
+++ b/src/Services/SuperMemoAssistant.Services.UI/Properties/AssemblyInfo.cs
@@ -31,7 +31,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.2.4")]
-[assembly: AssemblyFileVersion("2.0.2.4")]
+[assembly: AssemblyVersion("2.0.2.17")]
+[assembly: AssemblyFileVersion("2.0.2.17")]
[assembly: AssemblyInformationalVersion("2.0.2")]
\ No newline at end of file
diff --git a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.Internal.cs b/src/Services/SuperMemoAssistant.Services.UI/Services/UI/Extensions/StringEx.cs
similarity index 67%
rename from src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.Internal.cs
rename to src/Services/SuperMemoAssistant.Services.UI/Services/UI/Extensions/StringEx.cs
index 92f1260..b57be73 100644
--- a/src/Core/SuperMemoAssistant.Interop/Interop/SuperMemo/Content/Layout/Legacy/Grid/LayoutGrid.Internal.cs
+++ b/src/Services/SuperMemoAssistant.Services.UI/Services/UI/Extensions/StringEx.cs
@@ -6,7 +6,7 @@
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
+// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
@@ -21,8 +21,7 @@
// DEALINGS IN THE SOFTWARE.
//
//
-// Created On: 2019/01/17 14:35
-// Modified On: 2019/01/17 20:51
+// Modified On: 2020/02/03 10:19
// Modified By: Alexis
#endregion
@@ -30,33 +29,30 @@
-namespace SuperMemoAssistant.Interop.SuperMemo.Content.Layout.Legacy.Grid
+using System.Threading.Tasks;
+using Forge.Forms;
+
+namespace SuperMemoAssistant.Services.UI.Extensions
{
- public partial class LayoutGrid
+ public static class StringEx
{
- protected class VectorData
- {
- #region Properties & Fields - Public
-
- public int UsedSize { get; set; }
- public int BlockCount { get; set; }
- public int FillBlockCount { get; set; }
-
- #endregion
-
-
-
+ #region Methods
- #region Methods
+ public static Task ErrorMsgBox(this string msg)
+ {
+ return Show.Window().For(new Alert(msg, "Error"));
+ }
- public void Reset()
- {
- UsedSize = 0;
- BlockCount = 0;
- FillBlockCount = 0;
- }
+ public static Task WarningMsgBox(this string msg)
+ {
+ return Show.Window().For(new Alert(msg, "Warning"));
+ }
- #endregion
+ public static Task InfoMsgBox(this string msg)
+ {
+ return Show.Window().For(new Alert(msg, "Information"));
}
+
+ #endregion
}
}
diff --git a/src/Services/SuperMemoAssistant.Services.UI/SuperMemoAssistant.Services.UI.csproj b/src/Services/SuperMemoAssistant.Services.UI/SuperMemoAssistant.Services.UI.csproj
index 8bf6e55..fd5df8d 100644
--- a/src/Services/SuperMemoAssistant.Services.UI/SuperMemoAssistant.Services.UI.csproj
+++ b/src/Services/SuperMemoAssistant.Services.UI/SuperMemoAssistant.Services.UI.csproj
@@ -1,6 +1,6 @@
-
+
@@ -88,8 +88,8 @@
-
- ..\..\..\packages\PropertyChanged.Fody.3.2.4\lib\net40\PropertyChanged.dll
+
+ ..\..\..\packages\PropertyChanged.Fody.3.2.5\lib\net40\PropertyChanged.dll
..\..\..\packages\Serilog.2.9.0\lib\net46\Serilog.dll
@@ -125,6 +125,7 @@
+
@@ -168,8 +169,8 @@
-
-
+
+
-
+
\ No newline at end of file
diff --git a/src/Services/SuperMemoAssistant.Services.UI/packages.config b/src/Services/SuperMemoAssistant.Services.UI/packages.config
index c384b1b..ac6b5d1 100644
--- a/src/Services/SuperMemoAssistant.Services.UI/packages.config
+++ b/src/Services/SuperMemoAssistant.Services.UI/packages.config
@@ -3,7 +3,7 @@
-
+
@@ -12,6 +12,6 @@
-
+
\ No newline at end of file