mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-15 15:09:29 +00:00
Moved MonoGame.Extended.Gui to its own repository (#905)
This commit is contained in:
committed by
GitHub
parent
1f3f1c5aa0
commit
98ee05f58a
@@ -15,8 +15,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Entities", "so
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Graphics", "source\MonoGame.Extended.Graphics\FNA.Extended.Graphics.csproj", "{56627685-4BA7-44E3-ACA6-F2990DE089F2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Gui", "source\MonoGame.Extended.Gui\FNA.Extended.Gui.csproj", "{16E79E22-A41A-47BC-9DC9-287B812A6DD1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Input", "source\MonoGame.Extended.Input\FNA.Extended.Input.csproj", "{76B39424-7884-4EEC-A8D5-5126B29941B7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Particles", "source\MonoGame.Extended.Particles\FNA.Extended.Particles.csproj", "{BE74938D-9004-4D36-AD50-5C6C141A7180}"
|
||||
@@ -31,8 +29,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Collisions.Tes
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Entities.Tests", "tests\MonoGame.Extended.Entities.Tests\FNA.Extended.Entities.Tests.csproj", "{D3B0E350-B92E-4E49-99A3-68E66CB53F16}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Gui.Tests", "tests\MonoGame.Extended.Gui.Tests\FNA.Extended.Gui.Tests.csproj", "{AA52F204-3EE7-40CB-B041-0AB36475DAF0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Tests", "tests\MonoGame.Extended.Tests\FNA.Extended.Tests.csproj", "{E1339B07-EB0B-454F-9803-E923843DB5C4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Extended.Tiled.Tests", "tests\MonoGame.Extended.Tiled.Tests\FNA.Extended.Tiled.Tests.csproj", "{BF0EC593-4BAB-424F-B7E9-BB13EC78A0E5}"
|
||||
@@ -91,14 +87,6 @@ Global
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
@@ -147,14 +135,6 @@ Global
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
@@ -197,14 +177,12 @@ Global
|
||||
{7F60B59F-4B84-401F-8A13-AAA3F0B9E4A5} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{CD5C1878-13B6-4FAD-91AE-AEA3C1520E38} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{BE74938D-9004-4D36-AD50-5C6C141A7180} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{572C908D-4627-4678-9641-D4950DE43B13} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{F144A062-4FF3-44EC-9A04-31C654B436B0} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{58F88A3C-C09F-4664-A34E-60E89252870A} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{BF0EC593-4BAB-424F-B7E9-BB13EC78A0E5} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{C2A9982B-7BF7-4243-9E05-CFD31752B6DC} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
|
||||
@@ -17,8 +17,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Entities", "so
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Graphics", "source\MonoGame.Extended.Graphics\KNI.Extended.Graphics.csproj", "{56627685-4BA7-44E3-ACA6-F2990DE089F2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Gui", "source\MonoGame.Extended.Gui\KNI.Extended.Gui.csproj", "{16E79E22-A41A-47BC-9DC9-287B812A6DD1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Input", "source\MonoGame.Extended.Input\KNI.Extended.Input.csproj", "{76B39424-7884-4EEC-A8D5-5126B29941B7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Particles", "source\MonoGame.Extended.Particles\KNI.Extended.Particles.csproj", "{BE74938D-9004-4D36-AD50-5C6C141A7180}"
|
||||
@@ -37,8 +35,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Content.Pipeli
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Entities.Tests", "tests\MonoGame.Extended.Entities.Tests\KNI.Extended.Entities.Tests.csproj", "{D3B0E350-B92E-4E49-99A3-68E66CB53F16}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Gui.Tests", "tests\MonoGame.Extended.Gui.Tests\KNI.Extended.Gui.Tests.csproj", "{AA52F204-3EE7-40CB-B041-0AB36475DAF0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Tests", "tests\MonoGame.Extended.Tests\KNI.Extended.Tests.csproj", "{E1339B07-EB0B-454F-9803-E923843DB5C4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KNI.Extended.Tiled.Tests", "tests\MonoGame.Extended.Tiled.Tests\KNI.Extended.Tiled.Tests.csproj", "{BF0EC593-4BAB-424F-B7E9-BB13EC78A0E5}"
|
||||
@@ -101,14 +97,6 @@ Global
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
@@ -173,14 +161,6 @@ Global
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
@@ -216,7 +196,6 @@ Global
|
||||
{4A4066EB-B49A-4E80-B424-9E0BD2147886} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{CD5C1878-13B6-4FAD-91AE-AEA3C1520E38} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{BE74938D-9004-4D36-AD50-5C6C141A7180} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{572C908D-4627-4678-9641-D4950DE43B13} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
@@ -225,7 +204,6 @@ Global
|
||||
{A127A61A-B26E-4A01-BD4C-9896FDB287AE} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{0426263A-B8DE-43FC-A91E-21544F61D80E} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{BF0EC593-4BAB-424F-B7E9-BB13EC78A0E5} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{C2A9982B-7BF7-4243-9E05-CFD31752B6DC} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
|
||||
@@ -17,8 +17,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Entities"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Graphics", "source\MonoGame.Extended.Graphics\MonoGame.Extended.Graphics.csproj", "{56627685-4BA7-44E3-ACA6-F2990DE089F2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Gui", "source\MonoGame.Extended.Gui\MonoGame.Extended.Gui.csproj", "{16E79E22-A41A-47BC-9DC9-287B812A6DD1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Input", "source\MonoGame.Extended.Input\MonoGame.Extended.Input.csproj", "{76B39424-7884-4EEC-A8D5-5126B29941B7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Particles", "source\MonoGame.Extended.Particles\MonoGame.Extended.Particles.csproj", "{BE74938D-9004-4D36-AD50-5C6C141A7180}"
|
||||
@@ -37,8 +35,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Content.P
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Entities.Tests", "tests\MonoGame.Extended.Entities.Tests\MonoGame.Extended.Entities.Tests.csproj", "{D3B0E350-B92E-4E49-99A3-68E66CB53F16}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Gui.Tests", "tests\MonoGame.Extended.Gui.Tests\MonoGame.Extended.Gui.Tests.csproj", "{AA52F204-3EE7-40CB-B041-0AB36475DAF0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Tests", "tests\MonoGame.Extended.Tests\MonoGame.Extended.Tests.csproj", "{E1339B07-EB0B-454F-9803-E923843DB5C4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Tiled.Tests", "tests\MonoGame.Extended.Tiled.Tests\MonoGame.Extended.Tiled.Tests.csproj", "{BF0EC593-4BAB-424F-B7E9-BB13EC78A0E5}"
|
||||
@@ -101,14 +97,6 @@ Global
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
@@ -173,14 +161,6 @@ Global
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
@@ -216,7 +196,6 @@ Global
|
||||
{4A4066EB-B49A-4E80-B424-9E0BD2147886} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{CD5C1878-13B6-4FAD-91AE-AEA3C1520E38} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{56627685-4BA7-44E3-ACA6-F2990DE089F2} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{16E79E22-A41A-47BC-9DC9-287B812A6DD1} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{76B39424-7884-4EEC-A8D5-5126B29941B7} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{BE74938D-9004-4D36-AD50-5C6C141A7180} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
{572C908D-4627-4678-9641-D4950DE43B13} = {2BD6F851-7287-4361-85AB-DAE9DF30D932}
|
||||
@@ -225,7 +204,6 @@ Global
|
||||
{A127A61A-B26E-4A01-BD4C-9896FDB287AE} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{0426263A-B8DE-43FC-A91E-21544F61D80E} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{D3B0E350-B92E-4E49-99A3-68E66CB53F16} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{AA52F204-3EE7-40CB-B041-0AB36475DAF0} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{E1339B07-EB0B-454F-9803-E923843DB5C4} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{BF0EC593-4BAB-424F-B7E9-BB13EC78A0E5} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
{C2A9982B-7BF7-4243-9E05-CFD31752B6DC} = {61C82014-E3A9-4AB3-8705-FBBD5F799BA6}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public class ControlStyle : IDictionary<string, object>
|
||||
{
|
||||
private readonly Dictionary<Guid, Dictionary<string, object>> _previousStates = new Dictionary<Guid, Dictionary<string, object>>();
|
||||
|
||||
public ControlStyle()
|
||||
: this(typeof(Element))
|
||||
{
|
||||
}
|
||||
|
||||
public ControlStyle(Type targetType)
|
||||
: this(targetType.FullName, targetType)
|
||||
{
|
||||
}
|
||||
|
||||
public ControlStyle(string name, Type targetType)
|
||||
{
|
||||
Name = name;
|
||||
TargetType = targetType;
|
||||
_setters = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public Type TargetType { get; set; }
|
||||
|
||||
private readonly Dictionary<string, object> _setters;
|
||||
|
||||
public void ApplyIf(Control control, bool predicate)
|
||||
{
|
||||
if (predicate)
|
||||
Apply(control);
|
||||
else
|
||||
Revert(control);
|
||||
}
|
||||
|
||||
public void Apply(Control control)
|
||||
{
|
||||
_previousStates[control.Id] = _setters
|
||||
.ToDictionary(i => i.Key, i => TargetType.GetRuntimeProperty(i.Key)?.GetValue(control));
|
||||
|
||||
ChangePropertyValues(control, _setters);
|
||||
}
|
||||
|
||||
public void Revert(Control control)
|
||||
{
|
||||
if (_previousStates.ContainsKey(control.Id) && _previousStates[control.Id] != null)
|
||||
ChangePropertyValues(control, _previousStates[control.Id]);
|
||||
|
||||
_previousStates[control.Id] = null;
|
||||
}
|
||||
|
||||
private static void ChangePropertyValues(Control control, Dictionary<string, object> setters)
|
||||
{
|
||||
var targetType = control.GetType();
|
||||
|
||||
foreach (var propertyName in setters.Keys)
|
||||
{
|
||||
var propertyInfo = targetType.GetRuntimeProperty(propertyName);
|
||||
var value = setters[propertyName];
|
||||
|
||||
if (propertyInfo != null)
|
||||
{
|
||||
if(propertyInfo.CanWrite)
|
||||
propertyInfo.SetValue(control, value);
|
||||
|
||||
// special case when we have a list of items as objects (like on a list box)
|
||||
if (propertyInfo.PropertyType == typeof(List<object>))
|
||||
{
|
||||
var items = (List<object>)value;
|
||||
var addMethod = propertyInfo.PropertyType.GetRuntimeMethod("Add", new[] { typeof(object) });
|
||||
|
||||
foreach (var item in items)
|
||||
addMethod.Invoke(propertyInfo.GetValue(control), new[] {item});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public object this[string key]
|
||||
{
|
||||
get { return _setters[key]; }
|
||||
set { _setters[key] = value; }
|
||||
}
|
||||
|
||||
public ICollection<string> Keys => _setters.Keys;
|
||||
public ICollection<object> Values => _setters.Values;
|
||||
public int Count => _setters.Count;
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => _setters.GetEnumerator();
|
||||
public void Add(string key, object value) => _setters.Add(key, value);
|
||||
public void Add(KeyValuePair<string, object> item) => _setters.Add(item.Key, item.Value);
|
||||
public bool Remove(string key) => _setters.Remove(key);
|
||||
public bool Remove(KeyValuePair<string, object> item) => _setters.Remove(item.Key);
|
||||
public void Clear() => _setters.Clear();
|
||||
public bool Contains(KeyValuePair<string, object> item) => _setters.Contains(item);
|
||||
public bool ContainsKey(string key) => _setters.ContainsKey(key);
|
||||
public bool TryGetValue(string key, out object value) => _setters.TryGetValue(key, out value);
|
||||
|
||||
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class Box : Control
|
||||
{
|
||||
public override IEnumerable<Control> Children { get; } = Enumerable.Empty<Control>();
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
return new Size(Width, Height);
|
||||
}
|
||||
|
||||
public Color FillColor { get; set; } = Color.White;
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
base.Draw(context, renderer, deltaSeconds);
|
||||
renderer.FillRectangle(ContentRectangle, FillColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class Button : ContentControl
|
||||
{
|
||||
public Button()
|
||||
{
|
||||
}
|
||||
|
||||
public event EventHandler Clicked;
|
||||
public event EventHandler PressedStateChanged;
|
||||
|
||||
private bool _isPressed;
|
||||
public bool IsPressed
|
||||
{
|
||||
get => _isPressed;
|
||||
set
|
||||
{
|
||||
if (_isPressed != value)
|
||||
{
|
||||
_isPressed = value;
|
||||
PressedStyle?.ApplyIf(this, _isPressed);
|
||||
PressedStateChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ControlStyle _pressedStyle;
|
||||
public ControlStyle PressedStyle
|
||||
{
|
||||
get => _pressedStyle;
|
||||
set
|
||||
{
|
||||
if (_pressedStyle != value)
|
||||
{
|
||||
_pressedStyle = value;
|
||||
PressedStyle?.ApplyIf(this, _isPressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isPointerDown;
|
||||
|
||||
public override bool OnPointerDown(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
if (IsEnabled)
|
||||
{
|
||||
_isPointerDown = true;
|
||||
IsPressed = true;
|
||||
}
|
||||
|
||||
return base.OnPointerDown(context, args);
|
||||
}
|
||||
|
||||
public override bool OnPointerUp(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
_isPointerDown = false;
|
||||
|
||||
if (IsPressed)
|
||||
{
|
||||
IsPressed = false;
|
||||
|
||||
if (BoundingRectangle.Contains(args.Position) && IsEnabled)
|
||||
Click();
|
||||
}
|
||||
|
||||
return base.OnPointerUp(context, args);
|
||||
}
|
||||
|
||||
public override bool OnPointerEnter(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
if (IsEnabled && _isPointerDown)
|
||||
IsPressed = true;
|
||||
|
||||
return base.OnPointerEnter(context, args);
|
||||
}
|
||||
|
||||
public override bool OnPointerLeave(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
if (IsEnabled)
|
||||
IsPressed = false;
|
||||
|
||||
return base.OnPointerLeave(context, args);
|
||||
}
|
||||
|
||||
public void Click()
|
||||
{
|
||||
Clicked?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class Canvas : LayoutControl
|
||||
{
|
||||
public Canvas()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Layout(IGuiContext context, Rectangle rectangle)
|
||||
{
|
||||
foreach (var control in Items)
|
||||
{
|
||||
var actualSize = control.CalculateActualSize(context);
|
||||
PlaceControl(context, control, control.Position.X, control.Position.Y, actualSize.Width, actualSize.Height);
|
||||
}
|
||||
}
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
return new Size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class CheckBox : CompositeControl
|
||||
{
|
||||
public CheckBox()
|
||||
{
|
||||
_contentLabel = new Label();
|
||||
_checkLabel = new Box {Width = 20, Height = 20};
|
||||
|
||||
_toggleButton = new ToggleButton
|
||||
{
|
||||
Margin = 0,
|
||||
Padding = 0,
|
||||
BackgroundColor = Color.Transparent,
|
||||
BorderThickness = 0,
|
||||
HoverStyle = null,
|
||||
CheckedStyle = null,
|
||||
PressedStyle = null,
|
||||
Content = new StackPanel
|
||||
{
|
||||
Margin = 0,
|
||||
Orientation = Orientation.Horizontal,
|
||||
Items =
|
||||
{
|
||||
_checkLabel,
|
||||
_contentLabel
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_toggleButton.CheckedStateChanged += (sender, args) => OnIsCheckedChanged();
|
||||
Template = _toggleButton;
|
||||
OnIsCheckedChanged();
|
||||
}
|
||||
|
||||
private readonly Label _contentLabel;
|
||||
private readonly ToggleButton _toggleButton;
|
||||
private readonly Box _checkLabel;
|
||||
|
||||
protected override Control Template { get; }
|
||||
|
||||
public override object Content
|
||||
{
|
||||
get => _contentLabel.Content;
|
||||
set => _contentLabel.Content = value;
|
||||
}
|
||||
|
||||
public bool IsChecked
|
||||
{
|
||||
get => _toggleButton.IsChecked;
|
||||
set
|
||||
{
|
||||
_toggleButton.IsChecked = value;
|
||||
OnIsCheckedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnIsCheckedChanged()
|
||||
{
|
||||
_checkLabel.FillColor = IsChecked ? Color.White : Color.Transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using MonoGame.Extended.Graphics;
|
||||
using MonoGame.Extended.Input.InputListeners;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class ComboBox : SelectorControl
|
||||
{
|
||||
public ComboBox()
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsOpen { get; set; }
|
||||
public Texture2DRegion DropDownRegion { get; set; }
|
||||
public Color DropDownColor { get; set; } = Color.White;
|
||||
|
||||
public override bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args)
|
||||
{
|
||||
if (args.Key == Keys.Enter)
|
||||
IsOpen = false;
|
||||
|
||||
return base.OnKeyPressed(context, args);
|
||||
}
|
||||
|
||||
public override bool OnPointerUp(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
IsOpen = !IsOpen;
|
||||
return base.OnPointerUp(context, args);
|
||||
}
|
||||
|
||||
protected override Rectangle GetListAreaRectangle(IGuiContext context)
|
||||
{
|
||||
return GetDropDownRectangle(context);
|
||||
}
|
||||
|
||||
public override bool Contains(IGuiContext context, Point point)
|
||||
{
|
||||
return base.Contains(context, point) || IsOpen && GetListAreaRectangle(context).Contains(point);
|
||||
}
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
var width = 0;
|
||||
var height = 0;
|
||||
|
||||
foreach (var item in Items)
|
||||
{
|
||||
var itemSize = GetItemSize(context, item);
|
||||
|
||||
if (itemSize.Width > width)
|
||||
width = itemSize.Width;
|
||||
|
||||
if (itemSize.Height > height)
|
||||
height = itemSize.Height;
|
||||
}
|
||||
|
||||
return new Size(width + ClipPadding.Width, height + ClipPadding.Height);
|
||||
}
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
base.Draw(context, renderer, deltaSeconds);
|
||||
|
||||
if (IsOpen)
|
||||
{
|
||||
var dropDownRectangle = GetListAreaRectangle(context);
|
||||
|
||||
if (DropDownRegion != null)
|
||||
{
|
||||
renderer.DrawRegion(DropDownRegion, dropDownRectangle, DropDownColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.FillRectangle(dropDownRectangle, DropDownColor);
|
||||
renderer.DrawRectangle(dropDownRectangle, BorderColor);
|
||||
}
|
||||
|
||||
DrawItemList(context, renderer);
|
||||
}
|
||||
|
||||
var selectedTextInfo = GetItemTextInfo(context, ContentRectangle, SelectedItem);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(selectedTextInfo.Text))
|
||||
renderer.DrawText(selectedTextInfo.Font, selectedTextInfo.Text, selectedTextInfo.Position + TextOffset, selectedTextInfo.Color, selectedTextInfo.ClippingRectangle);
|
||||
}
|
||||
|
||||
private Rectangle GetDropDownRectangle(IGuiContext context)
|
||||
{
|
||||
var dropDownRectangle = BoundingRectangle;
|
||||
|
||||
dropDownRectangle.Y = dropDownRectangle.Y + dropDownRectangle.Height;
|
||||
dropDownRectangle.Height = (int) Items
|
||||
.Select(item => GetItemSize(context, item))
|
||||
.Select(itemSize => itemSize.Height)
|
||||
.Sum();
|
||||
|
||||
return dropDownRectangle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public abstract class CompositeControl : Control
|
||||
{
|
||||
protected CompositeControl()
|
||||
{
|
||||
}
|
||||
|
||||
protected bool IsDirty { get; set; } = true;
|
||||
|
||||
public abstract object Content { get; set; }
|
||||
|
||||
protected abstract Control Template { get; }
|
||||
|
||||
public override IEnumerable<Control> Children
|
||||
{
|
||||
get
|
||||
{
|
||||
var control = Template;
|
||||
|
||||
if (control != null)
|
||||
yield return control;
|
||||
}
|
||||
}
|
||||
|
||||
public override void InvalidateMeasure()
|
||||
{
|
||||
base.InvalidateMeasure();
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
var control = Template;
|
||||
|
||||
if (control != null)
|
||||
return Template.CalculateActualSize(context);
|
||||
|
||||
return Size.Empty;
|
||||
}
|
||||
|
||||
public override void Update(IGuiContext context, float deltaSeconds)
|
||||
{
|
||||
var control = Template;
|
||||
|
||||
if (control != null)
|
||||
{
|
||||
if (IsDirty)
|
||||
{
|
||||
control.Parent = this;
|
||||
control.ActualSize = new Point(ContentRectangle.Width, ContentRectangle.Height);
|
||||
control.Position = new Point(Padding.Left, Padding.Top);
|
||||
control.InvalidateMeasure();
|
||||
IsDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
base.Draw(context, renderer, deltaSeconds);
|
||||
|
||||
var control = Template;
|
||||
control?.Draw(context, renderer, deltaSeconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class ContentControl : Control
|
||||
{
|
||||
private bool _contentChanged = true;
|
||||
|
||||
private object _content;
|
||||
public object Content
|
||||
{
|
||||
get => _content;
|
||||
set
|
||||
{
|
||||
if (_content != value)
|
||||
{
|
||||
_content = value;
|
||||
_contentChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Control> Children
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Content is Control control)
|
||||
yield return control;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasContent => Content == null;
|
||||
|
||||
public override void InvalidateMeasure()
|
||||
{
|
||||
base.InvalidateMeasure();
|
||||
_contentChanged = true;
|
||||
}
|
||||
|
||||
public override void Update(IGuiContext context, float deltaSeconds)
|
||||
{
|
||||
if (_content is Control control && _contentChanged)
|
||||
{
|
||||
control.Parent = this;
|
||||
control.ActualSize = new Point(ContentRectangle.Width, ContentRectangle.Height);
|
||||
control.Position = new Point(Padding.Left, Padding.Top);
|
||||
control.InvalidateMeasure();
|
||||
_contentChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
base.Draw(context, renderer, deltaSeconds);
|
||||
|
||||
if (Content is Control control)
|
||||
{
|
||||
control.Draw(context, renderer, deltaSeconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
var text = Content?.ToString();
|
||||
var textInfo = GetTextInfo(context, text, ContentRectangle, HorizontalTextAlignment, VerticalTextAlignment);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(textInfo.Text))
|
||||
renderer.DrawText(textInfo.Font, textInfo.Text, textInfo.Position + TextOffset, textInfo.Color, textInfo.ClippingRectangle);
|
||||
}
|
||||
}
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
if (Content is Control control)
|
||||
return control.CalculateActualSize(context);
|
||||
|
||||
var text = Content?.ToString();
|
||||
var font = Font ?? context.DefaultFont;
|
||||
return (Size)font.MeasureString(text ?? string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,271 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.BitmapFonts;
|
||||
using MonoGame.Extended.Input.InputListeners;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public abstract class Control : Element<Control>, IRectangular
|
||||
{
|
||||
protected Control()
|
||||
{
|
||||
BackgroundColor = Color.White;
|
||||
TextColor = Color.White;
|
||||
IsEnabled = true;
|
||||
IsVisible = true;
|
||||
Origin = Point.Zero;
|
||||
Skin = Skin.Default;
|
||||
}
|
||||
|
||||
private Skin _skin;
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public Skin Skin
|
||||
{
|
||||
get => _skin;
|
||||
set
|
||||
{
|
||||
if (_skin != value)
|
||||
{
|
||||
_skin = value;
|
||||
_skin?.Apply(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract IEnumerable<Control> Children { get; }
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public Thickness Margin { get; set; }
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public Thickness Padding { get; set; }
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public Thickness ClipPadding { get; set; }
|
||||
|
||||
public bool IsLayoutRequired { get; set; }
|
||||
|
||||
public Rectangle ClippingRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
var r = BoundingRectangle;
|
||||
return new Rectangle(r.Left + ClipPadding.Left, r.Top + ClipPadding.Top, r.Width - ClipPadding.Width, r.Height - ClipPadding.Height);
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle ContentRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
var r = BoundingRectangle;
|
||||
return new Rectangle(r.Left + Padding.Left, r.Top + Padding.Top, r.Width - Padding.Width, r.Height - Padding.Height);
|
||||
}
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public bool IsFocused { get; set; }
|
||||
|
||||
private bool _isHovered;
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public bool IsHovered
|
||||
{
|
||||
get => _isHovered;
|
||||
private set
|
||||
{
|
||||
if (_isHovered != value)
|
||||
{
|
||||
_isHovered = value;
|
||||
HoverStyle?.ApplyIf(this, _isHovered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
public Vector2 Offset { get; set; }
|
||||
public BitmapFont Font { get; set; }
|
||||
public Color TextColor { get; set; }
|
||||
public Vector2 TextOffset { get; set; }
|
||||
public HorizontalAlignment HorizontalAlignment { get; set; } = HorizontalAlignment.Stretch;
|
||||
public VerticalAlignment VerticalAlignment { get; set; } = VerticalAlignment.Stretch;
|
||||
public HorizontalAlignment HorizontalTextAlignment { get; set; } = HorizontalAlignment.Centre;
|
||||
public VerticalAlignment VerticalTextAlignment { get; set; } = VerticalAlignment.Centre;
|
||||
|
||||
public abstract Size GetContentSize(IGuiContext context);
|
||||
|
||||
public virtual Size CalculateActualSize(IGuiContext context)
|
||||
{
|
||||
var fixedSize = Size;
|
||||
var desiredSize = GetContentSize(context) + Margin.Size + Padding.Size;
|
||||
|
||||
if (desiredSize.Width < MinWidth)
|
||||
desiredSize.Width = MinWidth;
|
||||
|
||||
if (desiredSize.Height < MinHeight)
|
||||
desiredSize.Height = MinHeight;
|
||||
|
||||
if (desiredSize.Width > MaxWidth)
|
||||
desiredSize.Width = MaxWidth;
|
||||
|
||||
if (desiredSize.Height > MaxWidth)
|
||||
desiredSize.Height = MaxHeight;
|
||||
|
||||
var width = fixedSize.Width == 0 ? desiredSize.Width : fixedSize.Width;
|
||||
var height = fixedSize.Height == 0 ? desiredSize.Height : fixedSize.Height;
|
||||
return new Size(width, height);
|
||||
}
|
||||
|
||||
public virtual void InvalidateMeasure() { }
|
||||
|
||||
private bool _isEnabled;
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set
|
||||
{
|
||||
if (_isEnabled != value)
|
||||
{
|
||||
_isEnabled = value;
|
||||
DisabledStyle?.ApplyIf(this, !_isEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsVisible { get; set; }
|
||||
|
||||
private ControlStyle _hoverStyle;
|
||||
public ControlStyle HoverStyle
|
||||
{
|
||||
get => _hoverStyle;
|
||||
set
|
||||
{
|
||||
if (_hoverStyle != value)
|
||||
{
|
||||
_hoverStyle = value;
|
||||
HoverStyle?.ApplyIf(this, _isHovered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ControlStyle _disabledStyle;
|
||||
public ControlStyle DisabledStyle
|
||||
{
|
||||
get => _disabledStyle;
|
||||
set
|
||||
{
|
||||
_disabledStyle = value;
|
||||
DisabledStyle?.ApplyIf(this, !_isEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnScrolled(int delta) { }
|
||||
|
||||
public virtual bool OnKeyTyped(IGuiContext context, KeyboardEventArgs args) { return true; }
|
||||
public virtual bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args) { return true; }
|
||||
|
||||
public virtual bool OnFocus(IGuiContext context) { return true; }
|
||||
public virtual bool OnUnfocus(IGuiContext context) { return true; }
|
||||
|
||||
public virtual bool OnPointerDown(IGuiContext context, PointerEventArgs args) { return true; }
|
||||
public virtual bool OnPointerMove(IGuiContext context, PointerEventArgs args) { return true; }
|
||||
public virtual bool OnPointerUp(IGuiContext context, PointerEventArgs args) { return true; }
|
||||
|
||||
public virtual bool OnPointerEnter(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
if (IsEnabled && !IsHovered)
|
||||
IsHovered = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool OnPointerLeave(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
if (IsEnabled && IsHovered)
|
||||
IsHovered = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool Contains(IGuiContext context, Point point)
|
||||
{
|
||||
return BoundingRectangle.Contains(point);
|
||||
}
|
||||
|
||||
public virtual void Update(IGuiContext context, float deltaSeconds) { }
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
if (BackgroundRegion != null)
|
||||
renderer.DrawRegion(BackgroundRegion, BoundingRectangle, BackgroundColor);
|
||||
else if (BackgroundColor != Color.Transparent)
|
||||
renderer.FillRectangle(BoundingRectangle, BackgroundColor);
|
||||
|
||||
if (BorderThickness != 0)
|
||||
renderer.DrawRectangle(BoundingRectangle, BorderColor, BorderThickness);
|
||||
|
||||
// handy debug rectangles
|
||||
//renderer.DrawRectangle(ContentRectangle, Color.Magenta);
|
||||
//renderer.DrawRectangle(BoundingRectangle, Color.Lime);
|
||||
}
|
||||
|
||||
public bool HasParent(Control control)
|
||||
{
|
||||
return Parent != null && (Parent == control || Parent.HasParent(control));
|
||||
}
|
||||
|
||||
protected TextInfo GetTextInfo(IGuiContext context, string text, Rectangle targetRectangle, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
|
||||
{
|
||||
var font = Font ?? context.DefaultFont;
|
||||
var textSize = (Size)font.GetStringRectangle(text ?? string.Empty, Vector2.Zero).Size;
|
||||
var destinationRectangle = LayoutHelper.AlignRectangle(horizontalAlignment, verticalAlignment, textSize, targetRectangle);
|
||||
var textPosition = destinationRectangle.Location.ToVector2();
|
||||
var textInfo = new TextInfo(text, font, textPosition, textSize, TextColor, targetRectangle);
|
||||
return textInfo;
|
||||
}
|
||||
|
||||
public struct TextInfo
|
||||
{
|
||||
public TextInfo(string text, BitmapFont font, Vector2 position, Size size, Color color, Rectangle? clippingRectangle)
|
||||
{
|
||||
Text = text ?? string.Empty;
|
||||
Font = font;
|
||||
Size = size;
|
||||
Color = color;
|
||||
ClippingRectangle = clippingRectangle;
|
||||
Position = position;
|
||||
}
|
||||
|
||||
public string Text;
|
||||
public BitmapFont Font;
|
||||
public Size Size;
|
||||
public Color Color;
|
||||
public Rectangle? ClippingRectangle;
|
||||
public Vector2 Position;
|
||||
}
|
||||
|
||||
public Dictionary<string, object> AttachedProperties { get; } = new Dictionary<string, object>();
|
||||
|
||||
public object GetAttachedProperty(string name)
|
||||
{
|
||||
return AttachedProperties.TryGetValue(name, out var value) ? value : null;
|
||||
}
|
||||
|
||||
public void SetAttachedProperty(string name, object value)
|
||||
{
|
||||
AttachedProperties[name] = value;
|
||||
}
|
||||
|
||||
public virtual Type GetAttachedPropertyType(string propertyName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class ControlCollection : ElementCollection<Control, Control>
|
||||
{
|
||||
public ControlCollection()
|
||||
: base(null)
|
||||
{
|
||||
}
|
||||
|
||||
public ControlCollection(Control parent)
|
||||
: base(parent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
//public class Dialog : LayoutControl
|
||||
//{
|
||||
// public Dialog()
|
||||
// {
|
||||
// HorizontalAlignment = HorizontalAlignment.Centre;
|
||||
// VerticalAlignment = VerticalAlignment.Centre;
|
||||
// }
|
||||
|
||||
// public Thickness Padding { get; set; }
|
||||
// public Screen Owner { get; private set; }
|
||||
|
||||
// public void Show(Screen owner)
|
||||
// {
|
||||
// Owner = owner;
|
||||
// Owner.Controls.Add(this);
|
||||
// }
|
||||
|
||||
// public void Hide()
|
||||
// {
|
||||
// Owner.Controls.Remove(this);
|
||||
// }
|
||||
|
||||
// protected override Size2 CalculateDesiredSize(IGuiContext context, Size2 availableSize)
|
||||
// {
|
||||
// var sizes = Items.Select(control => LayoutHelper.GetSizeWithMargins(control, context, availableSize)).ToArray();
|
||||
// var width = sizes.Max(s => s.Width);
|
||||
// var height = sizes.Max(s => s.Height);
|
||||
// return new Size2(width, height) + Padding.Size;
|
||||
// }
|
||||
|
||||
// public override void Layout(IGuiContext context, RectangleF rectangle)
|
||||
// {
|
||||
// foreach (var control in Items)
|
||||
// PlaceControl(context, control, Padding.Left, Padding.Top, Width - Padding.Size.Width, Height - Padding.Size.Height);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public enum Dock
|
||||
{
|
||||
Left, Right, Top, Bottom
|
||||
}
|
||||
|
||||
public class DockPanel : LayoutControl
|
||||
{
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
var size = new Size();
|
||||
|
||||
for (var i = 0; i < Items.Count; i++)
|
||||
{
|
||||
var control = Items[i];
|
||||
var actualSize = control.CalculateActualSize(context);
|
||||
|
||||
if (LastChildFill && i == Items.Count - 1)
|
||||
{
|
||||
size.Width += actualSize.Width;
|
||||
size.Height += actualSize.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
var dock = control.GetAttachedProperty(DockProperty) as Dock? ?? Dock.Left;
|
||||
|
||||
switch (dock)
|
||||
{
|
||||
case Dock.Left:
|
||||
case Dock.Right:
|
||||
size.Width += actualSize.Width;
|
||||
break;
|
||||
case Dock.Top:
|
||||
case Dock.Bottom:
|
||||
size.Height += actualSize.Height;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
protected override void Layout(IGuiContext context, Rectangle rectangle)
|
||||
{
|
||||
for (var i = 0; i < Items.Count; i++)
|
||||
{
|
||||
var control = Items[i];
|
||||
|
||||
if (LastChildFill && i == Items.Count - 1)
|
||||
{
|
||||
PlaceControl(context, control, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
var actualSize = control.CalculateActualSize(context);
|
||||
var dock = control.GetAttachedProperty(DockProperty) as Dock? ?? Dock.Left;
|
||||
|
||||
switch (dock)
|
||||
{
|
||||
case Dock.Left:
|
||||
PlaceControl(context, control, rectangle.Left, rectangle.Top, actualSize.Width, rectangle.Height);
|
||||
rectangle.X += actualSize.Width;
|
||||
rectangle.Width -= actualSize.Width;
|
||||
break;
|
||||
case Dock.Right:
|
||||
PlaceControl(context, control, rectangle.Right - actualSize.Width, rectangle.Top, actualSize.Width, rectangle.Height);
|
||||
rectangle.Width -= actualSize.Width;
|
||||
break;
|
||||
case Dock.Top:
|
||||
PlaceControl(context, control, rectangle.Left, rectangle.Top, rectangle.Width, actualSize.Height);
|
||||
rectangle.Y += actualSize.Height;
|
||||
rectangle.Height -= actualSize.Height;
|
||||
break;
|
||||
case Dock.Bottom:
|
||||
PlaceControl(context, control, rectangle.Left, rectangle.Bottom - actualSize.Height, rectangle.Width, actualSize.Height);
|
||||
rectangle.Height -= actualSize.Height;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public const string DockProperty = "Dock";
|
||||
|
||||
public override Type GetAttachedPropertyType(string propertyName)
|
||||
{
|
||||
if (string.Equals(DockProperty, propertyName, StringComparison.OrdinalIgnoreCase))
|
||||
return typeof(Dock);
|
||||
|
||||
return base.GetAttachedPropertyType(propertyName);
|
||||
}
|
||||
|
||||
public bool LastChildFill { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using System.Linq;
|
||||
using MonoGame.Extended.Input.InputListeners;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
//public class Form : StackPanel
|
||||
//{
|
||||
// public Form()
|
||||
// {
|
||||
// }
|
||||
|
||||
// public override bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args)
|
||||
// {
|
||||
// if (args.Key == Keys.Tab)
|
||||
// {
|
||||
// var controls = FindControls<Control>();
|
||||
// var index = controls.IndexOf(context.FocusedControl);
|
||||
// if (index > -1)
|
||||
// {
|
||||
// index++;
|
||||
// if (index >= controls.Count) index = 0;
|
||||
// context.SetFocus(controls[index]);
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (args.Key == Keys.Enter)
|
||||
// {
|
||||
// var controls = FindControls<Submit>();
|
||||
// if (controls.Count > 0)
|
||||
// {
|
||||
// var submit = controls.FirstOrDefault();
|
||||
// submit.TriggerClicked();
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return base.OnKeyPressed(context, args);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public abstract class ItemsControl : Control
|
||||
{
|
||||
protected ItemsControl()
|
||||
{
|
||||
Items = new ControlCollection(this);
|
||||
//{
|
||||
// ItemAdded = x => UpdateRootIsLayoutRequired(),
|
||||
// ItemRemoved = x => UpdateRootIsLayoutRequired()
|
||||
//};
|
||||
}
|
||||
|
||||
public override IEnumerable<Control> Children => Items;
|
||||
|
||||
public ControlCollection Items { get; }
|
||||
|
||||
///// <summary>
|
||||
///// Recursive Method to find the root element and update the IsLayoutRequired property. So that the screen knows that something in the controls
|
||||
///// have had a change to their layout. Also, it will reset the size of the element so that it can get a clean build so that the background patches
|
||||
///// can be rendered with the updates.
|
||||
///// </summary>
|
||||
//private void UpdateRootIsLayoutRequired()
|
||||
//{
|
||||
// var parent = Parent as ItemsControl;
|
||||
|
||||
// if (parent == null)
|
||||
// IsLayoutRequired = true;
|
||||
// else
|
||||
// parent.UpdateRootIsLayoutRequired();
|
||||
|
||||
// Size = Size2.Empty;
|
||||
//}
|
||||
|
||||
//protected List<T> FindControls<T>()
|
||||
// where T : Control
|
||||
//{
|
||||
// return FindControls<T>(Items);
|
||||
//}
|
||||
|
||||
//protected List<T> FindControls<T>(ControlCollection controls)
|
||||
// where T : Control
|
||||
//{
|
||||
// var results = new List<T>();
|
||||
// foreach (var control in controls)
|
||||
// {
|
||||
// if (control is T)
|
||||
// results.Add(control as T);
|
||||
|
||||
// var itemsControl = control as ItemsControl;
|
||||
|
||||
// if (itemsControl != null && itemsControl.Items.Any())
|
||||
// results = results.Concat(FindControls<T>(itemsControl.Items)).ToList();
|
||||
// }
|
||||
// return results;
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class Label : ContentControl
|
||||
{
|
||||
public Label()
|
||||
{
|
||||
}
|
||||
|
||||
public Label(string text = null)
|
||||
{
|
||||
Content = text ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public abstract class LayoutControl : ItemsControl
|
||||
{
|
||||
protected LayoutControl()
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
VerticalAlignment = VerticalAlignment.Stretch;
|
||||
BackgroundColor = Color.Transparent;
|
||||
}
|
||||
|
||||
private bool _isLayoutValid;
|
||||
|
||||
public override void InvalidateMeasure()
|
||||
{
|
||||
base.InvalidateMeasure();
|
||||
_isLayoutValid = false;
|
||||
}
|
||||
|
||||
public override void Update(IGuiContext context, float deltaSeconds)
|
||||
{
|
||||
base.Update(context, deltaSeconds);
|
||||
|
||||
if (!_isLayoutValid)
|
||||
{
|
||||
Layout(context, new Rectangle(Padding.Left, Padding.Top, ContentRectangle.Width, ContentRectangle.Height));
|
||||
_isLayoutValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void Layout(IGuiContext context, Rectangle rectangle);
|
||||
|
||||
protected static void PlaceControl(IGuiContext context, Control control, float x, float y, float width, float height)
|
||||
{
|
||||
LayoutHelper.PlaceControl(context, control, x, y, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class ListBox : SelectorControl
|
||||
{
|
||||
public ListBox()
|
||||
{
|
||||
}
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
var width = 0;
|
||||
var height = 0;
|
||||
|
||||
foreach (var item in Items)
|
||||
{
|
||||
var itemSize = GetItemSize(context, item);
|
||||
|
||||
if (itemSize.Width > width)
|
||||
width = itemSize.Width;
|
||||
|
||||
height += itemSize.Height;
|
||||
}
|
||||
|
||||
return new Size(width + ClipPadding.Width, height + ClipPadding.Height);
|
||||
}
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
base.Draw(context, renderer, deltaSeconds);
|
||||
|
||||
ScrollIntoView(context);
|
||||
DrawItemList(context, renderer);
|
||||
}
|
||||
|
||||
protected override Rectangle GetListAreaRectangle(IGuiContext context)
|
||||
{
|
||||
return ContentRectangle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Graphics;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class ProgressBar : Control
|
||||
{
|
||||
public ProgressBar()
|
||||
{
|
||||
}
|
||||
|
||||
private float _progress = 1.0f;
|
||||
public float Progress
|
||||
{
|
||||
get { return _progress; }
|
||||
set
|
||||
{
|
||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||
if(_progress != value)
|
||||
{
|
||||
_progress = value;
|
||||
ProgressChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Texture2DRegion BarRegion { get; set; }
|
||||
public Color BarColor { get; set; } = Color.White;
|
||||
|
||||
public event EventHandler ProgressChanged;
|
||||
|
||||
public override IEnumerable<Control> Children { get; } = Enumerable.Empty<Control>();
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
return new Size(5, 5);
|
||||
}
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
base.Draw(context, renderer, deltaSeconds);
|
||||
|
||||
var boundingRectangle = ContentRectangle;
|
||||
var clippingRectangle = new Rectangle(boundingRectangle.X, boundingRectangle.Y, (int)(boundingRectangle.Width * Progress), boundingRectangle.Height);
|
||||
|
||||
if (BarRegion != null)
|
||||
renderer.DrawRegion(BarRegion, BoundingRectangle, BarColor, clippingRectangle);
|
||||
else
|
||||
renderer.FillRectangle(BoundingRectangle, BarColor, clippingRectangle);
|
||||
}
|
||||
|
||||
//protected override void DrawBackground(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
//{
|
||||
// base.DrawBackground(context, renderer, deltaSeconds);
|
||||
|
||||
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using MonoGame.Extended.Input.InputListeners;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public abstract class SelectorControl : Control
|
||||
{
|
||||
protected SelectorControl()
|
||||
{
|
||||
}
|
||||
|
||||
private int _selectedIndex = -1;
|
||||
public virtual int SelectedIndex
|
||||
{
|
||||
get { return _selectedIndex; }
|
||||
set
|
||||
{
|
||||
if (_selectedIndex != value)
|
||||
{
|
||||
_selectedIndex = value;
|
||||
SelectedIndexChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Control> Children => Items.OfType<Control>();
|
||||
|
||||
public virtual List<object> Items { get; } = new List<object>();
|
||||
public virtual Color SelectedTextColor { get; set; } = Color.White;
|
||||
public virtual Color SelectedItemColor { get; set; } = Color.CornflowerBlue;
|
||||
public virtual Thickness ItemPadding { get; set; } = new Thickness(4, 2);
|
||||
public virtual string NameProperty { get; set; }
|
||||
|
||||
public event EventHandler SelectedIndexChanged;
|
||||
|
||||
protected int FirstIndex;
|
||||
|
||||
public object SelectedItem
|
||||
{
|
||||
get { return SelectedIndex >= 0 && SelectedIndex <= Items.Count - 1 ? Items[SelectedIndex] : null; }
|
||||
set { SelectedIndex = Items.IndexOf(value); }
|
||||
}
|
||||
|
||||
public override bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args)
|
||||
{
|
||||
if (args.Key == Keys.Down) ScrollDown();
|
||||
if (args.Key == Keys.Up) ScrollUp();
|
||||
|
||||
return base.OnKeyPressed(context, args);
|
||||
}
|
||||
|
||||
public override void OnScrolled(int delta)
|
||||
{
|
||||
base.OnScrolled(delta);
|
||||
|
||||
if (delta < 0) ScrollDown();
|
||||
if (delta > 0) ScrollUp();
|
||||
}
|
||||
|
||||
private void ScrollDown()
|
||||
{
|
||||
if (SelectedIndex < Items.Count - 1)
|
||||
SelectedIndex++;
|
||||
}
|
||||
|
||||
private void ScrollUp()
|
||||
{
|
||||
if (SelectedIndex > 0)
|
||||
SelectedIndex--;
|
||||
}
|
||||
|
||||
public override bool OnPointerDown(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
var contentRectangle = GetListAreaRectangle(context);
|
||||
|
||||
for (var i = FirstIndex; i < Items.Count; i++)
|
||||
{
|
||||
var itemRectangle = GetItemRectangle(context, i - FirstIndex, contentRectangle);
|
||||
|
||||
if (itemRectangle.Contains(args.Position))
|
||||
{
|
||||
SelectedIndex = i;
|
||||
OnItemClicked(context, args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnPointerDown(context, args);
|
||||
}
|
||||
|
||||
protected virtual void OnItemClicked(IGuiContext context, PointerEventArgs args) { }
|
||||
|
||||
protected TextInfo GetItemTextInfo(IGuiContext context, Rectangle itemRectangle, object item)
|
||||
{
|
||||
var textRectangle = new Rectangle(itemRectangle.X + ItemPadding.Left, itemRectangle.Y + ItemPadding.Top,
|
||||
itemRectangle.Width - ItemPadding.Right, itemRectangle.Height - ItemPadding.Bottom);
|
||||
var itemTextInfo = GetTextInfo(context, GetItemName(item), textRectangle, HorizontalTextAlignment, VerticalTextAlignment);
|
||||
return itemTextInfo;
|
||||
}
|
||||
|
||||
private string GetItemName(object item)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
if (NameProperty != null)
|
||||
{
|
||||
return item.GetType()
|
||||
.GetRuntimeProperty(NameProperty)
|
||||
.GetValue(item)
|
||||
?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
return item.ToString();
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
protected Rectangle GetItemRectangle(IGuiContext context, int index, Rectangle contentRectangle)
|
||||
{
|
||||
var font = Font ?? context.DefaultFont;
|
||||
var itemHeight = font.LineHeight + ItemPadding.Top + ItemPadding.Bottom;
|
||||
return new Rectangle(contentRectangle.X, contentRectangle.Y + itemHeight * index, contentRectangle.Width, itemHeight);
|
||||
}
|
||||
|
||||
protected void ScrollIntoView(IGuiContext context)
|
||||
{
|
||||
var contentRectangle = GetListAreaRectangle(context);
|
||||
var selectedItemRectangle = GetItemRectangle(context, SelectedIndex - FirstIndex, contentRectangle);
|
||||
|
||||
if (selectedItemRectangle.Bottom > ClippingRectangle.Bottom)
|
||||
FirstIndex++;
|
||||
|
||||
if (selectedItemRectangle.Top < ClippingRectangle.Top && FirstIndex > 0)
|
||||
FirstIndex--;
|
||||
}
|
||||
|
||||
protected Size GetItemSize(IGuiContext context, object item)
|
||||
{
|
||||
var text = GetItemName(item);
|
||||
var font = Font ?? context.DefaultFont;
|
||||
var textSize = (Size)font.MeasureString(text ?? string.Empty);
|
||||
var itemWidth = textSize.Width + ItemPadding.Width;
|
||||
var itemHeight = textSize.Height + ItemPadding.Height;
|
||||
return new Size(itemWidth, itemHeight);
|
||||
}
|
||||
|
||||
protected abstract Rectangle GetListAreaRectangle(IGuiContext context);
|
||||
|
||||
protected void DrawItemList(IGuiContext context, IGuiRenderer renderer)
|
||||
{
|
||||
var listRectangle = GetListAreaRectangle(context);
|
||||
|
||||
for (var i = FirstIndex; i < Items.Count; i++)
|
||||
{
|
||||
var item = Items[i];
|
||||
var itemRectangle = GetItemRectangle(context, i - FirstIndex, listRectangle);
|
||||
var itemTextInfo = GetItemTextInfo(context, itemRectangle, item);
|
||||
var textColor = i == SelectedIndex ? SelectedTextColor : itemTextInfo.Color;
|
||||
|
||||
if (SelectedIndex == i)
|
||||
renderer.FillRectangle(itemRectangle, SelectedItemColor, listRectangle);
|
||||
|
||||
renderer.DrawText(itemTextInfo.Font, itemTextInfo.Text, itemTextInfo.Position + TextOffset, textColor, itemTextInfo.ClippingRectangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class StackPanel : LayoutControl
|
||||
{
|
||||
public StackPanel()
|
||||
{
|
||||
}
|
||||
|
||||
public Orientation Orientation { get; set; } = Orientation.Vertical;
|
||||
public int Spacing { get; set; }
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
var width = 0;
|
||||
var height = 0;
|
||||
|
||||
foreach (var control in Items)
|
||||
{
|
||||
var actualSize = control.CalculateActualSize(context);
|
||||
|
||||
switch (Orientation)
|
||||
{
|
||||
case Orientation.Horizontal:
|
||||
width += actualSize.Width;
|
||||
height = actualSize.Height > height ? actualSize.Height : height;
|
||||
break;
|
||||
case Orientation.Vertical:
|
||||
width = actualSize.Width > width ? actualSize.Width : width;
|
||||
height += actualSize.Height;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"Unexpected orientation {Orientation}");
|
||||
}
|
||||
}
|
||||
|
||||
width += Orientation == Orientation.Horizontal ? (Items.Count - 1) * Spacing : 0;
|
||||
height += Orientation == Orientation.Vertical ? (Items.Count - 1) * Spacing : 0;
|
||||
|
||||
return new Size(width, height);
|
||||
}
|
||||
|
||||
protected override void Layout(IGuiContext context, Rectangle rectangle)
|
||||
{
|
||||
foreach (var control in Items)
|
||||
{
|
||||
var actualSize = control.CalculateActualSize(context);
|
||||
|
||||
switch (Orientation)
|
||||
{
|
||||
case Orientation.Vertical:
|
||||
PlaceControl(context, control, rectangle.X, rectangle.Y, rectangle.Width, actualSize.Height);
|
||||
rectangle.Y += actualSize.Height + Spacing;
|
||||
rectangle.Height -= actualSize.Height;
|
||||
break;
|
||||
case Orientation.Horizontal:
|
||||
PlaceControl(context, control, rectangle.X, rectangle.Y, actualSize.Width, rectangle.Height);
|
||||
rectangle.X += actualSize.Width + Spacing;
|
||||
rectangle.Width -= actualSize.Width;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"Unexpected orientation {Orientation}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,331 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using MonoGame.Extended.Input.InputListeners;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public sealed class TextBox : Control
|
||||
{
|
||||
public TextBox(string text = null)
|
||||
{
|
||||
Text = text ?? string.Empty;
|
||||
HorizontalTextAlignment = HorizontalAlignment.Left;
|
||||
}
|
||||
|
||||
public TextBox()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public int SelectionStart { get; set; }
|
||||
public char? PasswordCharacter { get; set; }
|
||||
|
||||
private string _text;
|
||||
|
||||
public string Text
|
||||
{
|
||||
get { return _text; }
|
||||
set
|
||||
{
|
||||
if (_text != value)
|
||||
{
|
||||
_text = value;
|
||||
OnTextChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextChanged()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Text) && SelectionStart > Text.Length)
|
||||
SelectionStart = Text.Length;
|
||||
|
||||
TextChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public event EventHandler TextChanged;
|
||||
|
||||
public override IEnumerable<Control> Children { get; } = Enumerable.Empty<Control>();
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
var font = Font ?? context.DefaultFont;
|
||||
var stringSize = (Size) font.MeasureString(Text ?? string.Empty);
|
||||
return new Size(stringSize.Width,
|
||||
stringSize.Height < font.LineHeight ? font.LineHeight : stringSize.Height);
|
||||
}
|
||||
|
||||
//protected override Size2 CalculateDesiredSize(IGuiContext context, Size2 availableSize)
|
||||
//{
|
||||
// var font = Font ?? context.DefaultFont;
|
||||
// return new Size2(Width + Padding.Left + Padding.Right, (Height <= 0.0f ? font.LineHeight + 2 : Height) + Padding.Top + Padding.Bottom);
|
||||
//}
|
||||
|
||||
public override bool OnPointerDown(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
SelectionStart = FindNearestGlyphIndex(context, args.Position);
|
||||
_isCaretVisible = true;
|
||||
|
||||
//_selectionIndexes.Clear();
|
||||
//_selectionIndexes.Push(SelectionStart);
|
||||
//_startSelectionBox = Text.Length > 0;
|
||||
|
||||
return base.OnPointerDown(context, args);
|
||||
}
|
||||
|
||||
//public override bool OnPointerMove(IGuiContext context, PointerEventArgs args)
|
||||
//{
|
||||
// if (_startSelectionBox)
|
||||
// {
|
||||
// var selection = FindNearestGlyphIndex(context, args.Position);
|
||||
// if (selection != _selectionIndexes.Peek())
|
||||
// {
|
||||
// if (_selectionIndexes.Count == 1)
|
||||
// {
|
||||
// _selectionIndexes.Push(selection);
|
||||
// }
|
||||
// else if (_selectionIndexes.Last() < _selectionIndexes.Peek())
|
||||
// {
|
||||
// if (selection > _selectionIndexes.Peek()) _selectionIndexes.Pop();
|
||||
// else _selectionIndexes.Push(selection);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (selection < _selectionIndexes.Peek()) _selectionIndexes.Pop();
|
||||
// else _selectionIndexes.Push(selection);
|
||||
// }
|
||||
// SelectionStart = selection;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return base.OnPointerMove(context, args);
|
||||
//}
|
||||
|
||||
//public override bool OnPointerLeave(IGuiContext context, PointerEventArgs args)
|
||||
//{
|
||||
// _startSelectionBox = false;
|
||||
|
||||
// return base.OnPointerLeave(context, args);
|
||||
//}
|
||||
|
||||
//public override bool OnPointerUp(IGuiContext context, PointerEventArgs args)
|
||||
//{
|
||||
// _startSelectionBox = false;
|
||||
|
||||
// return base.OnPointerUp(context, args);
|
||||
//}
|
||||
|
||||
private int FindNearestGlyphIndex(IGuiContext context, Point position)
|
||||
{
|
||||
var font = Font ?? context.DefaultFont;
|
||||
var textInfo = GetTextInfo(context, Text, ContentRectangle, HorizontalTextAlignment, VerticalTextAlignment);
|
||||
var i = 0;
|
||||
|
||||
foreach (var glyph in font.GetGlyphs(textInfo.Text, textInfo.Position))
|
||||
{
|
||||
var fontRegionWidth = glyph.Character?.TextureRegion?.Width ?? 0;
|
||||
var glyphMiddle = (int) (glyph.Position.X + fontRegionWidth * 0.5f);
|
||||
|
||||
if (position.X >= glyphMiddle)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public override bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args)
|
||||
{
|
||||
switch (args.Key)
|
||||
{
|
||||
case Keys.Tab:
|
||||
case Keys.Enter:
|
||||
return true;
|
||||
case Keys.Back:
|
||||
if (Text.Length > 0)
|
||||
{
|
||||
if (SelectionStart > 0) // && _selectionIndexes.Count <= 1)
|
||||
{
|
||||
SelectionStart--;
|
||||
Text = Text.Remove(SelectionStart, 1);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// var start = MathHelper.Min(_selectionIndexes.Last(), _selectionIndexes.Peek());
|
||||
// var end = MathHelper.Max(_selectionIndexes.Last(), _selectionIndexes.Peek());
|
||||
// Text = Text.Remove(start, end - start);
|
||||
|
||||
// _selectionIndexes.Clear();
|
||||
//}
|
||||
}
|
||||
|
||||
break;
|
||||
case Keys.Delete:
|
||||
if (SelectionStart < Text.Length) // && _selectionIndexes.Count <= 1)
|
||||
{
|
||||
Text = Text.Remove(SelectionStart, 1);
|
||||
}
|
||||
//else if (_selectionIndexes.Count > 1)
|
||||
//{
|
||||
// var start = MathHelper.Min(_selectionIndexes.Last(), _selectionIndexes.Peek());
|
||||
// var end = MathHelper.Max(_selectionIndexes.Last(), _selectionIndexes.Peek());
|
||||
// Text = Text.Remove(start, end - start);
|
||||
// SelectionStart = 0; // yeah, nah.
|
||||
|
||||
// _selectionIndexes.Clear();
|
||||
//}
|
||||
break;
|
||||
case Keys.Left:
|
||||
if (SelectionStart > 0)
|
||||
{
|
||||
//if (_selectionIndexes.Count > 1)
|
||||
//{
|
||||
// if (_selectionIndexes.Last() < SelectionStart) SelectionStart = _selectionIndexes.Last();
|
||||
// _selectionIndexes.Clear();
|
||||
//}
|
||||
//else
|
||||
{
|
||||
SelectionStart--;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case Keys.Right:
|
||||
if (SelectionStart < Text.Length)
|
||||
{
|
||||
//if (_selectionIndexes.Count > 1)
|
||||
//{
|
||||
// if (_selectionIndexes.Last() > SelectionStart) SelectionStart = _selectionIndexes.Last();
|
||||
// _selectionIndexes.Clear();
|
||||
//}
|
||||
//else
|
||||
{
|
||||
SelectionStart++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case Keys.Home:
|
||||
SelectionStart = 0;
|
||||
//_selectionIndexes.Clear();
|
||||
break;
|
||||
case Keys.End:
|
||||
SelectionStart = Text.Length;
|
||||
//_selectionIndexes.Clear();
|
||||
break;
|
||||
default:
|
||||
if (args.Character != null)
|
||||
{
|
||||
//if (_selectionIndexes.Count > 1)
|
||||
//{
|
||||
// var start = MathHelper.Min(_selectionIndexes.Last(), _selectionIndexes.Peek());
|
||||
// var end = MathHelper.Max(_selectionIndexes.Last(), _selectionIndexes.Peek());
|
||||
// Text = Text.Remove(start, end - start);
|
||||
|
||||
// _selectionIndexes.Clear();
|
||||
//}
|
||||
|
||||
Text = Text.Insert(SelectionStart, args.Character.ToString());
|
||||
SelectionStart++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_isCaretVisible = true;
|
||||
return base.OnKeyPressed(context, args);
|
||||
}
|
||||
|
||||
private const float _caretBlinkRate = 0.53f;
|
||||
private float _nextCaretBlink = _caretBlinkRate;
|
||||
private bool _isCaretVisible = true;
|
||||
|
||||
//private bool _startSelectionBox = false;
|
||||
//private Stack<int> _selectionIndexes = new Stack<int>();
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
base.Draw(context, renderer, deltaSeconds);
|
||||
|
||||
var text = PasswordCharacter.HasValue ? new string(PasswordCharacter.Value, Text.Length) : Text;
|
||||
var textInfo = GetTextInfo(context, text, ContentRectangle, HorizontalTextAlignment, VerticalTextAlignment);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(textInfo.Text))
|
||||
renderer.DrawText(textInfo.Font, textInfo.Text, textInfo.Position + TextOffset, textInfo.Color,
|
||||
textInfo.ClippingRectangle);
|
||||
|
||||
if (IsFocused)
|
||||
{
|
||||
var caretRectangle = GetCaretRectangle(textInfo, SelectionStart);
|
||||
|
||||
if (_isCaretVisible)
|
||||
renderer.DrawRectangle(caretRectangle, TextColor);
|
||||
|
||||
_nextCaretBlink -= deltaSeconds;
|
||||
|
||||
if (_nextCaretBlink <= 0)
|
||||
{
|
||||
_isCaretVisible = !_isCaretVisible;
|
||||
_nextCaretBlink = _caretBlinkRate;
|
||||
}
|
||||
|
||||
//if (_selectionIndexes.Count > 1)
|
||||
//{
|
||||
// var start = 0;
|
||||
// var end = 0;
|
||||
// var point = Vector2.Zero;
|
||||
// if (_selectionIndexes.Last() > _selectionIndexes.Peek())
|
||||
// {
|
||||
// start = _selectionIndexes.Peek();
|
||||
// end = _selectionIndexes.Last();
|
||||
// point = caretRectangle.Position;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// start = _selectionIndexes.Last();
|
||||
// end = _selectionIndexes.Peek();
|
||||
// point = GetCaretRectangle(textInfo, start).Position;
|
||||
// }
|
||||
// var selectionRectangle = textInfo.Font.GetStringRectangle(textInfo.Text.Substring(start, end - start), point);
|
||||
|
||||
// renderer.FillRectangle((Rectangle)selectionRectangle, Color.Black * 0.25f);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//protected override string CreateBoxText(string text, BitmapFont font, float width)
|
||||
//{
|
||||
// return text;
|
||||
//}
|
||||
|
||||
private Rectangle GetCaretRectangle(TextInfo textInfo, int index)
|
||||
{
|
||||
var caretRectangle = textInfo.Font.GetStringRectangle(textInfo.Text.Substring(0, index), textInfo.Position);
|
||||
|
||||
// TODO: Finish the caret position stuff when it's outside the clipping rectangle
|
||||
if (caretRectangle.Right > ClippingRectangle.Right)
|
||||
textInfo.Position.X -= caretRectangle.Right - ClippingRectangle.Right;
|
||||
|
||||
caretRectangle.X = caretRectangle.Right < ClippingRectangle.Right
|
||||
? caretRectangle.Right
|
||||
: ClippingRectangle.Right;
|
||||
caretRectangle.Width = 1;
|
||||
|
||||
if (caretRectangle.Left < ClippingRectangle.Left)
|
||||
{
|
||||
textInfo.Position.X += ClippingRectangle.Left - caretRectangle.Left;
|
||||
caretRectangle.X = ClippingRectangle.Left;
|
||||
}
|
||||
|
||||
return (Rectangle) caretRectangle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,328 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using MonoGame.Extended.Input.InputListeners;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class TextBox2 : Control
|
||||
{
|
||||
public TextBox2()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public TextBox2(string text)
|
||||
{
|
||||
Text = text ?? string.Empty;
|
||||
HorizontalTextAlignment = HorizontalAlignment.Left;
|
||||
VerticalTextAlignment = VerticalAlignment.Top;
|
||||
}
|
||||
|
||||
|
||||
private const float _caretBlinkRate = 0.53f;
|
||||
private float _nextCaretBlink = _caretBlinkRate;
|
||||
private bool _isCaretVisible = true;
|
||||
|
||||
private readonly List<StringBuilder> _lines = new List<StringBuilder>();
|
||||
public string Text
|
||||
{
|
||||
get => string.Concat(_lines.SelectMany(s => $"{s}\n"));
|
||||
set
|
||||
{
|
||||
_lines.Clear();
|
||||
|
||||
var line = new StringBuilder();
|
||||
|
||||
for (var i = 0; i < value.Length; i++)
|
||||
{
|
||||
var c = value[i];
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
_lines.Add(line);
|
||||
line = new StringBuilder();
|
||||
}
|
||||
else if(c != '\r')
|
||||
{
|
||||
line.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
_lines.Add(line);
|
||||
}
|
||||
}
|
||||
|
||||
public int CaretIndex => ColumnIndex * LineIndex + ColumnIndex;
|
||||
public int LineIndex { get; set; }
|
||||
public int ColumnIndex { get; set; }
|
||||
public int TabStops { get; set; } = 4;
|
||||
|
||||
public override IEnumerable<Control> Children => Enumerable.Empty<Control>();
|
||||
|
||||
public string GetLineText(int lineIndex) => _lines[lineIndex].ToString();
|
||||
public int GetLineLength(int lineIndex) => _lines[lineIndex].Length;
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
var font = Font ?? context.DefaultFont;
|
||||
var stringSize = (Size)font.MeasureString(Text ?? string.Empty);
|
||||
return new Size(stringSize.Width, stringSize.Height < font.LineHeight ? font.LineHeight : stringSize.Height);
|
||||
}
|
||||
|
||||
public override bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args)
|
||||
{
|
||||
switch (args.Key)
|
||||
{
|
||||
case Keys.Tab:
|
||||
Tab();
|
||||
break;
|
||||
case Keys.Back:
|
||||
Backspace();
|
||||
break;
|
||||
case Keys.Delete:
|
||||
Delete();
|
||||
break;
|
||||
case Keys.Left:
|
||||
Left();
|
||||
break;
|
||||
case Keys.Right:
|
||||
Right();
|
||||
break;
|
||||
case Keys.Up:
|
||||
Up();
|
||||
break;
|
||||
case Keys.Down:
|
||||
Down();
|
||||
break;
|
||||
case Keys.Home:
|
||||
Home();
|
||||
break;
|
||||
case Keys.End:
|
||||
End();
|
||||
break;
|
||||
case Keys.Enter:
|
||||
Type('\n');
|
||||
return true;
|
||||
default:
|
||||
if (args.Character.HasValue)
|
||||
Type(args.Character.Value);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_isCaretVisible = true;
|
||||
return base.OnKeyPressed(context, args);
|
||||
}
|
||||
|
||||
public void Type(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
var lineText = GetLineText(LineIndex);
|
||||
var left = lineText.Substring(0, ColumnIndex);
|
||||
var right = lineText.Substring(ColumnIndex);
|
||||
_lines.Insert(LineIndex + 1, new StringBuilder(right));
|
||||
_lines[LineIndex] = new StringBuilder(left);
|
||||
LineIndex++;
|
||||
Home();
|
||||
break;
|
||||
case '\t':
|
||||
Tab();
|
||||
break;
|
||||
default:
|
||||
_lines[LineIndex].Insert(ColumnIndex, c);
|
||||
ColumnIndex++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Backspace()
|
||||
{
|
||||
if (ColumnIndex == 0 && LineIndex > 0)
|
||||
{
|
||||
var topLineLength = GetLineLength(LineIndex - 1);
|
||||
|
||||
if (RemoveLineBreak(LineIndex - 1))
|
||||
{
|
||||
LineIndex--;
|
||||
ColumnIndex = topLineLength;
|
||||
}
|
||||
}
|
||||
else if (Left())
|
||||
{
|
||||
RemoveCharacter(LineIndex, ColumnIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
var lineLength = GetLineLength(LineIndex);
|
||||
|
||||
if (ColumnIndex == lineLength)
|
||||
RemoveLineBreak(LineIndex);
|
||||
else
|
||||
RemoveCharacter(LineIndex, ColumnIndex);
|
||||
}
|
||||
|
||||
public void RemoveCharacter(int lineIndex, int columnIndex)
|
||||
{
|
||||
_lines[lineIndex].Remove(columnIndex, 1);
|
||||
}
|
||||
|
||||
public bool RemoveLineBreak(int lineIndex)
|
||||
{
|
||||
if (lineIndex < _lines.Count - 1)
|
||||
{
|
||||
var topLine = _lines[lineIndex];
|
||||
var bottomLine = _lines[lineIndex + 1];
|
||||
_lines.RemoveAt(lineIndex + 1);
|
||||
topLine.Append(bottomLine);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Home()
|
||||
{
|
||||
ColumnIndex = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool End()
|
||||
{
|
||||
ColumnIndex = GetLineLength(LineIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Up()
|
||||
{
|
||||
if (LineIndex > 0)
|
||||
{
|
||||
LineIndex--;
|
||||
|
||||
if (ColumnIndex > GetLineLength(LineIndex))
|
||||
ColumnIndex = GetLineLength(LineIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Down()
|
||||
{
|
||||
if (LineIndex < _lines.Count - 1)
|
||||
{
|
||||
LineIndex++;
|
||||
|
||||
if (ColumnIndex > GetLineLength(LineIndex))
|
||||
ColumnIndex = GetLineLength(LineIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Left()
|
||||
{
|
||||
if (ColumnIndex == 0)
|
||||
{
|
||||
if (LineIndex == 0)
|
||||
return false;
|
||||
|
||||
LineIndex--;
|
||||
ColumnIndex = GetLineLength(LineIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColumnIndex--;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Right()
|
||||
{
|
||||
if (ColumnIndex == _lines[LineIndex].Length)
|
||||
{
|
||||
if (LineIndex == _lines.Count - 1)
|
||||
return false;
|
||||
|
||||
LineIndex++;
|
||||
ColumnIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ColumnIndex++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Tab()
|
||||
{
|
||||
var spaces = TabStops - ColumnIndex % TabStops;
|
||||
|
||||
for (var s = 0; s < spaces; s++)
|
||||
Type(' ');
|
||||
|
||||
return spaces > 0;
|
||||
}
|
||||
|
||||
public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
{
|
||||
base.Draw(context, renderer, deltaSeconds);
|
||||
|
||||
var text = Text;
|
||||
var textInfo = GetTextInfo(context, text, ContentRectangle, HorizontalTextAlignment, VerticalTextAlignment);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(textInfo.Text))
|
||||
renderer.DrawText(textInfo.Font, textInfo.Text, textInfo.Position + TextOffset, textInfo.Color, textInfo.ClippingRectangle);
|
||||
|
||||
if (IsFocused)
|
||||
{
|
||||
var caretRectangle = GetCaretRectangle(textInfo);
|
||||
|
||||
if (_isCaretVisible)
|
||||
renderer.DrawRectangle(caretRectangle, TextColor);
|
||||
|
||||
_nextCaretBlink -= deltaSeconds;
|
||||
|
||||
if (_nextCaretBlink <= 0)
|
||||
{
|
||||
_isCaretVisible = !_isCaretVisible;
|
||||
_nextCaretBlink = _caretBlinkRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Rectangle GetCaretRectangle(TextInfo textInfo)
|
||||
{
|
||||
var font = textInfo.Font;
|
||||
var text = GetLineText(LineIndex);
|
||||
var offset = new Vector2(0, font.LineHeight * LineIndex);
|
||||
var caretRectangle = font.GetStringRectangle(text.Substring(0, ColumnIndex), textInfo.Position + offset);
|
||||
|
||||
// TODO: Finish the caret position stuff when it's outside the clipping rectangle
|
||||
if (caretRectangle.Right > ClippingRectangle.Right)
|
||||
textInfo.Position.X -= caretRectangle.Right - ClippingRectangle.Right;
|
||||
|
||||
caretRectangle.X = caretRectangle.Right < ClippingRectangle.Right ? caretRectangle.Right : ClippingRectangle.Right;
|
||||
caretRectangle.Width = 1;
|
||||
|
||||
if (caretRectangle.Left < ClippingRectangle.Left)
|
||||
{
|
||||
textInfo.Position.X += ClippingRectangle.Left - caretRectangle.Left;
|
||||
caretRectangle.X = ClippingRectangle.Left;
|
||||
}
|
||||
|
||||
return (Rectangle)caretRectangle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class ToggleButton : Button
|
||||
{
|
||||
public ToggleButton()
|
||||
{
|
||||
}
|
||||
|
||||
public event EventHandler CheckedStateChanged;
|
||||
|
||||
private bool _isChecked;
|
||||
public bool IsChecked
|
||||
{
|
||||
get { return _isChecked; }
|
||||
set
|
||||
{
|
||||
if (_isChecked != value)
|
||||
{
|
||||
_isChecked = value;
|
||||
CheckedStyle?.ApplyIf(this, _isChecked);
|
||||
CheckedStateChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ControlStyle _checkedStyle;
|
||||
public ControlStyle CheckedStyle
|
||||
{
|
||||
get { return _checkedStyle; }
|
||||
set
|
||||
{
|
||||
if (_checkedStyle != value)
|
||||
{
|
||||
_checkedStyle = value;
|
||||
CheckedStyle?.ApplyIf(this, _isChecked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ControlStyle _checkedHoverStyle;
|
||||
public ControlStyle CheckedHoverStyle
|
||||
{
|
||||
get { return _checkedHoverStyle; }
|
||||
set
|
||||
{
|
||||
if (_checkedHoverStyle != value)
|
||||
{
|
||||
_checkedHoverStyle = value;
|
||||
CheckedHoverStyle?.ApplyIf(this, _isChecked && IsHovered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnPointerUp(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
base.OnPointerUp(context, args);
|
||||
|
||||
if (BoundingRectangle.Contains(args.Position))
|
||||
{
|
||||
HoverStyle?.Revert(this);
|
||||
CheckedHoverStyle?.Revert(this);
|
||||
|
||||
IsChecked = !IsChecked;
|
||||
|
||||
if (IsChecked)
|
||||
CheckedHoverStyle?.Apply(this);
|
||||
else
|
||||
HoverStyle?.Apply(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnPointerEnter(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
if (IsChecked)
|
||||
{
|
||||
CheckedHoverStyle?.Apply(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnPointerEnter(context, args);
|
||||
}
|
||||
|
||||
public override bool OnPointerLeave(IGuiContext context, PointerEventArgs args)
|
||||
{
|
||||
if (IsChecked)
|
||||
{
|
||||
CheckedHoverStyle?.Revert(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnPointerLeave(context, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Controls
|
||||
{
|
||||
public class UniformGrid : LayoutControl
|
||||
{
|
||||
public UniformGrid()
|
||||
{
|
||||
}
|
||||
|
||||
public int Columns { get; set; }
|
||||
public int Rows { get; set; }
|
||||
|
||||
public override Size GetContentSize(IGuiContext context)
|
||||
{
|
||||
var columns = Columns == 0 ? (int)Math.Ceiling(Math.Sqrt(Items.Count)) : Columns;
|
||||
var rows = Rows == 0 ? (int)Math.Ceiling((float)Items.Count / columns) : Rows;
|
||||
var sizes = Items
|
||||
.Select(control => control.CalculateActualSize(context))
|
||||
.ToArray();
|
||||
var minCellWidth = sizes.Max(s => s.Width);
|
||||
var minCellHeight = sizes.Max(s => s.Height);
|
||||
return new Size(minCellWidth * columns, minCellHeight * rows);
|
||||
}
|
||||
|
||||
protected override void Layout(IGuiContext context, Rectangle rectangle)
|
||||
{
|
||||
var gridInfo = CalculateGridInfo(context, new Point(rectangle.Width, rectangle.Height));
|
||||
var columnIndex = 0;
|
||||
var rowIndex = 0;
|
||||
var cellWidth = HorizontalAlignment == HorizontalAlignment.Stretch ? gridInfo.MaxCellWidth : gridInfo.MinCellWidth;
|
||||
var cellHeight = VerticalAlignment == VerticalAlignment.Stretch ? gridInfo.MaxCellHeight : gridInfo.MinCellHeight;
|
||||
|
||||
foreach (var control in Items)
|
||||
{
|
||||
var x = columnIndex * cellWidth + rectangle.X;
|
||||
var y = rowIndex * cellHeight + rectangle.Y;
|
||||
|
||||
PlaceControl(context, control, x, y, cellWidth, cellHeight);
|
||||
columnIndex++;
|
||||
|
||||
if (columnIndex > gridInfo.Columns - 1)
|
||||
{
|
||||
columnIndex = 0;
|
||||
rowIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct GridInfo
|
||||
{
|
||||
public float MinCellWidth;
|
||||
public float MinCellHeight;
|
||||
public float MaxCellWidth;
|
||||
public float MaxCellHeight;
|
||||
public float Columns;
|
||||
public float Rows;
|
||||
public SizeF MinCellSize => new SizeF(MinCellWidth * Columns, MinCellHeight * Rows);
|
||||
}
|
||||
|
||||
private GridInfo CalculateGridInfo(IGuiContext context, SizeF availableSize)
|
||||
{
|
||||
var columns = Columns == 0 ? (int)Math.Ceiling(Math.Sqrt(Items.Count)) : Columns;
|
||||
var rows = Rows == 0 ? (int)Math.Ceiling((float)Items.Count / columns) : Rows;
|
||||
var maxCellWidth = availableSize.Width / columns;
|
||||
var maxCellHeight = availableSize.Height / rows;
|
||||
var sizes = Items
|
||||
.Select(control => control.CalculateActualSize(context)) // LayoutHelper.GetSizeWithMargins(control, context, new Size2(maxCellWidth, maxCellHeight)))
|
||||
.ToArray();
|
||||
var maxControlWidth = sizes.Length == 0 ? 0 : sizes.Max(s => s.Width);
|
||||
var maxControlHeight = sizes.Length == 0 ? 0 : sizes.Max(s => s.Height);
|
||||
|
||||
return new GridInfo
|
||||
{
|
||||
Columns = columns,
|
||||
Rows = rows,
|
||||
MinCellWidth = Math.Min(maxControlWidth, maxCellWidth),
|
||||
MinCellHeight = Math.Min(maxControlHeight, maxCellHeight),
|
||||
MaxCellWidth = maxCellWidth,
|
||||
MaxCellHeight = maxCellHeight
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Graphics;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public class Cursor
|
||||
{
|
||||
public Texture2DRegion TextureRegion { get; set; }
|
||||
public Color Color { get; set; } = Color.White;
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Graphics;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public class Binding
|
||||
{
|
||||
public Binding(object viewModel, string viewModelProperty, string viewProperty)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
ViewModelProperty = viewModelProperty;
|
||||
ViewProperty = viewProperty;
|
||||
}
|
||||
|
||||
public object ViewModel { get; }
|
||||
public string ViewModelProperty { get; }
|
||||
public string ViewProperty { get; }
|
||||
}
|
||||
|
||||
public abstract class Element
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Point Position { get; set; }
|
||||
public Point Origin { get; set; }
|
||||
public Color BackgroundColor { get; set; }
|
||||
public Color BorderColor { get; set; } = Color.White;
|
||||
public int BorderThickness { get; set; } = 0;
|
||||
|
||||
private Texture2DRegion _backgroundRegion;
|
||||
public Texture2DRegion BackgroundRegion
|
||||
{
|
||||
get => _backgroundRegion;
|
||||
set
|
||||
{
|
||||
_backgroundRegion = value;
|
||||
|
||||
if (_backgroundRegion != null && BackgroundColor == Color.Transparent)
|
||||
BackgroundColor = Color.White;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Binding> Bindings { get; } = new List<Binding>();
|
||||
|
||||
protected void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
foreach (var binding in Bindings)
|
||||
{
|
||||
if (binding.ViewProperty == propertyName)
|
||||
{
|
||||
var value = GetType()
|
||||
.GetTypeInfo()
|
||||
.GetDeclaredProperty(binding.ViewProperty)
|
||||
.GetValue(this);
|
||||
|
||||
binding.ViewModel
|
||||
.GetType()
|
||||
.GetTypeInfo()
|
||||
.GetDeclaredProperty(binding.ViewModelProperty)
|
||||
.SetValue(binding.ViewModel, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Size _size;
|
||||
public Size Size
|
||||
{
|
||||
get => _size;
|
||||
set
|
||||
{
|
||||
_size = value;
|
||||
OnSizeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnSizeChanged() { }
|
||||
|
||||
public int MinWidth { get; set; }
|
||||
public int MinHeight { get; set; }
|
||||
public int MaxWidth { get; set; } = int.MaxValue;
|
||||
public int MaxHeight { get; set; } = int.MaxValue;
|
||||
|
||||
public int Width
|
||||
{
|
||||
get => Size.Width;
|
||||
set => Size = new Size(value, Size.Height);
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get => Size.Height;
|
||||
set => Size = new Size(Size.Width, value);
|
||||
}
|
||||
|
||||
public Size ActualSize { get; internal set; }
|
||||
|
||||
public abstract void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds);
|
||||
}
|
||||
|
||||
public abstract class Element<TParent> : Element, IRectangular
|
||||
where TParent : IRectangular
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[JsonIgnore]
|
||||
public TParent Parent { get; internal set; }
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[JsonIgnore]
|
||||
public Rectangle BoundingRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
var offset = Point.Zero;
|
||||
|
||||
if (Parent != null)
|
||||
offset = Parent.BoundingRectangle.Location;
|
||||
|
||||
var position = offset + Position - ActualSize * Origin;
|
||||
return new Rectangle(position.X, position.Y, ActualSize.Width, ActualSize.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public abstract class ElementCollection<TChild, TParent> : IList<TChild>
|
||||
where TParent : class, IRectangular
|
||||
where TChild : Element<TParent>
|
||||
{
|
||||
private readonly TParent _parent;
|
||||
private readonly List<TChild> _list = new List<TChild>();
|
||||
|
||||
public Action<TChild> ItemAdded { get; set; }
|
||||
public Action<TChild> ItemRemoved { get; set; }
|
||||
|
||||
protected ElementCollection(TParent parent)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
public IEnumerator<TChild> GetEnumerator()
|
||||
{
|
||||
return _list.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)_list).GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(TChild item)
|
||||
{
|
||||
item.Parent = _parent;
|
||||
_list.Add(item);
|
||||
ItemAdded?.Invoke(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var child in _list)
|
||||
{
|
||||
child.Parent = null;
|
||||
ItemRemoved?.Invoke(child);
|
||||
}
|
||||
|
||||
_list.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(TChild item)
|
||||
{
|
||||
return _list.Contains(item);
|
||||
}
|
||||
|
||||
public void CopyTo(TChild[] array, int arrayIndex)
|
||||
{
|
||||
_list.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public bool Remove(TChild item)
|
||||
{
|
||||
item.Parent = null;
|
||||
ItemRemoved?.Invoke(item);
|
||||
return _list.Remove(item);
|
||||
}
|
||||
|
||||
public int Count => _list.Count;
|
||||
|
||||
public bool IsReadOnly => ((ICollection<Control>)_list).IsReadOnly;
|
||||
|
||||
public int IndexOf(TChild item)
|
||||
{
|
||||
return _list.IndexOf(item);
|
||||
}
|
||||
|
||||
public void Insert(int index, TChild item)
|
||||
{
|
||||
item.Parent = _parent;
|
||||
_list.Insert(index, item);
|
||||
ItemAdded?.Invoke(item);
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
var child = _list[index];
|
||||
child.Parent = null;
|
||||
_list.RemoveAt(index);
|
||||
ItemRemoved?.Invoke(child);
|
||||
}
|
||||
|
||||
public TChild this[int index]
|
||||
{
|
||||
get { return _list[index]; }
|
||||
set { _list[index] = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||
<Description>A GUI system for FNA written from the ground up to make FNA more awesome.</Description>
|
||||
<PackageTags>fna gui</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MonoGame.Extended.Input\FNA.Extended.Input.csproj" />
|
||||
<ProjectReference Include="..\MonoGame.Extended\FNA.Extended.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,82 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using MonoGame.Extended.BitmapFonts;
|
||||
using MonoGame.Extended.Graphics;
|
||||
using MonoGame.Extended.TextureAtlases;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public interface IGuiRenderer
|
||||
{
|
||||
void Begin();
|
||||
void DrawRegion(Texture2DRegion textureRegion, Rectangle rectangle, Color color, Rectangle? clippingRectangle = null);
|
||||
void DrawRegion(Texture2DRegion textureRegion, Vector2 position, Color color, Rectangle? clippingRectangle = null);
|
||||
void DrawText(BitmapFont font, string text, Vector2 position, Color color, Rectangle? clippingRectangle = null);
|
||||
void DrawRectangle(Rectangle rectangle, Color color, float thickness = 1f, Rectangle? clippingRectangle = null);
|
||||
void FillRectangle(Rectangle rectangle, Color color, Rectangle? clippingRectangle = null);
|
||||
void End();
|
||||
}
|
||||
|
||||
public class GuiSpriteBatchRenderer : IGuiRenderer
|
||||
{
|
||||
private readonly Func<Matrix> _getTransformMatrix;
|
||||
private readonly SpriteBatch _spriteBatch;
|
||||
|
||||
public GuiSpriteBatchRenderer(GraphicsDevice graphicsDevice, Func<Matrix> getTransformMatrix)
|
||||
{
|
||||
_getTransformMatrix = getTransformMatrix;
|
||||
_spriteBatch = new SpriteBatch(graphicsDevice);
|
||||
}
|
||||
|
||||
public SpriteSortMode SortMode { get; set; }
|
||||
public BlendState BlendState { get; set; } = BlendState.AlphaBlend;
|
||||
public SamplerState SamplerState { get; set; } = SamplerState.PointClamp;
|
||||
public DepthStencilState DepthStencilState { get; set; } = DepthStencilState.Default;
|
||||
public RasterizerState RasterizerState { get; set; } = RasterizerState.CullNone;
|
||||
public Effect Effect { get; set; }
|
||||
|
||||
public void Begin()
|
||||
{
|
||||
_spriteBatch.Begin(SortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, _getTransformMatrix());
|
||||
}
|
||||
|
||||
public void End()
|
||||
{
|
||||
_spriteBatch.End();
|
||||
}
|
||||
|
||||
public void DrawRegion(Texture2DRegion textureRegion, Rectangle rectangle, Color color, Rectangle? clippingRectangle = null)
|
||||
{
|
||||
if (textureRegion != null)
|
||||
_spriteBatch.Draw(textureRegion, rectangle, color, clippingRectangle);
|
||||
}
|
||||
|
||||
public void DrawRegion(Texture2DRegion textureRegion, Vector2 position, Color color, Rectangle? clippingRectangle = null)
|
||||
{
|
||||
if (textureRegion != null)
|
||||
_spriteBatch.Draw(textureRegion, position, color, clippingRectangle);
|
||||
}
|
||||
|
||||
public void DrawText(BitmapFont font, string text, Vector2 position, Color color, Rectangle? clippingRectangle = null)
|
||||
{
|
||||
_spriteBatch.DrawString(font, text, position, color, clippingRectangle);
|
||||
}
|
||||
|
||||
public void DrawRectangle(Rectangle rectangle, Color color, float thickness = 1f, Rectangle? clippingRectangle = null)
|
||||
{
|
||||
if (clippingRectangle.HasValue)
|
||||
rectangle = rectangle.Clip(clippingRectangle.Value);
|
||||
|
||||
_spriteBatch.DrawRectangle(rectangle, color, thickness);
|
||||
}
|
||||
|
||||
public void FillRectangle(Rectangle rectangle, Color color, Rectangle? clippingRectangle = null)
|
||||
{
|
||||
if (clippingRectangle.HasValue)
|
||||
rectangle = rectangle.Clip(clippingRectangle.Value);
|
||||
|
||||
_spriteBatch.FillRectangle(rectangle, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.BitmapFonts;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
using MonoGame.Extended.Input.InputListeners;
|
||||
using MonoGame.Extended.ViewportAdapters;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public interface IGuiContext
|
||||
{
|
||||
BitmapFont DefaultFont { get; }
|
||||
Vector2 CursorPosition { get; }
|
||||
Control FocusedControl { get; }
|
||||
|
||||
void SetFocus(Control focusedControl);
|
||||
}
|
||||
|
||||
public class GuiSystem : IGuiContext, IRectangular
|
||||
{
|
||||
private readonly ViewportAdapter _viewportAdapter;
|
||||
private readonly IGuiRenderer _renderer;
|
||||
private readonly MouseListener _mouseListener;
|
||||
private readonly TouchListener _touchListener;
|
||||
private readonly KeyboardListener _keyboardListener;
|
||||
|
||||
private Control _preFocusedControl;
|
||||
|
||||
public GuiSystem(ViewportAdapter viewportAdapter, IGuiRenderer renderer)
|
||||
{
|
||||
_viewportAdapter = viewportAdapter;
|
||||
_renderer = renderer;
|
||||
|
||||
_mouseListener = new MouseListener(viewportAdapter);
|
||||
_mouseListener.MouseDown += (s, e) => OnPointerDown(PointerEventArgs.FromMouseArgs(e));
|
||||
_mouseListener.MouseMoved += (s, e) => OnPointerMoved(PointerEventArgs.FromMouseArgs(e));
|
||||
_mouseListener.MouseUp += (s, e) => OnPointerUp(PointerEventArgs.FromMouseArgs(e));
|
||||
_mouseListener.MouseWheelMoved += (s, e) => FocusedControl?.OnScrolled(e.ScrollWheelDelta);
|
||||
|
||||
_touchListener = new TouchListener(viewportAdapter);
|
||||
_touchListener.TouchStarted += (s, e) => OnPointerDown(PointerEventArgs.FromTouchArgs(e));
|
||||
_touchListener.TouchMoved += (s, e) => OnPointerMoved(PointerEventArgs.FromTouchArgs(e));
|
||||
_touchListener.TouchEnded += (s, e) => OnPointerUp(PointerEventArgs.FromTouchArgs(e));
|
||||
|
||||
_keyboardListener = new KeyboardListener();
|
||||
_keyboardListener.KeyTyped += (sender, args) => PropagateDown(FocusedControl, x => x.OnKeyTyped(this, args));
|
||||
_keyboardListener.KeyPressed += (sender, args) => PropagateDown(FocusedControl, x => x.OnKeyPressed(this, args));
|
||||
}
|
||||
|
||||
public Control FocusedControl { get; private set; }
|
||||
public Control HoveredControl { get; private set; }
|
||||
|
||||
private Screen _activeScreen;
|
||||
public Screen ActiveScreen
|
||||
{
|
||||
get => _activeScreen;
|
||||
set
|
||||
{
|
||||
if (_activeScreen != value)
|
||||
{
|
||||
_activeScreen = value;
|
||||
|
||||
if(_activeScreen != null)
|
||||
InitializeScreen(_activeScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle BoundingRectangle => _viewportAdapter.BoundingRectangle;
|
||||
|
||||
public Vector2 CursorPosition { get; set; }
|
||||
|
||||
public BitmapFont DefaultFont => Skin.Default?.DefaultFont;
|
||||
|
||||
private void InitializeScreen(Screen screen)
|
||||
{
|
||||
screen.Layout(this, BoundingRectangle);
|
||||
}
|
||||
|
||||
public void ClientSizeChanged()
|
||||
{
|
||||
//ActiveScreen?.Content?.InvalidateMeasure();
|
||||
ActiveScreen?.Layout(this, BoundingRectangle);
|
||||
}
|
||||
|
||||
public void Update(GameTime gameTime)
|
||||
{
|
||||
if(ActiveScreen == null)
|
||||
return;
|
||||
|
||||
_touchListener.Update(gameTime);
|
||||
_mouseListener.Update(gameTime);
|
||||
_keyboardListener.Update(gameTime);
|
||||
|
||||
var deltaSeconds = gameTime.GetElapsedSeconds();
|
||||
|
||||
if (ActiveScreen != null && ActiveScreen.IsVisible)
|
||||
UpdateControl(ActiveScreen.Content, deltaSeconds);
|
||||
|
||||
//if (ActiveScreen.IsLayoutRequired)
|
||||
// ActiveScreen.Layout(this, BoundingRectangle);
|
||||
|
||||
ActiveScreen.Update(gameTime);
|
||||
}
|
||||
|
||||
public void Draw(GameTime gameTime)
|
||||
{
|
||||
var deltaSeconds = gameTime.GetElapsedSeconds();
|
||||
|
||||
_renderer.Begin();
|
||||
|
||||
if (ActiveScreen != null && ActiveScreen.IsVisible)
|
||||
{
|
||||
DrawControl(ActiveScreen.Content, deltaSeconds);
|
||||
//DrawWindows(ActiveScreen.Windows, deltaSeconds);
|
||||
}
|
||||
|
||||
var cursor = Skin.Default?.Cursor;
|
||||
|
||||
if (cursor != null)
|
||||
_renderer.DrawRegion(cursor.TextureRegion, CursorPosition, cursor.Color);
|
||||
|
||||
_renderer.End();
|
||||
}
|
||||
|
||||
//private void DrawWindows(WindowCollection windows, float deltaSeconds)
|
||||
//{
|
||||
// foreach (var window in windows)
|
||||
// {
|
||||
// window.Draw(this, _renderer, deltaSeconds);
|
||||
// DrawChildren(window.Controls, deltaSeconds);
|
||||
// }
|
||||
//}
|
||||
|
||||
public void UpdateControl(Control control, float deltaSeconds)
|
||||
{
|
||||
if (control.IsVisible)
|
||||
{
|
||||
control.Update(this, deltaSeconds);
|
||||
|
||||
foreach (var childControl in control.Children)
|
||||
UpdateControl(childControl, deltaSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawControl(Control control, float deltaSeconds)
|
||||
{
|
||||
if (control.IsVisible)
|
||||
{
|
||||
control.Draw(this, _renderer, deltaSeconds);
|
||||
|
||||
foreach (var childControl in control.Children)
|
||||
DrawControl(childControl, deltaSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPointerDown(PointerEventArgs args)
|
||||
{
|
||||
if (ActiveScreen == null || !ActiveScreen.IsVisible)
|
||||
return;
|
||||
|
||||
_preFocusedControl = FindControlAtPoint(args.Position);
|
||||
PropagateDown(HoveredControl, x => x.OnPointerDown(this, args));
|
||||
}
|
||||
|
||||
private void OnPointerUp(PointerEventArgs args)
|
||||
{
|
||||
if (ActiveScreen == null || !ActiveScreen.IsVisible)
|
||||
return;
|
||||
|
||||
var postFocusedControl = FindControlAtPoint(args.Position);
|
||||
|
||||
if (_preFocusedControl == postFocusedControl)
|
||||
{
|
||||
SetFocus(postFocusedControl);
|
||||
}
|
||||
|
||||
_preFocusedControl = null;
|
||||
PropagateDown(HoveredControl, x => x.OnPointerUp(this, args));
|
||||
}
|
||||
|
||||
private void OnPointerMoved(PointerEventArgs args)
|
||||
{
|
||||
CursorPosition = args.Position.ToVector2();
|
||||
|
||||
if (ActiveScreen == null || !ActiveScreen.IsVisible)
|
||||
return;
|
||||
|
||||
var hoveredControl = FindControlAtPoint(args.Position);
|
||||
|
||||
if (HoveredControl != hoveredControl)
|
||||
{
|
||||
if (HoveredControl != null && (hoveredControl == null || !hoveredControl.HasParent(HoveredControl)))
|
||||
PropagateDown(HoveredControl, x => x.OnPointerLeave(this, args));
|
||||
|
||||
HoveredControl = hoveredControl;
|
||||
PropagateDown(HoveredControl, x => x.OnPointerEnter(this, args));
|
||||
}
|
||||
else
|
||||
{
|
||||
PropagateDown(HoveredControl, x => x.OnPointerMove(this, args));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFocus(Control focusedControl)
|
||||
{
|
||||
if (FocusedControl != focusedControl)
|
||||
{
|
||||
if (FocusedControl != null)
|
||||
{
|
||||
FocusedControl.IsFocused = false;
|
||||
PropagateDown(FocusedControl, x => x.OnUnfocus(this));
|
||||
}
|
||||
|
||||
FocusedControl = focusedControl;
|
||||
|
||||
if (FocusedControl != null)
|
||||
{
|
||||
FocusedControl.IsFocused = true;
|
||||
PropagateDown(FocusedControl, x => x.OnFocus(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method is meant to loop down the parents control to find a suitable event control. If the predicate returns false
|
||||
/// it will continue down the control tree.
|
||||
/// </summary>
|
||||
/// <param name="control">The control we want to check against</param>
|
||||
/// <param name="predicate">A function to check if the propagation should resume, if returns false it will continue down the tree.</param>
|
||||
private static void PropagateDown(Control control, Func<Control, bool> predicate)
|
||||
{
|
||||
while(control != null && predicate(control))
|
||||
{
|
||||
control = control.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
private Control FindControlAtPoint(Point point)
|
||||
{
|
||||
if (ActiveScreen == null || !ActiveScreen.IsVisible)
|
||||
return null;
|
||||
|
||||
return FindControlAtPoint(ActiveScreen.Content, point);
|
||||
}
|
||||
|
||||
private Control FindControlAtPoint(Control control, Point point)
|
||||
{
|
||||
foreach (var controlChild in control.Children.Reverse())
|
||||
{
|
||||
var c = FindControlAtPoint(controlChild, point);
|
||||
|
||||
if (c != null)
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
if (control.IsVisible && control.Contains(this, point))
|
||||
return control;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);KNI</DefineConstants>
|
||||
<Description>A GUI system for KNI written from the ground up to make KNI more awesome.</Description>
|
||||
<PackageTags>kni gui</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MonoGame.Extended.Input\KNI.Extended.Input.csproj" />
|
||||
<ProjectReference Include="..\MonoGame.Extended\KNI.Extended.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public enum HorizontalAlignment { Left, Right, Centre, Stretch }
|
||||
public enum VerticalAlignment { Top, Bottom, Centre, Stretch }
|
||||
|
||||
public static class LayoutHelper
|
||||
{
|
||||
public static void PlaceControl(IGuiContext context, Control control, float x, float y, float width, float height)
|
||||
{
|
||||
var rectangle = new Rectangle((int)x, (int)y, (int)width, (int)height);
|
||||
var desiredSize = control.CalculateActualSize(context);
|
||||
var alignedRectangle = AlignRectangle(control.HorizontalAlignment, control.VerticalAlignment, desiredSize, rectangle);
|
||||
|
||||
control.Position = new Point(control.Margin.Left + alignedRectangle.X, control.Margin.Top + alignedRectangle.Y);
|
||||
control.ActualSize = new Size(alignedRectangle.Width, alignedRectangle.Height) - control.Margin.Size;
|
||||
control.InvalidateMeasure();
|
||||
}
|
||||
|
||||
public static Rectangle AlignRectangle(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, Size size, Rectangle targetRectangle)
|
||||
{
|
||||
var x = GetHorizontalPosition(horizontalAlignment, size, targetRectangle);
|
||||
var y = GetVerticalPosition(verticalAlignment, size, targetRectangle);
|
||||
var width = horizontalAlignment == HorizontalAlignment.Stretch ? targetRectangle.Width : size.Width;
|
||||
var height = verticalAlignment == VerticalAlignment.Stretch ? targetRectangle.Height : size.Height;
|
||||
|
||||
return new Rectangle(x, y, width, height);
|
||||
}
|
||||
|
||||
public static int GetHorizontalPosition(HorizontalAlignment horizontalAlignment, Size size, Rectangle targetRectangle)
|
||||
{
|
||||
switch (horizontalAlignment)
|
||||
{
|
||||
case HorizontalAlignment.Stretch:
|
||||
case HorizontalAlignment.Left:
|
||||
return targetRectangle.X;
|
||||
case HorizontalAlignment.Right:
|
||||
return targetRectangle.Right - size.Width;
|
||||
case HorizontalAlignment.Centre:
|
||||
return targetRectangle.X + targetRectangle.Width / 2 - size.Width / 2;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(horizontalAlignment), horizontalAlignment, $"{horizontalAlignment} is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetVerticalPosition(VerticalAlignment verticalAlignment, Size size, Rectangle targetRectangle)
|
||||
{
|
||||
switch (verticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Stretch:
|
||||
case VerticalAlignment.Top:
|
||||
return targetRectangle.Y;
|
||||
case VerticalAlignment.Bottom:
|
||||
return targetRectangle.Bottom - size.Height;
|
||||
case VerticalAlignment.Centre:
|
||||
return targetRectangle.Y + targetRectangle.Height / 2 - size.Height / 2;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(verticalAlignment), verticalAlignment, $"{verticalAlignment} is not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Markup
|
||||
{
|
||||
public class MarkupParser
|
||||
{
|
||||
public MarkupParser()
|
||||
{
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, Type> _controlTypes =
|
||||
typeof(Control).Assembly
|
||||
.ExportedTypes
|
||||
.Where(t => t.IsSubclassOf(typeof(Control)))
|
||||
.ToDictionary(t => t.Name, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private static readonly Dictionary<Type, Func<string, object>> _converters =
|
||||
new Dictionary<Type, Func<string, object>>
|
||||
{
|
||||
{typeof(object), s => s},
|
||||
{typeof(string), s => s},
|
||||
{typeof(bool), s => bool.Parse(s)},
|
||||
{typeof(int), s => int.Parse(s)},
|
||||
{typeof(Color), s => s.StartsWith("#") ? ColorHelper.FromHex(s) : ColorHelper.FromName(s)}
|
||||
};
|
||||
|
||||
private static object ConvertValue(Type propertyType, string input, object dataContext)
|
||||
{
|
||||
var value = ParseBinding(input, dataContext);
|
||||
|
||||
if (_converters.TryGetValue(propertyType, out var converter))
|
||||
return converter(value); //property.SetValue(control, converter(value));
|
||||
|
||||
if (propertyType.IsEnum)
|
||||
return
|
||||
Enum.Parse(propertyType, value,
|
||||
true); // property.SetValue(control, Enum.Parse(propertyType, value, true));
|
||||
|
||||
throw new InvalidOperationException($"Converter not found for {propertyType}");
|
||||
}
|
||||
|
||||
private static object ParseChildNode(XmlNode node, Control parent, object dataContext)
|
||||
{
|
||||
if (node is XmlText)
|
||||
return node.InnerText.Trim();
|
||||
|
||||
if (_controlTypes.TryGetValue(node.Name, out var type))
|
||||
{
|
||||
var typeInfo = type.GetTypeInfo();
|
||||
var control = (Control) Activator.CreateInstance(type);
|
||||
|
||||
// ReSharper disable once AssignNullToNotNullAttribute
|
||||
foreach (var attribute in node.Attributes.Cast<XmlAttribute>())
|
||||
{
|
||||
var property = typeInfo.GetProperty(attribute.Name);
|
||||
|
||||
if (property != null)
|
||||
{
|
||||
var value = ConvertValue(property.PropertyType, attribute.Value, dataContext);
|
||||
property.SetValue(control, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var parts = attribute.Name.Split('.');
|
||||
var parentType = parts[0];
|
||||
var propertyName = parts[1];
|
||||
var propertyType = parent.GetAttachedPropertyType(propertyName);
|
||||
var propertyValue = ConvertValue(propertyType, attribute.Value, dataContext);
|
||||
|
||||
if (!string.Equals(parent.GetType().Name, parentType, StringComparison.OrdinalIgnoreCase))
|
||||
throw new InvalidOperationException(
|
||||
$"Attached properties are only supported on the immediate parent type {parentType}");
|
||||
|
||||
control.SetAttachedProperty(propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (node.HasChildNodes)
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
case ContentControl contentControl:
|
||||
if (node.ChildNodes.Count > 1)
|
||||
throw new InvalidOperationException("A content control can only have one child");
|
||||
|
||||
contentControl.Content = ParseChildNode(node.ChildNodes[0], control, dataContext);
|
||||
break;
|
||||
case LayoutControl layoutControl:
|
||||
foreach (var childControl in ParseChildNodes(node.ChildNodes, control, dataContext))
|
||||
layoutControl.Items.Add(childControl as Control);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Unknown control type {node.Name}");
|
||||
}
|
||||
|
||||
private static string ParseBinding(string expression, object dataContext)
|
||||
{
|
||||
if (dataContext != null && expression.StartsWith("{{") && expression.EndsWith("}}"))
|
||||
{
|
||||
var binding = expression.Substring(2, expression.Length - 4);
|
||||
var bindingValue = dataContext
|
||||
.GetType()
|
||||
.GetProperty(binding)
|
||||
?.GetValue(dataContext);
|
||||
|
||||
return $"{bindingValue}";
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
private static IEnumerable<object> ParseChildNodes(XmlNodeList nodes, Control parent, object dataContext)
|
||||
{
|
||||
foreach (var node in nodes.Cast<XmlNode>())
|
||||
{
|
||||
if (node.Name == "xml")
|
||||
{
|
||||
// TODO: Validate header
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return ParseChildNode(node, parent, dataContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Control Parse(string filePath, object dataContext)
|
||||
{
|
||||
var d = new XmlDocument();
|
||||
d.Load(filePath);
|
||||
return ParseChildNodes(d.ChildNodes, null, dataContext)
|
||||
.LastOrDefault() as Control;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>A GUI system for MonoGame written from the ground up to make MonoGame more awesome.</Description>
|
||||
<PackageTags>monogame gui</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MonoGame.Extended.Input\MonoGame.Extended.Input.csproj" />
|
||||
<ProjectReference Include="..\MonoGame.Extended\MonoGame.Extended.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public enum Orientation { Horizontal, Vertical }
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Input;
|
||||
using MonoGame.Extended.Input.InputListeners;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public class PointerEventArgs : EventArgs
|
||||
{
|
||||
private PointerEventArgs()
|
||||
{
|
||||
}
|
||||
|
||||
public Point Position { get; private set; }
|
||||
public MouseButton Button { get; private set; }
|
||||
public int ScrollWheelDelta { get; private set; }
|
||||
public int ScrollWheelValue { get; private set; }
|
||||
public TimeSpan Time { get; private set; }
|
||||
|
||||
public static PointerEventArgs FromMouseArgs(MouseEventArgs args)
|
||||
{
|
||||
return new PointerEventArgs
|
||||
{
|
||||
Position = args.Position,
|
||||
Button = args.Button,
|
||||
ScrollWheelDelta = args.ScrollWheelDelta,
|
||||
ScrollWheelValue = args.ScrollWheelValue,
|
||||
Time = args.Time
|
||||
};
|
||||
}
|
||||
|
||||
public static PointerEventArgs FromTouchArgs(TouchEventArgs args)
|
||||
{
|
||||
return new PointerEventArgs
|
||||
{
|
||||
Position = args.Position,
|
||||
Button = MouseButton.Left,
|
||||
Time = args.Time
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
using MonoGame.Extended.Gui.Serialization;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public class Screen //: Element<GuiSystem>, IDisposable
|
||||
{
|
||||
public Screen()
|
||||
{
|
||||
//Windows = new WindowCollection(this) { ItemAdded = w => _isLayoutRequired = true };
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
private Control _content;
|
||||
[JsonPropertyOrder(1)]
|
||||
public Control Content
|
||||
{
|
||||
get { return _content; }
|
||||
set
|
||||
{
|
||||
if (_content != value)
|
||||
{
|
||||
_content = value;
|
||||
_isLayoutRequired = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//[JsonIgnore]
|
||||
//public WindowCollection Windows { get; }
|
||||
|
||||
public float Width { get; private set; }
|
||||
public float Height { get; private set; }
|
||||
public SizeF Size => new SizeF(Width, Height);
|
||||
public bool IsVisible { get; set; } = true;
|
||||
|
||||
private bool _isLayoutRequired;
|
||||
[JsonIgnore]
|
||||
public bool IsLayoutRequired => _isLayoutRequired || Content.IsLayoutRequired;
|
||||
|
||||
public virtual void Update(GameTime gameTime)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
IsVisible = true;
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
IsVisible = false;
|
||||
}
|
||||
|
||||
public T FindControl<T>(string name)
|
||||
where T : Control
|
||||
{
|
||||
return FindControl<T>(Content, name);
|
||||
}
|
||||
|
||||
private static T FindControl<T>(Control rootControl, string name)
|
||||
where T : Control
|
||||
{
|
||||
if (rootControl.Name == name)
|
||||
return rootControl as T;
|
||||
|
||||
foreach (var childControl in rootControl.Children)
|
||||
{
|
||||
var control = FindControl<T>(childControl, name);
|
||||
|
||||
if (control != null)
|
||||
return control;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Layout(IGuiContext context, Rectangle rectangle)
|
||||
{
|
||||
Width = rectangle.Width;
|
||||
Height = rectangle.Height;
|
||||
|
||||
LayoutHelper.PlaceControl(context, Content, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
|
||||
|
||||
//foreach (var window in Windows)
|
||||
// LayoutHelper.PlaceWindow(context, window, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
|
||||
|
||||
_isLayoutRequired = false;
|
||||
Content.IsLayoutRequired = false;
|
||||
}
|
||||
|
||||
//public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
//{
|
||||
// renderer.DrawRectangle(BoundingRectangle, Color.Green);
|
||||
//}
|
||||
|
||||
public static Screen FromStream(ContentManager contentManager, Stream stream, params Type[] customControlTypes)
|
||||
{
|
||||
return FromStream<Screen>(contentManager, stream, customControlTypes);
|
||||
}
|
||||
|
||||
public static TScreen FromStream<TScreen>(ContentManager contentManager, Stream stream, params Type[] customControlTypes)
|
||||
where TScreen : Screen
|
||||
{
|
||||
var skinService = new SkinService();
|
||||
var options = GuiJsonSerializerOptionsProvider.GetOptions(contentManager, customControlTypes);
|
||||
options.Converters.Add(new SkinJsonConverter(contentManager, skinService, customControlTypes));
|
||||
options.Converters.Add(new ControlJsonConverter(skinService, customControlTypes));
|
||||
return JsonSerializer.Deserialize<TScreen>(stream, options);
|
||||
}
|
||||
|
||||
public static Screen FromFile(ContentManager contentManager, string path, params Type[] customControlTypes)
|
||||
{
|
||||
using (var stream = TitleContainer.OpenStream(path))
|
||||
{
|
||||
return FromStream<Screen>(contentManager, stream, customControlTypes);
|
||||
}
|
||||
}
|
||||
|
||||
public static TScreen FromFile<TScreen>(ContentManager contentManager, string path, params Type[] customControlTypes)
|
||||
where TScreen : Screen
|
||||
{
|
||||
using (var stream = TitleContainer.OpenStream(path))
|
||||
{
|
||||
return FromStream<TScreen>(contentManager, stream, customControlTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
//public class ScreenCollection : ElementCollection<Screen, GuiSystem>
|
||||
//{
|
||||
// public ScreenCollection(GuiSystem parent)
|
||||
// : base(parent)
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization
|
||||
{
|
||||
public class ControlJsonConverter : JsonConverter<Control>
|
||||
{
|
||||
private readonly IGuiSkinService _guiSkinService;
|
||||
private readonly ControlStyleJsonConverter _styleConverter;
|
||||
private const string _styleProperty = "Style";
|
||||
|
||||
public ControlJsonConverter(IGuiSkinService guiSkinService, params Type[] customControlTypes)
|
||||
{
|
||||
_guiSkinService = guiSkinService;
|
||||
_styleConverter = new ControlStyleJsonConverter(customControlTypes);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(Control);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Control Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var style = _styleConverter.Read(ref reader, typeToConvert, options);
|
||||
var template = GetControlTemplate(style);
|
||||
var skin = _guiSkinService.Skin;
|
||||
var control = skin.Create(style.TargetType, template);
|
||||
|
||||
var itemsControl = control as ItemsControl;
|
||||
if (itemsControl != null)
|
||||
{
|
||||
object childControls;
|
||||
|
||||
if (style.TryGetValue(nameof(ItemsControl.Items), out childControls))
|
||||
{
|
||||
var controlCollection = childControls as ControlCollection;
|
||||
|
||||
if (controlCollection != null)
|
||||
{
|
||||
foreach (var child in controlCollection)
|
||||
itemsControl.Items.Add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
style.Apply(control);
|
||||
return control;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, Control value, JsonSerializerOptions options) { }
|
||||
|
||||
|
||||
|
||||
private static string GetControlTemplate(ControlStyle style)
|
||||
{
|
||||
object template;
|
||||
|
||||
if (style.TryGetValue(_styleProperty, out template))
|
||||
return template as string;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using MonoGame.Extended.Collections;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization
|
||||
{
|
||||
public class ControlStyleJsonConverter : JsonConverter<ControlStyle>
|
||||
{
|
||||
private readonly Dictionary<string, Type> _controlTypes;
|
||||
private const string _typeProperty = "Type";
|
||||
private const string _nameProperty = "Name";
|
||||
|
||||
public ControlStyleJsonConverter(params Type[] customControlTypes)
|
||||
{
|
||||
_controlTypes = typeof(Control)
|
||||
.GetTypeInfo()
|
||||
.Assembly
|
||||
.ExportedTypes
|
||||
.Concat(customControlTypes)
|
||||
.Where(t => t.GetTypeInfo().IsSubclassOf(typeof(Control)))
|
||||
.ToDictionary(t => t.Name);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(ControlStyle);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ControlStyle Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var dictionary = JsonSerializer.Deserialize<Dictionary<string, object>>(ref reader, options);
|
||||
var name = dictionary.GetValueOrDefault(_nameProperty) as string;
|
||||
var typeName = dictionary.GetValueOrDefault(_typeProperty) as string;
|
||||
|
||||
if (!_controlTypes.TryGetValue(typeName, out Type controlType))
|
||||
throw new FormatException("invalid control type: " + typeName);
|
||||
|
||||
var targetType = typeName != null ? controlType : typeof(Control);
|
||||
var properties = targetType
|
||||
.GetRuntimeProperties()
|
||||
.ToDictionary(p => p.Name);
|
||||
var style = new ControlStyle(name, targetType);
|
||||
|
||||
foreach (var keyValuePair in dictionary.Where(i => i.Key != _typeProperty))
|
||||
{
|
||||
var propertyName = keyValuePair.Key;
|
||||
var rawValue = keyValuePair.Value;
|
||||
|
||||
PropertyInfo propertyInfo;
|
||||
var value = properties.TryGetValue(propertyName, out propertyInfo)
|
||||
? DeserializeValueAs(rawValue, propertyInfo.PropertyType)
|
||||
: DeserializeValueAs(rawValue, typeof(object));
|
||||
|
||||
style.Add(propertyName, value);
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
private static object DeserializeValueAs(object value, Type type)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(value, type);
|
||||
return JsonSerializer.Deserialize(json, type);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, ControlStyle value, JsonSerializerOptions options)
|
||||
{
|
||||
var style = (ControlStyle)value;
|
||||
var dictionary = new Dictionary<string, object> { [_typeProperty] = style.TargetType.Name };
|
||||
|
||||
foreach (var keyValuePair in style)
|
||||
dictionary.Add(keyValuePair.Key, keyValuePair.Value);
|
||||
|
||||
JsonSerializer.Serialize(writer, dictionary);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using MonoGame.Extended.BitmapFonts;
|
||||
using MonoGame.Extended.Serialization;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization;
|
||||
|
||||
public static class GuiJsonSerializerOptionsProvider
|
||||
{
|
||||
public static JsonSerializerOptions GetOptions(ContentManager contentManager, params Type[] customControlTypes)
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
|
||||
var textureRegionService = new GuiTextureRegionService();
|
||||
|
||||
options.Converters.Add(new Vector2JsonConverter());
|
||||
options.Converters.Add(new SizeJsonConverter());
|
||||
options.Converters.Add(new Size2JsonConverter());
|
||||
options.Converters.Add(new ColorJsonConverter());
|
||||
options.Converters.Add(new ThicknessJsonConverter());
|
||||
options.Converters.Add(new ContentManagerJsonConverter<BitmapFont>(contentManager, font => font.Face));
|
||||
options.Converters.Add(new ControlStyleJsonConverter(customControlTypes));
|
||||
options.Converters.Add(new GuiTextureAtlasJsonConverter(contentManager, textureRegionService));
|
||||
options.Converters.Add(new GuiNinePatchRegion2DJsonConverter(textureRegionService));
|
||||
options.Converters.Add(new TextureRegion2DJsonConverter(textureRegionService));
|
||||
options.Converters.Add(new VerticalAlignmentConverter());
|
||||
options.Converters.Add(new HorizontalAlignmentConverter());
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using MonoGame.Extended.Serialization;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization
|
||||
{
|
||||
public class GuiNinePatchRegion2DJsonConverter : NinePatchJsonConverter
|
||||
{
|
||||
private readonly IGuiTextureRegionService _textureRegionService;
|
||||
|
||||
public GuiNinePatchRegion2DJsonConverter(IGuiTextureRegionService textureRegionService)
|
||||
: base(textureRegionService)
|
||||
{
|
||||
_textureRegionService = textureRegionService;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using MonoGame.Extended.Graphics;
|
||||
using MonoGame.Extended.Serialization;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization
|
||||
{
|
||||
public class GuiTextureAtlasJsonConverter : ContentManagerJsonConverter<Texture2DAtlas>
|
||||
{
|
||||
private readonly IGuiTextureRegionService _textureRegionService;
|
||||
|
||||
public GuiTextureAtlasJsonConverter(ContentManager contentManager, IGuiTextureRegionService textureRegionService)
|
||||
: base(contentManager, atlas => atlas.Name)
|
||||
{
|
||||
_textureRegionService = textureRegionService;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Texture2DAtlas Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var textureAtlas = base.Read(ref reader, typeToConvert, options);
|
||||
if (textureAtlas is not null)
|
||||
{
|
||||
_textureRegionService.TextureAtlases.Add(textureAtlas);
|
||||
}
|
||||
|
||||
return textureAtlas;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using MonoGame.Extended.Graphics;
|
||||
using MonoGame.Extended.Serialization;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization
|
||||
{
|
||||
public interface IGuiTextureRegionService : ITextureRegionService
|
||||
{
|
||||
IList<Texture2DAtlas> TextureAtlases { get; }
|
||||
}
|
||||
|
||||
public class GuiTextureRegionService : TextureRegionService, IGuiTextureRegionService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization;
|
||||
|
||||
public class HorizontalAlignmentConverter : JsonConverter<HorizontalAlignment>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(HorizontalAlignment);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override HorizontalAlignment Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var value = reader.GetString();
|
||||
|
||||
if (value.Equals("Center", StringComparison.OrdinalIgnoreCase) || value.Equals("Centre", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return HorizontalAlignment.Centre;
|
||||
}
|
||||
|
||||
if (Enum.TryParse<HorizontalAlignment>(value, true, out var alignment))
|
||||
{
|
||||
return alignment;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Invalid value for '{nameof(HorizontalAlignment)}'");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, HorizontalAlignment value, JsonSerializerOptions options) { }
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization;
|
||||
|
||||
public interface IGuiSkinService
|
||||
{
|
||||
Skin Skin { get; set; }
|
||||
}
|
||||
|
||||
public class SkinService : IGuiSkinService
|
||||
{
|
||||
public Skin Skin { get; set; }
|
||||
}
|
||||
|
||||
public class SkinJsonConverter : JsonConverter<Skin>
|
||||
{
|
||||
private readonly ContentManager _contentManager;
|
||||
private readonly IGuiSkinService _skinService;
|
||||
private readonly Type[] _customControlTypes;
|
||||
|
||||
public SkinJsonConverter(ContentManager contentManager, IGuiSkinService skinService, params Type[] customControlTypes)
|
||||
{
|
||||
_contentManager = contentManager;
|
||||
_skinService = skinService;
|
||||
_customControlTypes = customControlTypes;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(Skin);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Skin Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
var assetName = reader.GetString();
|
||||
|
||||
// TODO: Load this using the ContentManager instead.
|
||||
using (var stream = TitleContainer.OpenStream(assetName))
|
||||
{
|
||||
var skin = Skin.FromStream(_contentManager, stream, _customControlTypes);
|
||||
_skinService.Skin = skin;
|
||||
return skin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"{nameof(SkinJsonConverter)} can only convert from a string");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, Skin value, JsonSerializerOptions options) { }
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Serialization;
|
||||
|
||||
public class VerticalAlignmentConverter : JsonConverter<VerticalAlignment>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(VerticalAlignment);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override VerticalAlignment Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var value = reader.GetString();
|
||||
|
||||
if (value.Equals("Center", StringComparison.OrdinalIgnoreCase) || value.Equals("Centre", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return VerticalAlignment.Centre;
|
||||
}
|
||||
|
||||
if (Enum.TryParse<VerticalAlignment>(value, true, out var alignment))
|
||||
{
|
||||
return alignment;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Invalid value for '{nameof(VerticalAlignment)}'");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, VerticalAlignment value, JsonSerializerOptions options) { }
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using MonoGame.Extended.BitmapFonts;
|
||||
using MonoGame.Extended.Collections;
|
||||
using MonoGame.Extended.Graphics;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
using MonoGame.Extended.Gui.Serialization;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
public class Skin
|
||||
{
|
||||
public Skin()
|
||||
{
|
||||
TextureAtlases = new List<Texture2DAtlas>();
|
||||
Fonts = new List<BitmapFont>();
|
||||
NinePatches = new List<NinePatch>();
|
||||
Styles = new KeyedCollection<string, ControlStyle>(s => s.Name ?? s.TargetType.Name);
|
||||
}
|
||||
|
||||
[JsonPropertyOrder(0)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyOrder(1)]
|
||||
public IList<Texture2DAtlas> TextureAtlases { get; set; }
|
||||
|
||||
[JsonPropertyOrder(2)]
|
||||
public IList<BitmapFont> Fonts { get; set; }
|
||||
|
||||
[JsonPropertyOrder(3)]
|
||||
public IList<NinePatch> NinePatches { get; set; }
|
||||
|
||||
[JsonPropertyOrder(4)]
|
||||
public BitmapFont DefaultFont => Fonts.FirstOrDefault();
|
||||
|
||||
[JsonPropertyOrder(5)]
|
||||
public Cursor Cursor { get; set; }
|
||||
|
||||
[JsonPropertyOrder(6)]
|
||||
public KeyedCollection<string, ControlStyle> Styles { get; private set; }
|
||||
|
||||
public ControlStyle GetStyle(string name)
|
||||
{
|
||||
if (Styles.TryGetValue(name, out var controlStyle))
|
||||
return controlStyle;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ControlStyle GetStyle(Type controlType)
|
||||
{
|
||||
return GetStyle(controlType.FullName);
|
||||
}
|
||||
|
||||
public void Apply(Control control)
|
||||
{
|
||||
// TODO: This allocates memory on each apply because it needs to apply styles in reverse
|
||||
var types = new List<Type>();
|
||||
var controlType = control.GetType();
|
||||
|
||||
while (controlType != null)
|
||||
{
|
||||
types.Add(controlType);
|
||||
controlType = controlType.GetTypeInfo().BaseType;
|
||||
}
|
||||
|
||||
for (var i = types.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var style = GetStyle(types[i]);
|
||||
style?.Apply(control);
|
||||
}
|
||||
}
|
||||
|
||||
public static Skin FromFile(ContentManager contentManager, string path, params Type[] customControlTypes)
|
||||
{
|
||||
using (var stream = TitleContainer.OpenStream(path))
|
||||
{
|
||||
return FromStream(contentManager, stream, customControlTypes);
|
||||
}
|
||||
}
|
||||
|
||||
public static Skin FromStream(ContentManager contentManager, Stream stream, params Type[] customControlTypes)
|
||||
{
|
||||
var options = GuiJsonSerializerOptionsProvider.GetOptions(contentManager, customControlTypes);
|
||||
return JsonSerializer.Deserialize<Skin>(stream, options);
|
||||
}
|
||||
|
||||
|
||||
public T Create<T>(string template, Action<T> onCreate)
|
||||
where T : Control, new()
|
||||
{
|
||||
var control = new T();
|
||||
GetStyle(template).Apply(control);
|
||||
onCreate(control);
|
||||
return control;
|
||||
}
|
||||
|
||||
public Control Create(Type type, string template)
|
||||
{
|
||||
var control = (Control)Activator.CreateInstance(type);
|
||||
|
||||
if (template != null)
|
||||
{
|
||||
var style = GetStyle(template);
|
||||
if (style != null)
|
||||
style.Apply(control);
|
||||
else
|
||||
throw new FormatException($"invalid style {template} for control {type.Name}");
|
||||
}
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
public static Skin Default { get; set; }
|
||||
|
||||
public static Skin CreateDefault(BitmapFont font)
|
||||
{
|
||||
Default = new Skin
|
||||
{
|
||||
Fonts = { font },
|
||||
Styles =
|
||||
{
|
||||
new ControlStyle(typeof(Control)) {
|
||||
{nameof(Control.BackgroundColor), new Color(51, 51, 55)},
|
||||
{nameof(Control.BorderColor), new Color(67, 67, 70)},
|
||||
{nameof(Control.BorderThickness), 1},
|
||||
{nameof(Control.TextColor), new Color(241, 241, 241)},
|
||||
{nameof(Control.Padding), new Thickness(5)},
|
||||
{nameof(Control.DisabledStyle), new ControlStyle(typeof(Control)) {
|
||||
{ nameof(Control.TextColor), new Color(78,78,80) }
|
||||
}
|
||||
}
|
||||
},
|
||||
new ControlStyle(typeof(LayoutControl)) {
|
||||
{nameof(Control.BackgroundColor), Color.Transparent},
|
||||
{nameof(Control.BorderColor), Color.Transparent },
|
||||
{nameof(Control.BorderThickness), 0},
|
||||
{nameof(Control.Padding), new Thickness(0)},
|
||||
{nameof(Control.Margin), new Thickness(0)},
|
||||
},
|
||||
new ControlStyle(typeof(ComboBox)) {
|
||||
{nameof(ComboBox.DropDownColor), new Color(71, 71, 75)},
|
||||
{nameof(ComboBox.SelectedItemColor), new Color(0, 122, 204)},
|
||||
{nameof(ComboBox.HorizontalTextAlignment), HorizontalAlignment.Left }
|
||||
},
|
||||
new ControlStyle(typeof(CheckBox))
|
||||
{
|
||||
{nameof(CheckBox.HorizontalTextAlignment), HorizontalAlignment.Left },
|
||||
{nameof(CheckBox.BorderThickness), 0},
|
||||
{nameof(CheckBox.BackgroundColor), Color.Transparent},
|
||||
},
|
||||
new ControlStyle(typeof(ListBox))
|
||||
{
|
||||
{nameof(ListBox.SelectedItemColor), new Color(0, 122, 204)},
|
||||
{nameof(ListBox.HorizontalTextAlignment), HorizontalAlignment.Left }
|
||||
},
|
||||
new ControlStyle(typeof(Label)) {
|
||||
{nameof(Label.BackgroundColor), Color.Transparent},
|
||||
{nameof(Label.TextColor), Color.White},
|
||||
{nameof(Label.BorderColor), Color.Transparent},
|
||||
{nameof(Label.BorderThickness), 0},
|
||||
{nameof(Label.HorizontalTextAlignment), HorizontalAlignment.Left},
|
||||
{nameof(Label.VerticalTextAlignment), VerticalAlignment.Bottom},
|
||||
{nameof(Control.Margin), new Thickness(5,0)},
|
||||
{nameof(Control.Padding), new Thickness(0)},
|
||||
},
|
||||
new ControlStyle(typeof(TextBox)) {
|
||||
{nameof(Control.BackgroundColor), Color.DarkGray},
|
||||
{nameof(Control.TextColor), Color.Black},
|
||||
{nameof(Control.BorderColor), new Color(67, 67, 70)},
|
||||
{nameof(Control.BorderThickness), 2},
|
||||
},
|
||||
new ControlStyle(typeof(TextBox2)) {
|
||||
{nameof(Control.BackgroundColor), Color.DarkGray},
|
||||
{nameof(Control.TextColor), Color.Black},
|
||||
{nameof(Control.BorderColor), new Color(67, 67, 70)},
|
||||
{nameof(Control.BorderThickness), 2},
|
||||
},
|
||||
new ControlStyle(typeof(Button)) {
|
||||
{
|
||||
nameof(Button.HoverStyle), new ControlStyle {
|
||||
{nameof(Button.BackgroundColor), new Color(62, 62, 64)},
|
||||
{nameof(Button.BorderColor), Color.WhiteSmoke }
|
||||
}
|
||||
},
|
||||
{
|
||||
nameof(Button.PressedStyle), new ControlStyle {
|
||||
{nameof(Button.BackgroundColor), new Color(0, 122, 204)}
|
||||
}
|
||||
}
|
||||
},
|
||||
new ControlStyle(typeof(ToggleButton)) {
|
||||
{
|
||||
nameof(ToggleButton.CheckedStyle), new ControlStyle {
|
||||
{nameof(Button.BackgroundColor), new Color(0, 122, 204)}
|
||||
}
|
||||
},
|
||||
{
|
||||
nameof(ToggleButton.CheckedHoverStyle), new ControlStyle {
|
||||
{nameof(Button.BorderColor), Color.WhiteSmoke}
|
||||
}
|
||||
}
|
||||
},
|
||||
new ControlStyle(typeof(ProgressBar)) {
|
||||
{nameof(ProgressBar.BarColor), new Color(0, 122, 204) },
|
||||
{nameof(ProgressBar.Height), 32 },
|
||||
{nameof(ProgressBar.Padding), new Thickness(5, 4)},
|
||||
}
|
||||
}
|
||||
};
|
||||
return Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
//public class Window : Element<Screen>
|
||||
//{
|
||||
// public Window(Screen parent)
|
||||
// {
|
||||
// Parent = parent;
|
||||
// }
|
||||
|
||||
// public ControlCollection Controls { get; } = new ControlCollection();
|
||||
|
||||
// public void Show()
|
||||
// {
|
||||
// Parent.Windows.Add(this);
|
||||
// }
|
||||
|
||||
// public void Hide()
|
||||
// {
|
||||
// Parent.Windows.Remove(this);
|
||||
// }
|
||||
|
||||
// public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
|
||||
// {
|
||||
// renderer.FillRectangle(BoundingRectangle, Color.Magenta);
|
||||
// }
|
||||
|
||||
// public Size2 GetDesiredSize(IGuiContext context, Size2 availableSize)
|
||||
// {
|
||||
// return new Size2(Width, Height);
|
||||
// }
|
||||
|
||||
// public void Layout(IGuiContext context, RectangleF rectangle)
|
||||
// {
|
||||
// foreach (var control in Controls)
|
||||
// LayoutHelper.PlaceControl(context, control, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace MonoGame.Extended.Gui
|
||||
{
|
||||
//public class WindowCollection : ElementCollection<Window, Screen>
|
||||
//{
|
||||
// public WindowCollection(Screen parent)
|
||||
// : base(parent)
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
//using System.Collections.Generic;
|
||||
//using Microsoft.Xna.Framework.Graphics;
|
||||
//using MonoGame.Extended.BitmapFonts;
|
||||
//using MonoGame.Extended.Gui.Controls;
|
||||
//using MonoGame.Extended.Tests;
|
||||
//using MonoGame.Extended.TextureAtlases;
|
||||
//using NSubstitute;
|
||||
//using Xunit;
|
||||
|
||||
//namespace MonoGame.Extended.Gui.Tests.Controls
|
||||
//{
|
||||
// public class GuiButtonTests
|
||||
// {
|
||||
// [Fact]
|
||||
// public void DesiredSizeShouldBeEmptyByDefault()
|
||||
// {
|
||||
// var availableSize = new Size2(800, 480);
|
||||
// var context = Substitute.For<IGuiContext>();
|
||||
// var button = new Button();
|
||||
// var desiredSize = button.GetDesiredSize(context, availableSize);
|
||||
|
||||
// Assert.That(desiredSize, Is.EqualTo(Size2.Empty));
|
||||
// }
|
||||
|
||||
// [Fact]
|
||||
// public void DesiredSizeShouldBeTheSizeOfTheBackgroundRegion()
|
||||
// {
|
||||
// var availableSize = new Size2(800, 480);
|
||||
// var context = Substitute.For<IGuiContext>();
|
||||
// var backgroundRegion = MockTextureRegion();
|
||||
// var button = new GuiButton { BackgroundRegion = backgroundRegion };
|
||||
// var desiredSize = button.GetDesiredSize(context, availableSize);
|
||||
|
||||
// Assert.That(desiredSize, Is.EqualTo(backgroundRegion.Size));
|
||||
// }
|
||||
|
||||
// [Fact]
|
||||
// public void DesiredSizeShouldBeTheSizeOfTheMarginsInANinePatchRegion()
|
||||
// {
|
||||
// var availableSize = new Size2(800, 480);
|
||||
// var context = Substitute.For<IGuiContext>();
|
||||
// var texture = new Texture2D(new TestGraphicsDevice(), 512, 512);
|
||||
// var backgroundRegion = new NinePatchRegion2D(new TextureRegion2D(texture), new Thickness(10, 20));
|
||||
// var button = new GuiButton() { BackgroundRegion = backgroundRegion };
|
||||
// var desiredSize = button.GetDesiredSize(context, availableSize);
|
||||
|
||||
// Assert.That(desiredSize, Is.EqualTo(new Size2(20, 40)));
|
||||
// }
|
||||
|
||||
// [Fact]
|
||||
// public void DesiredSizeShouldAtLeastBeTheSizeOfTheText()
|
||||
// {
|
||||
// const string text = "abcdefg";
|
||||
|
||||
// var availableSize = new Size2(800, 480);
|
||||
// var context = Substitute.For<IGuiContext>();
|
||||
// var font = CreateMockFont(text, lineHeight: 32);
|
||||
// var expectedSize = font.MeasureString(text);
|
||||
// var button = new GuiButton {Text = text, Font = font};
|
||||
|
||||
// var desiredSize = button.GetDesiredSize(context, availableSize);
|
||||
|
||||
// Assert.That(desiredSize, Is.EqualTo(expectedSize));
|
||||
// }
|
||||
|
||||
// [Fact]
|
||||
// public void DesiredSizeShouldAtLeastBeTheSizeOfTheIcon()
|
||||
// {
|
||||
// var texture = new Texture2D(new TestGraphicsDevice(), 35, 38);
|
||||
// var icon = new TextureRegion2D(texture);
|
||||
|
||||
// var availableSize = new Size2(800, 480);
|
||||
// var context = Substitute.For<IGuiContext>();
|
||||
// var button = new GuiButton { IconRegion = icon };
|
||||
// var desiredSize = button.GetDesiredSize(context, availableSize);
|
||||
|
||||
// Assert.That(desiredSize, Is.EqualTo(icon.Size));
|
||||
// }
|
||||
|
||||
// [Fact]
|
||||
// public void DesiredSizeShouldBeTheSizeOfTheBiggestTextOrIcon()
|
||||
// {
|
||||
// const string text = "abcdefg";
|
||||
|
||||
// var texture = new Texture2D(new TestGraphicsDevice(), 35, 38);
|
||||
// var icon = new TextureRegion2D(texture);
|
||||
// var iconExpectedSize = icon.Size;
|
||||
|
||||
// var availableSize = new Size2(800, 480);
|
||||
// var context = Substitute.For<IGuiContext>();
|
||||
|
||||
// var font = CreateMockFont(text, 32);
|
||||
// var fontExpectedSize = font.MeasureString(text);
|
||||
|
||||
// var button = new GuiButton { Text = text, Font = font, IconRegion = icon };
|
||||
// var desiredSize = button.GetDesiredSize(context, availableSize);
|
||||
|
||||
// Assert.That(desiredSize.Width, Is.EqualTo(fontExpectedSize.Width));
|
||||
// Assert.That(desiredSize.Height, Is.EqualTo(iconExpectedSize.Height));
|
||||
// }
|
||||
|
||||
// private static BitmapFont CreateMockFont(string text, int lineHeight)
|
||||
// {
|
||||
// var regions = new List<BitmapFontRegion>();
|
||||
// var xOffset = 0;
|
||||
|
||||
// foreach (var character in text)
|
||||
// {
|
||||
// regions.Add(new BitmapFontRegion(MockTextureRegion(10, 10), character, xOffset, yOffset: 0, xAdvance: 0));
|
||||
// xOffset += 10;
|
||||
// }
|
||||
|
||||
// return new BitmapFont("font", regions, lineHeight);
|
||||
// }
|
||||
|
||||
// private static TextureRegion2D MockTextureRegion(int width = 100, int height = 200)
|
||||
// {
|
||||
// var texture = new Texture2D(new TestGraphicsDevice(), width, height);
|
||||
// return new TextureRegion2D(texture, 0, 0, width, height);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -1,58 +0,0 @@
|
||||
//using MonoGame.Extended.Gui.Controls;
|
||||
//using NSubstitute;
|
||||
//using Xunit;
|
||||
|
||||
//namespace MonoGame.Extended.Gui.Tests.Controls
|
||||
//{
|
||||
|
||||
// public class GuiControlCollectionTests
|
||||
// {
|
||||
// [Fact]
|
||||
// public void GuiControlCollection_Add_SetsTheParent_Test()
|
||||
// {
|
||||
// var parent = Substitute.For<GuiControl>();
|
||||
// var child = Substitute.For<GuiControl>();
|
||||
|
||||
// var controls = new GuiControlCollection(parent) { child };
|
||||
// Assert.IsTrue(controls.Contains(child));
|
||||
// Assert.AreSame(parent, child.Parent);
|
||||
// }
|
||||
|
||||
// [Fact]
|
||||
// public void GuiControlCollection_Remove_SetsTheParentToNull_Test()
|
||||
// {
|
||||
// var parent = Substitute.For<GuiControl>();
|
||||
// var child = Substitute.For<GuiControl>();
|
||||
|
||||
// new GuiControlCollection(parent) { child }.Remove(child);
|
||||
|
||||
// Assert.IsNull(child.Parent);
|
||||
// }
|
||||
|
||||
// [Fact]
|
||||
// public void GuiControlCollection_Insert_SetsTheParent_Test()
|
||||
// {
|
||||
// var parent = Substitute.For<GuiControl>();
|
||||
// var child = Substitute.For<GuiControl>();
|
||||
|
||||
// var controls = new GuiControlCollection(parent);
|
||||
|
||||
// controls.Insert(0, child);
|
||||
// Assert.IsTrue(controls.Contains(child));
|
||||
// Assert.AreSame(parent, child.Parent);
|
||||
// }
|
||||
|
||||
// [Fact]
|
||||
// public void GuiControlCollection_Clear_SetsAllTheParentsToNull_Test()
|
||||
// {
|
||||
// var parent = Substitute.For<GuiControl>();
|
||||
// var child0 = Substitute.For<GuiControl>();
|
||||
// var child1 = Substitute.For<GuiControl>();
|
||||
|
||||
// new GuiControlCollection(parent) { child0, child1 }.Clear();
|
||||
|
||||
// Assert.IsNull(child0.Parent);
|
||||
// Assert.IsNull(child1.Parent);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -1,11 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\source\MonoGame.Extended.Gui\FNA.Extended.Gui.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,34 +0,0 @@
|
||||
using MonoGame.Extended.Gui.Controls;
|
||||
using Xunit;
|
||||
|
||||
namespace MonoGame.Extended.Gui.Tests
|
||||
{
|
||||
//
|
||||
//public class GuiRendererTests
|
||||
//{
|
||||
// [Fact]
|
||||
// public void GuiRenderer_TargetScreen_Test()
|
||||
// {
|
||||
// var screen = new GuiScreen();
|
||||
// var renderer = new GuiTestRenderer(screen);
|
||||
|
||||
// Assert.That(renderer.TargetScreen, Is.SameAs(screen));
|
||||
// }
|
||||
//}
|
||||
|
||||
//public class GuiTestRenderer : GuiRenderer<TestDrawer>
|
||||
//{
|
||||
// public GuiTestRenderer(GuiScreen targetScreen)
|
||||
// : base(targetScreen)
|
||||
// {
|
||||
// }
|
||||
|
||||
// protected override void DrawControl(TestDrawer drawer, GuiControl control)
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
|
||||
//public class TestDrawer
|
||||
//{
|
||||
//}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);KNI</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\source\MonoGame.Extended.Gui\KNI.Extended.Gui.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,7 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\source\MonoGame.Extended.Gui\MonoGame.Extended.Gui.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user