From 1f740387eb38eb94bffb341d05d8cd51628b1b65 Mon Sep 17 00:00:00 2001 From: "J. Zebedee" Date: Sun, 10 Oct 2021 22:14:55 -0500 Subject: [PATCH 001/103] Target .NET Framework 4.8 --- .../FunctionalFun.UI.Behaviors.csproj | 174 ++--- NtfsReader/NtfsReader.csproj | 198 +++--- .../WinDirStat.Net.Wpf.Base.csproj | 2 +- .../WinDirStat.Net.Wpf.Single.csproj | 652 +++++++++--------- 4 files changed, 514 insertions(+), 512 deletions(-) diff --git a/FunctionalFun.UI.Behaviours/FunctionalFun.UI.Behaviors.csproj b/FunctionalFun.UI.Behaviours/FunctionalFun.UI.Behaviors.csproj index 1f356bd..8100f95 100644 --- a/FunctionalFun.UI.Behaviours/FunctionalFun.UI.Behaviors.csproj +++ b/FunctionalFun.UI.Behaviours/FunctionalFun.UI.Behaviors.csproj @@ -1,94 +1,94 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {7DA5A107-B474-4AC0-B861-63A489DB0C02} - Library - Properties - FunctionalFun.UI.Behaviors - FunctionalFun.UI.Behaviors - v4.6.2 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - - - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - 3.5 - - - - - - - - - Code - - - - - - - False - .NET Framework 3.5 SP1 - true - - - + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {7DA5A107-B474-4AC0-B861-63A489DB0C02} + Library + Properties + FunctionalFun.UI.Behaviors + FunctionalFun.UI.Behaviors + v4.8 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + + + + + + 3.5 + + + + + + + + + Code + + + + + + + False + .NET Framework 3.5 SP1 + true + + + + --> \ No newline at end of file diff --git a/NtfsReader/NtfsReader.csproj b/NtfsReader/NtfsReader.csproj index 6a7b6dd..940ded4 100644 --- a/NtfsReader/NtfsReader.csproj +++ b/NtfsReader/NtfsReader.csproj @@ -1,106 +1,106 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {DBACEFC5-0234-4317-B096-F212ECAE1DD1} - Library - Properties - NtfsReader - NtfsReader - v4.6.1 - 512 - - - true - NtfsReader.snk - - - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - false - - - - - - - - - - - - - - NtfsReader.cs - - - NtfsReader.cs - - - NtfsReader.cs - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 - true - - - + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {DBACEFC5-0234-4317-B096-F212ECAE1DD1} + Library + Properties + NtfsReader + NtfsReader + v4.8 + 512 + + + true + NtfsReader.snk + + + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + false + + + + + + + + + + + + + + NtfsReader.cs + + + NtfsReader.cs + + + NtfsReader.cs + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 + true + + + + --> \ No newline at end of file diff --git a/WinDirStat.Net.Wpf.Base/WinDirStat.Net.Wpf.Base.csproj b/WinDirStat.Net.Wpf.Base/WinDirStat.Net.Wpf.Base.csproj index 3476f38..24114b4 100644 --- a/WinDirStat.Net.Wpf.Base/WinDirStat.Net.Wpf.Base.csproj +++ b/WinDirStat.Net.Wpf.Base/WinDirStat.Net.Wpf.Base.csproj @@ -1,7 +1,7 @@  - net462 + net48 WinDirStat.Net true latest diff --git a/WinDirStat.Net.Wpf.Single/WinDirStat.Net.Wpf.Single.csproj b/WinDirStat.Net.Wpf.Single/WinDirStat.Net.Wpf.Single.csproj index 352e7cf..e76a09d 100644 --- a/WinDirStat.Net.Wpf.Single/WinDirStat.Net.Wpf.Single.csproj +++ b/WinDirStat.Net.Wpf.Single/WinDirStat.Net.Wpf.Single.csproj @@ -1,326 +1,328 @@ - - - - - Debug - AnyCPU - {DA620261-55E4-4382-8866-168D958A3BE7} - WinExe - WinDirStat.Net.Wpf - WinDirStat.Net - v4.6.2 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - true - true - - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - latest - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - latest - - - Resources\App.ico - - - Properties\App.manifest - - - - - - - - - - - 4.0 - - - - - - - - - MSBuild:Compile - Designer - - - - - - - - - - - - - - - - - - - - - - - - - GraphView.xaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DriveSelectDialog.xaml - - - ErrorMessageBox.xaml - - - - ConfigureDialog.xaml - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - App.xaml - Code - - - MainWindow.xaml - Code - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - - - Code - - - - - - {7da5a107-b474-4ac0-b861-63a489db0c02} - FunctionalFun.UI.Behaviors - - - {ef57db12-06c2-4441-ba5e-56aeb8e0b907} - WinDirStat.Net.Wpf.Base - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.0.1 - - - 5.4.1.1 - - - 1.0.0 - - - 1.0.0 - - - 1.6.2 - - - + + + + + Debug + AnyCPU + {DA620261-55E4-4382-8866-168D958A3BE7} + WinExe + WinDirStat.Net.Wpf + WinDirStat.Net + v4.8 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + true + + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + latest + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + latest + + + Resources\App.ico + + + Properties\App.manifest + + + + + + + + + + + 4.0 + + + + + + + + + MSBuild:Compile + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + GraphView.xaml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DriveSelectDialog.xaml + + + ErrorMessageBox.xaml + + + + ConfigureDialog.xaml + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + Code + + + + + + {7da5a107-b474-4ac0-b861-63a489db0c02} + FunctionalFun.UI.Behaviors + + + {ef57db12-06c2-4441-ba5e-56aeb8e0b907} + WinDirStat.Net.Wpf.Base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0.1 + + + 5.4.1.1 + + + 1.0.0 + + + 1.0.0 + + + 1.6.2 + + + \ No newline at end of file From 3db991169a8f06537cb6558237cd42afea4825a3 Mon Sep 17 00:00:00 2001 From: "J. Zebedee" Date: Sun, 10 Oct 2021 22:16:00 -0500 Subject: [PATCH 002/103] Clean up configuration profiles Removed the extra "Wpf debug" and "Wpf release" configurations, as well as fixing the NtfsReader being set to Release in the default Debug profile --- WinDirStat.Net.sln | 200 +++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 117 deletions(-) diff --git a/WinDirStat.Net.sln b/WinDirStat.Net.sln index 1575a62..17d05c9 100644 --- a/WinDirStat.Net.sln +++ b/WinDirStat.Net.sln @@ -1,117 +1,83 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2042 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net", "WinDirStat.Net\WinDirStat.Net.csproj", "{7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NtfsReader", "NtfsReader\NtfsReader.csproj", "{DBACEFC5-0234-4317-B096-F212ECAE1DD1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunctionalFun.UI.Behaviors", "FunctionalFun.UI.Behaviours\FunctionalFun.UI.Behaviors.csproj", "{7DA5A107-B474-4AC0-B861-63A489DB0C02}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Base", "WinDirStat.Net.Base\WinDirStat.Net.Base.csproj", "{0ED71F8B-0797-468B-8420-2E2879DA2302}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Windows", "WinDirStat.Net.Windows\WinDirStat.Net.Windows.csproj", "{6416AA44-0296-4FF8-B408-A39A6C80DC2B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net.Wpf", "WinDirStat.Net.Wpf\WinDirStat.Net.Wpf.csproj", "{BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Wpf.Base", "WinDirStat.Net.Wpf.Base\WinDirStat.Net.Wpf.Base.csproj", "{EF57DB12-06C2-4441-BA5E-56AEB8E0B907}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net.Wpf.Single", "WinDirStat.Net.Wpf.Single\WinDirStat.Net.Wpf.Single.csproj", "{DA620261-55E4-4382-8866-168D958A3BE7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{46B0460D-2FF3-421B-843A-C44A4599B51B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Old", "Old", "{4CC41450-EB44-4066-93B5-BD8C3A3130DD}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - Wpf Debug|Any CPU = Wpf Debug|Any CPU - Wpf Release|Any CPU = Wpf Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Release|Any CPU.Build.0 = Release|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Wpf Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Wpf Debug|Any CPU.Build.0 = Debug|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Wpf Release|Any CPU.ActiveCfg = Release|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Wpf Release|Any CPU.Build.0 = Release|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Debug|Any CPU.ActiveCfg = Release|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Debug|Any CPU.Build.0 = Release|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Release|Any CPU.Build.0 = Release|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Wpf Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Wpf Debug|Any CPU.Build.0 = Debug|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Wpf Release|Any CPU.ActiveCfg = Release|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Wpf Release|Any CPU.Build.0 = Release|Any CPU - {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Release|Any CPU.Build.0 = Release|Any CPU - {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Wpf Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Wpf Debug|Any CPU.Build.0 = Debug|Any CPU - {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Wpf Release|Any CPU.ActiveCfg = Release|Any CPU - {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Wpf Release|Any CPU.Build.0 = Release|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Release|Any CPU.Build.0 = Release|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Wpf Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Wpf Debug|Any CPU.Build.0 = Debug|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Wpf Release|Any CPU.ActiveCfg = Release|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Wpf Release|Any CPU.Build.0 = Release|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Release|Any CPU.Build.0 = Release|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Wpf Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Wpf Debug|Any CPU.Build.0 = Debug|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Wpf Release|Any CPU.ActiveCfg = Release|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Wpf Release|Any CPU.Build.0 = Release|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Release|Any CPU.Build.0 = Release|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Wpf Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Wpf Debug|Any CPU.Build.0 = Debug|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Wpf Release|Any CPU.ActiveCfg = Release|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Wpf Release|Any CPU.Build.0 = Release|Any CPU - {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Release|Any CPU.Build.0 = Release|Any CPU - {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Wpf Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Wpf Debug|Any CPU.Build.0 = Debug|Any CPU - {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Wpf Release|Any CPU.ActiveCfg = Release|Any CPU - {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Wpf Release|Any CPU.Build.0 = Release|Any CPU - {DA620261-55E4-4382-8866-168D958A3BE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA620261-55E4-4382-8866-168D958A3BE7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA620261-55E4-4382-8866-168D958A3BE7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA620261-55E4-4382-8866-168D958A3BE7}.Release|Any CPU.Build.0 = Release|Any CPU - {DA620261-55E4-4382-8866-168D958A3BE7}.Wpf Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA620261-55E4-4382-8866-168D958A3BE7}.Wpf Debug|Any CPU.Build.0 = Debug|Any CPU - {DA620261-55E4-4382-8866-168D958A3BE7}.Wpf Release|Any CPU.ActiveCfg = Release|Any CPU - {DA620261-55E4-4382-8866-168D958A3BE7}.Wpf Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} - {DBACEFC5-0234-4317-B096-F212ECAE1DD1} = {46B0460D-2FF3-421B-843A-C44A4599B51B} - {7DA5A107-B474-4AC0-B861-63A489DB0C02} = {46B0460D-2FF3-421B-843A-C44A4599B51B} - {0ED71F8B-0797-468B-8420-2E2879DA2302} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} - {6416AA44-0296-4FF8-B408-A39A6C80DC2B} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.Common.6.0.1304.0\lib\NET45 - SolutionGuid = {A93EEC7D-680B-4135-9261-B4201D37538C} - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31717.71 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net", "WinDirStat.Net\WinDirStat.Net.csproj", "{7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NtfsReader", "NtfsReader\NtfsReader.csproj", "{DBACEFC5-0234-4317-B096-F212ECAE1DD1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunctionalFun.UI.Behaviors", "FunctionalFun.UI.Behaviours\FunctionalFun.UI.Behaviors.csproj", "{7DA5A107-B474-4AC0-B861-63A489DB0C02}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Base", "WinDirStat.Net.Base\WinDirStat.Net.Base.csproj", "{0ED71F8B-0797-468B-8420-2E2879DA2302}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Windows", "WinDirStat.Net.Windows\WinDirStat.Net.Windows.csproj", "{6416AA44-0296-4FF8-B408-A39A6C80DC2B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net.Wpf", "WinDirStat.Net.Wpf\WinDirStat.Net.Wpf.csproj", "{BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Wpf.Base", "WinDirStat.Net.Wpf.Base\WinDirStat.Net.Wpf.Base.csproj", "{EF57DB12-06C2-4441-BA5E-56AEB8E0B907}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net.Wpf.Single", "WinDirStat.Net.Wpf.Single\WinDirStat.Net.Wpf.Single.csproj", "{DA620261-55E4-4382-8866-168D958A3BE7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{46B0460D-2FF3-421B-843A-C44A4599B51B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Old", "Old", "{4CC41450-EB44-4066-93B5-BD8C3A3130DD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Release|Any CPU.Build.0 = Release|Any CPU + {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Release|Any CPU.Build.0 = Release|Any CPU + {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Release|Any CPU.Build.0 = Release|Any CPU + {0ED71F8B-0797-468B-8420-2E2879DA2302}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0ED71F8B-0797-468B-8420-2E2879DA2302}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0ED71F8B-0797-468B-8420-2E2879DA2302}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0ED71F8B-0797-468B-8420-2E2879DA2302}.Release|Any CPU.Build.0 = Release|Any CPU + {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Release|Any CPU.Build.0 = Release|Any CPU + {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Release|Any CPU.Build.0 = Release|Any CPU + {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Release|Any CPU.Build.0 = Release|Any CPU + {DA620261-55E4-4382-8866-168D958A3BE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA620261-55E4-4382-8866-168D958A3BE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA620261-55E4-4382-8866-168D958A3BE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA620261-55E4-4382-8866-168D958A3BE7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} + {DBACEFC5-0234-4317-B096-F212ECAE1DD1} = {46B0460D-2FF3-421B-843A-C44A4599B51B} + {7DA5A107-B474-4AC0-B861-63A489DB0C02} = {46B0460D-2FF3-421B-843A-C44A4599B51B} + {0ED71F8B-0797-468B-8420-2E2879DA2302} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} + {6416AA44-0296-4FF8-B408-A39A6C80DC2B} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} + {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.Common.6.0.1304.0\lib\NET45 + SolutionGuid = {A93EEC7D-680B-4135-9261-B4201D37538C} + EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection +EndGlobal From 4b8d97033e33465fd5dd1a5ac3bb57338b5aeaa7 Mon Sep 17 00:00:00 2001 From: "J. Zebedee" Date: Sun, 10 Oct 2021 22:19:39 -0500 Subject: [PATCH 003/103] Remove app.config and None-action files --- .../WinDirStat.Net.Wpf.Single.csproj | 3 - .../Controls/FocusExtension - Copy.cs | 68 ------------------- 2 files changed, 71 deletions(-) delete mode 100644 WinDirStat.Net.Wpf/Controls/FocusExtension - Copy.cs diff --git a/WinDirStat.Net.Wpf.Single/WinDirStat.Net.Wpf.Single.csproj b/WinDirStat.Net.Wpf.Single/WinDirStat.Net.Wpf.Single.csproj index e76a09d..0e761b6 100644 --- a/WinDirStat.Net.Wpf.Single/WinDirStat.Net.Wpf.Single.csproj +++ b/WinDirStat.Net.Wpf.Single/WinDirStat.Net.Wpf.Single.csproj @@ -16,7 +16,6 @@ true - AnyCPU @@ -85,8 +84,6 @@ - - diff --git a/WinDirStat.Net.Wpf/Controls/FocusExtension - Copy.cs b/WinDirStat.Net.Wpf/Controls/FocusExtension - Copy.cs deleted file mode 100644 index 9fcdf71..0000000 --- a/WinDirStat.Net.Wpf/Controls/FocusExtension - Copy.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; - -namespace WinDirStat.Net.Wpf.Controls { - public static class FocusExtension { - public static bool? GetIsFocused(DependencyObject obj) { - return (bool?) obj.GetValue(IsFocusedProperty); - } - - public static void SetIsFocused(DependencyObject obj, bool? value) { - obj.SetValue(IsFocusedProperty, value); - } - - public static readonly DependencyProperty IsFocusedProperty = - DependencyProperty.RegisterAttached( - "IsFocused", typeof(bool?), typeof(FocusExtension), - new FrameworkPropertyMetadata(null, OnIsFocusedPropertyChanged)); - - private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - FrameworkElement element = (FrameworkElement) d; - if (e.OldValue == null) { - element.GotFocus += OnGotFocus; - element.LostFocus += OnLostFocus; - element.GotKeyboardFocus += OnGotKeyboardFocus; - element.LostKeyboardFocus += OnLostKeyboardFocus; - } - else if (e.NewValue == null) { - element.GotFocus -= OnGotFocus; - element.LostFocus -= OnLostFocus; - element.GotKeyboardFocus -= OnGotKeyboardFocus; - element.LostKeyboardFocus -= OnLostKeyboardFocus; - } - - if (((bool?) e.NewValue) ?? false) { - element.Focus(); // Don't care about false values. - //Keyboard.Focus(element); - } - } - - private static void OnGotFocus(object sender, RoutedEventArgs e) { - FrameworkElement element = (FrameworkElement) sender; - Console.WriteLine("GotFocus"); - SetIsFocused(element, true); - } - private static void OnLostFocus(object sender, RoutedEventArgs e) { - FrameworkElement element = (FrameworkElement) sender; - Console.WriteLine("LostFocus"); - SetIsFocused(element, false); - } - - private static void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { - FrameworkElement element = (FrameworkElement) sender; - //SetIsFocused(element, true); - Console.WriteLine("LostKeyboardFocus"); - } - - private static void OnLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { - FrameworkElement element = (FrameworkElement) sender; - //SetIsFocused(element, false); - Console.WriteLine("GotKeyboardFocus"); - } - } -} From d5bf7506531444ccdd1dc7ae248f6960c38df053 Mon Sep 17 00:00:00 2001 From: "J. Zebedee" Date: Sun, 10 Oct 2021 22:39:33 -0500 Subject: [PATCH 004/103] Remove old projects from solution --- WinDirStat.Net.sln | 44 +++++++------------------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/WinDirStat.Net.sln b/WinDirStat.Net.sln index 17d05c9..82ecaf2 100644 --- a/WinDirStat.Net.sln +++ b/WinDirStat.Net.sln @@ -3,25 +3,15 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31717.71 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net", "WinDirStat.Net\WinDirStat.Net.csproj", "{7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NtfsReader", "NtfsReader\NtfsReader.csproj", "{DBACEFC5-0234-4317-B096-F212ECAE1DD1}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunctionalFun.UI.Behaviors", "FunctionalFun.UI.Behaviours\FunctionalFun.UI.Behaviors.csproj", "{7DA5A107-B474-4AC0-B861-63A489DB0C02}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Base", "WinDirStat.Net.Base\WinDirStat.Net.Base.csproj", "{0ED71F8B-0797-468B-8420-2E2879DA2302}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Windows", "WinDirStat.Net.Windows\WinDirStat.Net.Windows.csproj", "{6416AA44-0296-4FF8-B408-A39A6C80DC2B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net.Wpf", "WinDirStat.Net.Wpf\WinDirStat.Net.Wpf.csproj", "{BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinDirStat.Net.Wpf.Base", "WinDirStat.Net.Wpf.Base\WinDirStat.Net.Wpf.Base.csproj", "{EF57DB12-06C2-4441-BA5E-56AEB8E0B907}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinDirStat.Net.Wpf.Single", "WinDirStat.Net.Wpf.Single\WinDirStat.Net.Wpf.Single.csproj", "{DA620261-55E4-4382-8866-168D958A3BE7}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{46B0460D-2FF3-421B-843A-C44A4599B51B}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Old", "Old", "{4CC41450-EB44-4066-93B5-BD8C3A3130DD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NtfsReader", "NtfsReader\NtfsReader.csproj", "{57FD4ACE-28E4-4BCC-9E94-8DE342213A6A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -29,30 +19,10 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7}.Release|Any CPU.Build.0 = Release|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DBACEFC5-0234-4317-B096-F212ECAE1DD1}.Release|Any CPU.Build.0 = Release|Any CPU {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Debug|Any CPU.Build.0 = Debug|Any CPU {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Release|Any CPU.ActiveCfg = Release|Any CPU {7DA5A107-B474-4AC0-B861-63A489DB0C02}.Release|Any CPU.Build.0 = Release|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0ED71F8B-0797-468B-8420-2E2879DA2302}.Release|Any CPU.Build.0 = Release|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6416AA44-0296-4FF8-B408-A39A6C80DC2B}.Release|Any CPU.Build.0 = Release|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605}.Release|Any CPU.Build.0 = Release|Any CPU {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Debug|Any CPU.Build.0 = Debug|Any CPU {EF57DB12-06C2-4441-BA5E-56AEB8E0B907}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -61,21 +31,21 @@ Global {DA620261-55E4-4382-8866-168D958A3BE7}.Debug|Any CPU.Build.0 = Debug|Any CPU {DA620261-55E4-4382-8866-168D958A3BE7}.Release|Any CPU.ActiveCfg = Release|Any CPU {DA620261-55E4-4382-8866-168D958A3BE7}.Release|Any CPU.Build.0 = Release|Any CPU + {57FD4ACE-28E4-4BCC-9E94-8DE342213A6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {57FD4ACE-28E4-4BCC-9E94-8DE342213A6A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57FD4ACE-28E4-4BCC-9E94-8DE342213A6A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {57FD4ACE-28E4-4BCC-9E94-8DE342213A6A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {7577AAA1-EF63-40F5-BFC1-EB8BA1F46FD7} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} - {DBACEFC5-0234-4317-B096-F212ECAE1DD1} = {46B0460D-2FF3-421B-843A-C44A4599B51B} {7DA5A107-B474-4AC0-B861-63A489DB0C02} = {46B0460D-2FF3-421B-843A-C44A4599B51B} - {0ED71F8B-0797-468B-8420-2E2879DA2302} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} - {6416AA44-0296-4FF8-B408-A39A6C80DC2B} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605} = {4CC41450-EB44-4066-93B5-BD8C3A3130DD} + {57FD4ACE-28E4-4BCC-9E94-8DE342213A6A} = {46B0460D-2FF3-421B-843A-C44A4599B51B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.Common.6.0.1304.0\lib\NET45 SolutionGuid = {A93EEC7D-680B-4135-9261-B4201D37538C} + EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.Common.6.0.1304.0\lib\NET45 EndGlobalSection GlobalSection(Performance) = preSolution HasPerformanceSessions = true From c0db368c0e01b6bd7d037e83a1953ac349008742 Mon Sep 17 00:00:00 2001 From: "J. Zebedee" Date: Sun, 10 Oct 2021 22:41:17 -0500 Subject: [PATCH 005/103] Remove old projects from disk --- WinDirStat.Net.Base/Model/Drives/DriveItem.cs | 87 -- .../Model/Drives/DriveItems.cs | 75 -- .../Model/Drives/Misc/DriveSelectMode.cs | 22 - .../Model/Drives/Misc/DriveSelectResult.cs | 62 - .../Model/Extensions/ExtensionItem.cs | 277 ---- .../Model/Extensions/ExtensionItems.cs | 230 ---- .../Extensions/Misc/ExtensionItemEvents.cs | 53 - WinDirStat.Net.Base/Model/Files/FileItem.cs | 90 -- .../Model/Files/FileItemBase.cs | 596 --------- WinDirStat.Net.Base/Model/Files/FolderItem.cs | 1142 ----------------- .../Model/Files/FreeSpaceItem.cs | 84 -- .../Model/Files/Misc/FileItemEnums.cs | 135 -- .../Model/Files/Misc/FileItemEvent.cs | 97 -- .../Model/Files/Misc/IScanFileInfo.cs | 42 - WinDirStat.Net.Base/Model/Files/RootItem.cs | 230 ---- .../Model/Files/UnknownItem.cs | 90 -- .../ObservableCollectionObject.cs | 230 ---- WinDirStat.Net.Base/ObservableObjectEx.cs | 23 - .../ObservablePropertyCollectionObject.cs | 223 ---- .../ObservableVolatileObject.cs | 45 - .../Rendering/BetterTreemapOptions.cs | 85 -- WinDirStat.Net.Base/Rendering/ColorSpace.cs | 114 -- WinDirStat.Net.Base/Rendering/ITreemapItem.cs | 26 - .../Rendering/PreviewTreemapItem.cs | 179 --- .../Rendering/TreemapOptions.cs | 81 -- .../Rendering/TreemapRenderer.DrawChildren.cs | 192 --- .../Rendering/TreemapRenderer.Highlighting.cs | 103 -- .../Rendering/TreemapRenderer.KDirStat.cs | 190 --- .../Rendering/TreemapRenderer.Sequoia.cs | 21 - .../Rendering/TreemapRenderer.cs | 166 --- .../Rendering/TreemapRendererFactory.cs | 32 - WinDirStat.Net.Base/Rendering/TreemapStyle.cs | 24 - .../Services/IBitmapFactory.cs | 60 - .../Services/IClipboardService.cs | 24 - .../Services/IIconCacheService.cs | 78 -- .../Services/IImagesService.cs | 27 - .../Services/IMainCommandInfoService.cs | 58 - WinDirStat.Net.Base/Services/IOSService.cs | 110 -- .../Services/IScanningService.cs | 59 - .../Services/ISettingsService.cs | 56 - .../Services/IShortcutsService.cs | 56 - WinDirStat.Net.Base/Services/IUIService.cs | 61 - .../Services/IWindowDialogService.cs | 69 - .../Services/ImagesServiceBase.cs | 141 -- .../Implementation/CommandInfoService.cs | 30 - .../Implementation/RelayCommandService.cs | 59 - .../Implementation/ScanningService.cs | 895 ------------- .../SettingsService.Defaults.cs | 86 -- .../Implementation/SettingsService.cs | 339 ----- .../Services/RelayCommandService.cs | 59 - .../Services/Structures/IBrush.cs | 12 - .../Services/Structures/IControl.cs | 25 - .../Services/Structures/IImage.cs | 48 - .../Structures/IRelayCommandInfo.Generic.cs | 23 - .../Services/Structures/IRelayCommandInfo.cs | 23 - .../Structures/IRelayUICommandInfo.Generic.cs | 14 - .../Structures/IRelayUICommandInfo.cs | 14 - .../Services/Structures/IShortcut.cs | 15 - .../Services/Structures/IUITimer.cs | 29 - .../Services/Structures/IWindow.cs | 42 - .../Structures/Implementation/IconCache.cs | 60 - .../Structures/Implementation/Message.cs | 33 - .../Implementation/RecyleBinInfo.cs | 37 - .../Structures/Implementation/Scanning.cs | 68 - WinDirStat.Net.Base/StringConstants.cs | 17 - WinDirStat.Net.Base/Structures/Point2D.cs | 275 ---- WinDirStat.Net.Base/Structures/Point2F.cs | 265 ---- WinDirStat.Net.Base/Structures/Point2I.cs | 168 --- WinDirStat.Net.Base/Structures/Rectangle2I.cs | 152 --- WinDirStat.Net.Base/Structures/Rectangle2S.cs | 76 -- WinDirStat.Net.Base/Structures/Rgb24Color.cs | 55 - WinDirStat.Net.Base/Structures/Rgba32Color.cs | 142 -- WinDirStat.Net.Base/Utils/ArrayExtensions.cs | 598 --------- .../Utils/CommandExtensions.cs | 23 - WinDirStat.Net.Base/Utils/Enumerator.cs | 100 -- WinDirStat.Net.Base/Utils/FormatBytes.cs | 101 -- WinDirStat.Net.Base/Utils/ListExtensions.cs | 56 - WinDirStat.Net.Base/Utils/MathUtils.cs | 75 -- WinDirStat.Net.Base/Utils/PathUtils.cs | 549 -------- .../Utils/Volatiles/IVolatile.cs | 37 - .../Utils/Volatiles/Volatile.cs | 119 -- .../Utils/Volatiles/VolatileBoolean.cs | 64 - .../Utils/Volatiles/VolatileCompound.cs | 116 -- .../Utils/Volatiles/VolatileDouble.cs | 102 -- .../Utils/Volatiles/VolatileInt16.cs | 81 -- .../Utils/Volatiles/VolatileInt32.cs | 81 -- .../Utils/Volatiles/VolatileInt64.cs | 81 -- .../Utils/Volatiles/VolatileSingle.cs | 102 -- .../ViewModel/Commands/IRelayCommand.cs | 25 - .../ViewModel/Commands/IRelayUICommand.cs | 13 - .../Commands/RelayUICommand.Generic.cs | 101 -- .../ViewModel/Commands/RelayUICommand.cs | 101 -- .../ViewModel/Comparers/DriveComparer.cs | 107 -- .../ViewModel/Comparers/ExtensionComparer.cs | 85 -- .../ViewModel/Comparers/FileComparer.cs | 104 -- .../ViewModel/Comparers/SortComparer.cs | 134 -- .../ViewModel/ConfigureViewModel.cs | 45 - .../DriveSelectViewModel.Commands.cs | 44 - .../ViewModel/DriveSelectViewModel.Methods.cs | 31 - .../ViewModel/DriveSelectViewModel.cs | 167 --- .../ViewModel/Drives/DriveItemViewModel.cs | 94 -- .../Drives/DriveItemViewModelCollection.cs | 137 -- .../Extensions/ExtensionItemViewModel.cs | 191 --- .../ExtensionItemViewModelCollection.cs | 208 --- .../Collection/FileItemViewModelCollection.cs | 394 ------ .../IReadOnlyFileItemViewModelCollection.cs | 16 - .../Files/FileItemViewModel.Flags.cs | 47 - .../Files/FileItemViewModel.FlatList.cs | 402 ------ .../Files/FileItemViewModel.TreeNode.cs | 771 ----------- .../ViewModel/Files/FileItemViewModel.cs | 657 ---------- .../ViewModel/Files/FileItemViewModelFlags.cs | 43 - .../ViewModel/Files/FileTreeFlattener.cs | 194 --- .../ViewModel/Files/FileTreeTraversal.cs | 66 - .../ViewModel/Graph/FileGraphViewModel.cs | 257 ---- .../ViewModel/Graph/GraphViewModel.cs | 419 ------ .../ViewModel/MainViewModel.Commands.cs | 361 ------ .../ViewModel/MainViewModel.Methods.cs | 60 - .../ViewModel/MainViewModel.cs | 387 ------ .../ViewModel/ViewModelCommandBase.cs | 237 ---- .../ViewModel/ViewModelControlBase.cs | 25 - .../ViewModel/ViewModelWindowBase.cs | 32 - .../WinDirStat.Net.Base.csproj | 109 -- .../Native/Win32.FindFile.cs | 227 ---- .../Native/Win32.ImageList.cs | 59 - .../Native/Win32.RecycleBin.cs | 80 -- .../Native/Win32.SHFileOperation.cs | 81 -- .../Native/Win32.SHGetFileInfo.cs | 114 -- .../Native/Win32.SHGetStockIconInfo.cs | 143 --- WinDirStat.Net.Windows/Native/Win32.Shell.cs | 104 -- .../Native/Win32.ShellExecute.cs | 84 -- .../Native/Win32.Windows.cs | 70 - WinDirStat.Net.Windows/Native/Win32.cs | 98 -- .../Native/Win32Extensions.cs | 24 - .../Structures/WindowsScanFileInfo.cs | 71 - .../Services/WindowsIconCacheService.cs | 387 ------ .../Services/WindowsOSService.cs | 241 ---- .../Services/WindowsScanningService.Mft.cs | 165 --- .../Services/WindowsScanningService.Native.cs | 102 -- .../WindowsScanningService.Refresh.cs | 146 --- .../Services/WindowsScanningService.cs | 220 ---- .../WinDirStat.Net.Windows.csproj | 49 - WinDirStat.Net.Wpf/App.config | 6 - WinDirStat.Net.Wpf/App.ico | Bin 321053 -> 0 bytes WinDirStat.Net.Wpf/App.xaml | 17 - WinDirStat.Net.Wpf/App.xaml.cs | 14 - WinDirStat.Net.Wpf/Controls/CommandButton.cs | 98 -- .../Controls/CommandMenuItem.cs | 112 -- .../Controls/FileList/EditTextBox.cs | 91 -- .../Controls/FileList/ExtensionMethods.cs | 47 - .../Controls/FileList/FileGridView.cs | 42 - .../Controls/FileList/FileTreeNodeView.cs | 165 --- .../Controls/FileList/FileTreeView.cs | 711 ---------- .../Controls/FileList/FileTreeViewItem.cs | 139 -- .../Controls/FileList/GeneralAdorner.cs | 73 -- .../Controls/FileList/InsertMarker.cs | 33 - .../Controls/FileList/LinesRenderer.cs | 68 - .../Controls/FlashyProgressBar.cs | 12 - WinDirStat.Net.Wpf/Controls/FocusBehavior.cs | 88 -- WinDirStat.Net.Wpf/Controls/FocusExtension.cs | 112 -- WinDirStat.Net.Wpf/Controls/GraphView.xaml | 34 - WinDirStat.Net.Wpf/Controls/GraphView.xaml.cs | 506 -------- WinDirStat.Net.Wpf/Controls/ImageButton.cs | 63 - WinDirStat.Net.Wpf/Controls/ImageMenuItem.cs | 73 -- WinDirStat.Net.Wpf/Controls/ListSettings.cs | 23 - WinDirStat.Net.Wpf/Controls/PercentageBar.cs | 66 - WinDirStat.Net.Wpf/Controls/RelayUIBinding.cs | 36 - .../Controls/SortList/SortListView.cs | 352 ----- .../Controls/SortList/SortView.cs | 61 - .../Controls/SortList/SortViewColumn.cs | 180 --- .../Controls/SortList/SortViewKeys.cs | 47 - .../Controls/SubtreePercentage.cs | 117 -- .../Controls/VisibleColumnDefinition.cs | 81 -- .../Controls/VisibleRowDefinition.cs | 81 -- .../Converters/AttributesFormatter.cs | 33 - .../Converters/ByteFormatter.cs | 28 - .../Converters/CollapsedWhenBoolean.cs | 43 - .../Converters/DirectoryExistsToBoolean.cs | 34 - .../Converters/FileTimeFormatter.cs | 32 - .../Converters/InverseBoolean.cs | 26 - .../Converters/ItemCountFormatter.cs | 30 - .../Converters/RadioButtonConverter.cs | 34 - .../Converters/ScaleConverter.cs | 34 - .../Converters/ScanTimeFormatter.cs | 34 - .../Converters/TextToHorizontalAlignment.cs | 43 - .../Converters/ZeroGridLengthWhenBoolean.cs | 42 - .../Converters/ZeroWhenBoolean.cs | 37 - WinDirStat.Net.Wpf/MainWindow.xaml | 555 -------- WinDirStat.Net.Wpf/MainWindow.xaml.cs | 78 -- WinDirStat.Net.Wpf/Properties/App.manifest | 76 -- WinDirStat.Net.Wpf/Properties/AssemblyInfo.cs | 57 - .../Resources/FileIcons/FileCollection.png | Bin 488 -> 0 bytes .../Resources/FileIcons/FreeSpace.png | Bin 504 -> 0 bytes .../Resources/FileIcons/Missing.png | Bin 322 -> 0 bytes .../Resources/FileIcons/Shortcut.png | Bin 352 -> 0 bytes .../Resources/FileIcons/UnknownSpace.png | Bin 542 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Close.png | Bin 570 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Cmd.png | Bin 358 -> 0 bytes .../Resources/Icons/CmdElevated.png | Bin 537 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Copy.png | Bin 445 -> 0 bytes .../Resources/Icons/CopyPath.png | Bin 478 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Cut.png | Bin 555 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Delete.png | Bin 374 -> 0 bytes .../Resources/Icons/Elevate.png | Bin 532 -> 0 bytes .../Resources/Icons/EmptyRecycleBin.png | Bin 789 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Exit.png | Bin 213 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Expand.png | Bin 339 -> 0 bytes .../Resources/Icons/Explore.png | Bin 265 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Open.png | Bin 519 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Paste.png | Bin 546 -> 0 bytes .../Resources/Icons/PowerShell.png | Bin 707 -> 0 bytes .../Resources/Icons/PowerShellElevated.png | Bin 767 -> 0 bytes .../Resources/Icons/Properties.png | Bin 581 -> 0 bytes .../Resources/Icons/RecycleBin.png | Bin 854 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Redo.png | Bin 563 -> 0 bytes .../Resources/Icons/RefreshSelected.png | Bin 234 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Reload.png | Bin 612 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Run.png | Bin 374 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Save.png | Bin 499 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Search.png | Bin 558 -> 0 bytes .../Resources/Icons/Settings.png | Bin 520 -> 0 bytes .../Resources/Icons/ShowFileTypes.png | Bin 488 -> 0 bytes .../Resources/Icons/ShowTotalSpace.png | Bin 520 -> 0 bytes .../Resources/Icons/ShowTreemap.png | Bin 785 -> 0 bytes WinDirStat.Net.Wpf/Resources/Icons/Undo.png | Bin 572 -> 0 bytes .../Resources/ImageResources.cs | 11 - .../Services/ResourceImagesService.cs | 46 - .../Services/Structures/IWpfRelayCommand.cs | 18 - .../Services/Structures/WpfImage.cs | 140 -- .../Services/Structures/WpfRelayCommand.cs | 56 - .../Structures/WpfRelayCommandInfo.cs | 12 - .../Services/Structures/WpfRelayUICommand.cs | 50 - .../Services/Structures/WpfShortcut.cs | 42 - .../Services/Structures/WpfUITimer.cs | 95 -- .../Services/Structures/WpfWindow.cs | 90 -- .../Services/WpfBitmapFactory.cs | 115 -- .../Services/WpfClipboardService.cs | 25 - WinDirStat.Net.Wpf/Services/WpfUIService.cs | 112 -- .../Services/WpfWindowDialogService.cs | 132 -- WinDirStat.Net.Wpf/Themes/Generic.xaml | 751 ----------- WinDirStat.Net.Wpf/Themes/SortView.xaml | 129 -- .../Utils/DependencyObjectExtensions.cs | 23 - WinDirStat.Net.Wpf/Utils/WindowExtensions.cs | 47 - WinDirStat.Net.Wpf/Utils/WpfCasting.cs | 135 -- WinDirStat.Net.Wpf/Utils/WpfExtensions.cs | 66 - WinDirStat.Net.Wpf/Utils/WpfUtils.cs | 20 - .../ViewModel/ViewModelLocator.cs | 79 -- WinDirStat.Net.Wpf/WinDirStat.Net.Wpf.csproj | 317 ----- .../Windows/ConfigureDialog.xaml | 31 - .../Windows/ConfigureDialog.xaml.cs | 48 - .../Windows/DriveSelectDialog.xaml | 85 -- .../Windows/DriveSelectDialog.xaml.cs | 76 -- .../Windows/FolderBrowserDialog.cs | 174 --- WinDirStat.Net/App.config | 14 - WinDirStat.Net/App.ico | Bin 321053 -> 0 bytes WinDirStat.Net/App.xaml | 18 - WinDirStat.Net/App.xaml.cs | 15 - WinDirStat.Net/Controls/CommandButton.cs | 91 -- WinDirStat.Net/Controls/CommandMenuItem.cs | 108 -- WinDirStat.Net/Controls/FlashyProgressBar.cs | 12 - WinDirStat.Net/Controls/GraphView.xaml | 33 - WinDirStat.Net/Controls/GraphView.xaml.cs | 675 ---------- WinDirStat.Net/Controls/ImageButton.cs | 62 - WinDirStat.Net/Controls/ImageMenuItem.cs | 72 -- WinDirStat.Net/Controls/PercentageBar.cs | 66 - WinDirStat.Net/Controls/SubtreePercentage.cs | 115 -- .../Converters/AttributesFormatter.cs | 33 - WinDirStat.Net/Converters/ByteFormatter.cs | 28 - .../Converters/CollapsedWhenBoolean.cs | 43 - .../Converters/DirectoryExistsToBoolean.cs | 34 - .../Converters/EmptyWhenNegative.cs | 32 - .../Converters/RadioButtonConverter.cs | 34 - .../Converters/ScanTimeFormatter.cs | 35 - .../Converters/TextToHorizontalAlignment.cs | 43 - WinDirStat.Net/Converters/ZeroWhenBoolean.cs | 42 - WinDirStat.Net/Drawing/ColorSpace.cs | 126 -- WinDirStat.Net/Drawing/ITreemapItem.cs | 20 - WinDirStat.Net/Drawing/PreviewTreemapItem.cs | 127 -- WinDirStat.Net/Drawing/Treemap.cs | 972 -------------- WinDirStat.Net/Drawing/TreemapItem.cs | 167 --- .../Model/Data/Extensions/ExtensionRecord.cs | 160 --- .../Data/Extensions/ExtensionRecordEvents.cs | 23 - .../Model/Data/Extensions/ExtensionRecords.cs | 183 --- WinDirStat.Net/Model/Data/Nodes/FileNode.cs | 45 - .../Model/Data/Nodes/FileNodeBase.Flags.cs | 149 --- .../Model/Data/Nodes/FileNodeBase.cs | 333 ----- .../Model/Data/Nodes/FileNodeEvents.cs | 61 - .../Model/Data/Nodes/FileNodeFlags.cs | 82 -- .../Model/Data/Nodes/FolderNode.Flags.cs | 63 - WinDirStat.Net/Model/Data/Nodes/FolderNode.cs | 421 ------ .../Model/Data/Nodes/FreeSpaceNode.cs | 38 - WinDirStat.Net/Model/Data/Nodes/RootNode.cs | 184 --- .../Model/Data/Nodes/UnknownNode.cs | 38 - WinDirStat.Net/Model/Data/ScanState.cs | 48 - .../Model/Data/SelectDrivesModel.cs | 11 - .../Data/WinDirStatModel.Scanning.Mft.cs | 101 -- .../Data/WinDirStatModel.Scanning.Native.cs | 101 -- .../Data/WinDirStatModel.Scanning.Private.cs | 177 --- .../Model/Data/WinDirStatModel.Scanning.cs | 287 ----- WinDirStat.Net/Model/Data/WinDirStatModel.cs | 79 -- WinDirStat.Net/Model/IRelayUICommand.cs | 15 - WinDirStat.Net/Model/ObservableObject.cs | 63 - WinDirStat.Net/Model/RelayCommand.Generic.cs | 47 - WinDirStat.Net/Model/RelayCommand.cs | 55 - WinDirStat.Net/Model/RelayUIBinding.cs | 34 - .../Model/RelayUICommand.Generic.cs | 78 -- WinDirStat.Net/Model/RelayUICommand.cs | 100 -- .../Settings/WinDirStatSettings.Defaults.cs | 82 -- .../Model/Settings/WinDirStatSettings.IO.cs | 19 - .../Model/Settings/WinDirStatSettings.cs | 324 ----- .../Model/View/Comparers/DriveComparer.cs | 79 -- .../Model/View/Comparers/ExtensionComparer.cs | 62 - .../Model/View/Comparers/FileComparer.cs | 83 -- .../Model/View/Comparers/SortComparer.cs | 107 -- .../Model/View/DriveSelectViewModel.cs | 174 --- .../Drives/Collections/DriveCollection.cs | 59 - .../Model/View/Drives/DriveViewModel.cs | 70 - .../Extensions/ExtensionRecordViewModel.cs | 120 -- .../Extensions/ExtensionRecordsViewModel.cs | 206 --- WinDirStat.Net/Model/View/IconCache.Queue.cs | 105 -- WinDirStat.Net/Model/View/IconCache.cs | 419 ------ .../Collections/EmptyFileNodeCollection.cs | 91 -- .../Nodes/Collections/FileNodeCollection.cs | 263 ---- .../Nodes/Collections/IFileNodeCollection.cs | 21 - .../View/Nodes/FileNodeViewModel.Flags.cs | 39 - .../View/Nodes/FileNodeViewModel.FlatList.cs | 403 ------ .../View/Nodes/FileNodeViewModel.TreeNode.cs | 831 ------------ .../Model/View/Nodes/FileNodeViewModel.cs | 424 ------ .../View/Nodes/FileNodeViewModelFlags.cs | 30 - .../Model/View/Nodes/TreeFlattener.cs | 179 --- .../Model/View/Nodes/TreeTraversal.cs | 66 - .../View/WinDirStatViewModel.Commands.cs | 285 ---- .../Model/View/WinDirStatViewModel.Events.cs | 33 - .../View/WinDirStatViewModel.Scanning.cs | 53 - .../Model/View/WinDirStatViewModel.cs | 304 ----- WinDirStat.Net/Model/ViewModel.cs | 21 - WinDirStat.Net/Properties/App.manifest | 15 - WinDirStat.Net/Properties/AssemblyInfo.cs | 56 - .../Properties/Settings.Designer.cs | 26 - WinDirStat.Net/Properties/Settings.settings | 7 - WinDirStat.Net/Resources/DimmedGraph.png | Bin 167 -> 0 bytes .../Resources/FileIcons/FileCollection.png | Bin 488 -> 0 bytes .../Resources/FileIcons/FreeSpace.png | Bin 504 -> 0 bytes .../Resources/FileIcons/Shortcut.png | Bin 352 -> 0 bytes .../Resources/FileIcons/UnknownSpace.png | Bin 542 -> 0 bytes .../Resources/FileIcons/UnknownSpace2.png | Bin 520 -> 0 bytes WinDirStat.Net/Resources/Icons/Cmd.png | Bin 358 -> 0 bytes .../Resources/Icons/CmdElevated.png | Bin 537 -> 0 bytes WinDirStat.Net/Resources/Icons/Copy.png | Bin 445 -> 0 bytes WinDirStat.Net/Resources/Icons/Cut.png | Bin 555 -> 0 bytes WinDirStat.Net/Resources/Icons/Delete.png | Bin 374 -> 0 bytes .../Resources/Icons/DeleteFolder.png | Bin 570 -> 0 bytes .../Resources/Icons/DeleteRecycleBin.png | Bin 789 -> 0 bytes WinDirStat.Net/Resources/Icons/Elevate.png | Bin 532 -> 0 bytes WinDirStat.Net/Resources/Icons/Exit.png | Bin 213 -> 0 bytes WinDirStat.Net/Resources/Icons/Expand.png | Bin 339 -> 0 bytes WinDirStat.Net/Resources/Icons/Explore.png | Bin 265 -> 0 bytes WinDirStat.Net/Resources/Icons/Open.png | Bin 519 -> 0 bytes WinDirStat.Net/Resources/Icons/Paste.png | Bin 546 -> 0 bytes WinDirStat.Net/Resources/Icons/Path.png | Bin 478 -> 0 bytes WinDirStat.Net/Resources/Icons/PowerShell.png | Bin 707 -> 0 bytes .../Resources/Icons/PowerShellElevated.png | Bin 767 -> 0 bytes WinDirStat.Net/Resources/Icons/Properties.png | Bin 581 -> 0 bytes WinDirStat.Net/Resources/Icons/Recycle.png | Bin 854 -> 0 bytes WinDirStat.Net/Resources/Icons/Redo.png | Bin 563 -> 0 bytes .../Resources/Icons/RefreshSelected.png | Bin 245 -> 0 bytes WinDirStat.Net/Resources/Icons/Reload.png | Bin 612 -> 0 bytes WinDirStat.Net/Resources/Icons/Run.png | Bin 374 -> 0 bytes WinDirStat.Net/Resources/Icons/Save.png | Bin 499 -> 0 bytes WinDirStat.Net/Resources/Icons/Search.png | Bin 558 -> 0 bytes WinDirStat.Net/Resources/Icons/Settings.png | Bin 520 -> 0 bytes WinDirStat.Net/Resources/Icons/Undo.png | Bin 572 -> 0 bytes WinDirStat.Net/Resources/Images.cs | 83 -- WinDirStat.Net/Settings/Geometry/Point2F.cs | 426 ------ WinDirStat.Net/Settings/Geometry/Point2I.cs | 326 ----- .../Settings/Geometry/Rectangle2I.cs | 155 --- .../Settings/Geometry/Rectangle2S.cs | 99 -- .../Settings/Geometry/Rgb24Color.cs | 52 - .../Settings/Geometry/Rgba32Color.cs | 147 --- WinDirStat.Net/Settings/IconCacheMode.cs | 28 - WinDirStat.Net/Settings/TreemapOptions.cs | 83 -- WinDirStat.Net/Settings/TreemapStyle.cs | 24 - WinDirStat.Net/Sorting/SortListView.cs | 353 ----- WinDirStat.Net/Sorting/SortView.cs | 61 - WinDirStat.Net/Sorting/SortViewColumn.cs | 179 --- WinDirStat.Net/Sorting/SortViewKeys.cs | 59 - WinDirStat.Net/Themes/Generic.xaml | 716 ----------- WinDirStat.Net/Themes/SortView.xaml | 121 -- WinDirStat.Net/TreeView/EditTextBox.cs | 91 -- WinDirStat.Net/TreeView/ExtensionMethods.cs | 47 - WinDirStat.Net/TreeView/FileGridView.cs | 41 - WinDirStat.Net/TreeView/FileTreeNodeView.cs | 165 --- WinDirStat.Net/TreeView/FileTreeView.cs | 700 ---------- WinDirStat.Net/TreeView/FileTreeViewItem.cs | 139 -- WinDirStat.Net/TreeView/GeneralAdorner.cs | 73 -- WinDirStat.Net/TreeView/InsertMarker.cs | 33 - WinDirStat.Net/TreeView/LinesRenderer.cs | 68 - WinDirStat.Net/Utils/BitField16.cs | 161 --- WinDirStat.Net/Utils/BitField32.cs | 201 --- WinDirStat.Net/Utils/BitmapUtils.cs | 73 -- WinDirStat.Net/Utils/ByteFormatter.cs | 47 - WinDirStat.Net/Utils/EmptyEnumerator.cs | 51 - WinDirStat.Net/Utils/ListExtensions.cs | 29 - WinDirStat.Net/Utils/MathUtils.cs | 34 - WinDirStat.Net/Utils/Native/Win32.FindFile.cs | 226 ---- .../Utils/Native/Win32.ImageList.cs | 59 - .../Utils/Native/Win32.SHGetFileInfo.cs | 114 -- .../Utils/Native/Win32.SHGetStockIconInfo.cs | 141 -- WinDirStat.Net/Utils/Native/Win32.Shell.cs | 104 -- WinDirStat.Net/Utils/Native/Win32.Windows.cs | 70 - WinDirStat.Net/Utils/Native/Win32.cs | 70 - .../Utils/Native/Win32Extensions.cs | 19 - WinDirStat.Net/Utils/PathUtils.cs | 475 ------- WinDirStat.Net/Utils/SpeedTester.cs | 160 --- WinDirStat.Net/Utils/TimedLock.cs | 162 --- WinDirStat.Net/Utils/WindowExtensions.cs | 47 - WinDirStat.Net/Utils/WpfExtensions.cs | 23 - WinDirStat.Net/WinDirStat.Net.csproj | 308 ----- WinDirStat.Net/WinDirStatWindow.xaml | 502 -------- WinDirStat.Net/WinDirStatWindow.xaml.cs | 62 - WinDirStat.Net/Windows/DriveSelectDialog.xaml | 88 -- .../Windows/DriveSelectDialog.xaml.cs | 73 -- WinDirStat.Net/Windows/FolderBrowserDialog.cs | 174 --- 422 files changed, 46200 deletions(-) delete mode 100644 WinDirStat.Net.Base/Model/Drives/DriveItem.cs delete mode 100644 WinDirStat.Net.Base/Model/Drives/DriveItems.cs delete mode 100644 WinDirStat.Net.Base/Model/Drives/Misc/DriveSelectMode.cs delete mode 100644 WinDirStat.Net.Base/Model/Drives/Misc/DriveSelectResult.cs delete mode 100644 WinDirStat.Net.Base/Model/Extensions/ExtensionItem.cs delete mode 100644 WinDirStat.Net.Base/Model/Extensions/ExtensionItems.cs delete mode 100644 WinDirStat.Net.Base/Model/Extensions/Misc/ExtensionItemEvents.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/FileItem.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/FileItemBase.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/FolderItem.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/FreeSpaceItem.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/Misc/FileItemEnums.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/Misc/FileItemEvent.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/Misc/IScanFileInfo.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/RootItem.cs delete mode 100644 WinDirStat.Net.Base/Model/Files/UnknownItem.cs delete mode 100644 WinDirStat.Net.Base/ObservableCollectionObject.cs delete mode 100644 WinDirStat.Net.Base/ObservableObjectEx.cs delete mode 100644 WinDirStat.Net.Base/ObservablePropertyCollectionObject.cs delete mode 100644 WinDirStat.Net.Base/ObservableVolatileObject.cs delete mode 100644 WinDirStat.Net.Base/Rendering/BetterTreemapOptions.cs delete mode 100644 WinDirStat.Net.Base/Rendering/ColorSpace.cs delete mode 100644 WinDirStat.Net.Base/Rendering/ITreemapItem.cs delete mode 100644 WinDirStat.Net.Base/Rendering/PreviewTreemapItem.cs delete mode 100644 WinDirStat.Net.Base/Rendering/TreemapOptions.cs delete mode 100644 WinDirStat.Net.Base/Rendering/TreemapRenderer.DrawChildren.cs delete mode 100644 WinDirStat.Net.Base/Rendering/TreemapRenderer.Highlighting.cs delete mode 100644 WinDirStat.Net.Base/Rendering/TreemapRenderer.KDirStat.cs delete mode 100644 WinDirStat.Net.Base/Rendering/TreemapRenderer.Sequoia.cs delete mode 100644 WinDirStat.Net.Base/Rendering/TreemapRenderer.cs delete mode 100644 WinDirStat.Net.Base/Rendering/TreemapRendererFactory.cs delete mode 100644 WinDirStat.Net.Base/Rendering/TreemapStyle.cs delete mode 100644 WinDirStat.Net.Base/Services/IBitmapFactory.cs delete mode 100644 WinDirStat.Net.Base/Services/IClipboardService.cs delete mode 100644 WinDirStat.Net.Base/Services/IIconCacheService.cs delete mode 100644 WinDirStat.Net.Base/Services/IImagesService.cs delete mode 100644 WinDirStat.Net.Base/Services/IMainCommandInfoService.cs delete mode 100644 WinDirStat.Net.Base/Services/IOSService.cs delete mode 100644 WinDirStat.Net.Base/Services/IScanningService.cs delete mode 100644 WinDirStat.Net.Base/Services/ISettingsService.cs delete mode 100644 WinDirStat.Net.Base/Services/IShortcutsService.cs delete mode 100644 WinDirStat.Net.Base/Services/IUIService.cs delete mode 100644 WinDirStat.Net.Base/Services/IWindowDialogService.cs delete mode 100644 WinDirStat.Net.Base/Services/ImagesServiceBase.cs delete mode 100644 WinDirStat.Net.Base/Services/Implementation/CommandInfoService.cs delete mode 100644 WinDirStat.Net.Base/Services/Implementation/RelayCommandService.cs delete mode 100644 WinDirStat.Net.Base/Services/Implementation/ScanningService.cs delete mode 100644 WinDirStat.Net.Base/Services/Implementation/SettingsService.Defaults.cs delete mode 100644 WinDirStat.Net.Base/Services/Implementation/SettingsService.cs delete mode 100644 WinDirStat.Net.Base/Services/RelayCommandService.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IBrush.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IControl.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IImage.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IRelayCommandInfo.Generic.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IRelayCommandInfo.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IRelayUICommandInfo.Generic.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IRelayUICommandInfo.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IShortcut.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IUITimer.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/IWindow.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/Implementation/IconCache.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/Implementation/Message.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/Implementation/RecyleBinInfo.cs delete mode 100644 WinDirStat.Net.Base/Services/Structures/Implementation/Scanning.cs delete mode 100644 WinDirStat.Net.Base/StringConstants.cs delete mode 100644 WinDirStat.Net.Base/Structures/Point2D.cs delete mode 100644 WinDirStat.Net.Base/Structures/Point2F.cs delete mode 100644 WinDirStat.Net.Base/Structures/Point2I.cs delete mode 100644 WinDirStat.Net.Base/Structures/Rectangle2I.cs delete mode 100644 WinDirStat.Net.Base/Structures/Rectangle2S.cs delete mode 100644 WinDirStat.Net.Base/Structures/Rgb24Color.cs delete mode 100644 WinDirStat.Net.Base/Structures/Rgba32Color.cs delete mode 100644 WinDirStat.Net.Base/Utils/ArrayExtensions.cs delete mode 100644 WinDirStat.Net.Base/Utils/CommandExtensions.cs delete mode 100644 WinDirStat.Net.Base/Utils/Enumerator.cs delete mode 100644 WinDirStat.Net.Base/Utils/FormatBytes.cs delete mode 100644 WinDirStat.Net.Base/Utils/ListExtensions.cs delete mode 100644 WinDirStat.Net.Base/Utils/MathUtils.cs delete mode 100644 WinDirStat.Net.Base/Utils/PathUtils.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/IVolatile.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/Volatile.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/VolatileBoolean.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/VolatileCompound.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/VolatileDouble.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/VolatileInt16.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/VolatileInt32.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/VolatileInt64.cs delete mode 100644 WinDirStat.Net.Base/Utils/Volatiles/VolatileSingle.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Commands/IRelayCommand.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Commands/IRelayUICommand.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Commands/RelayUICommand.Generic.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Commands/RelayUICommand.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Comparers/DriveComparer.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Comparers/ExtensionComparer.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Comparers/FileComparer.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Comparers/SortComparer.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/ConfigureViewModel.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.Commands.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.Methods.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Drives/DriveItemViewModel.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Drives/DriveItemViewModelCollection.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Extensions/ExtensionItemViewModel.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Extensions/ExtensionItemViewModelCollection.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/Collection/FileItemViewModelCollection.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/Collection/IReadOnlyFileItemViewModelCollection.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.Flags.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.FlatList.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.TreeNode.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/FileItemViewModelFlags.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/FileTreeFlattener.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Files/FileTreeTraversal.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Graph/FileGraphViewModel.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/Graph/GraphViewModel.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/MainViewModel.Commands.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/MainViewModel.Methods.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/MainViewModel.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/ViewModelCommandBase.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/ViewModelControlBase.cs delete mode 100644 WinDirStat.Net.Base/ViewModel/ViewModelWindowBase.cs delete mode 100644 WinDirStat.Net.Base/WinDirStat.Net.Base.csproj delete mode 100644 WinDirStat.Net.Windows/Native/Win32.FindFile.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.ImageList.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.RecycleBin.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.SHFileOperation.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.SHGetFileInfo.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.SHGetStockIconInfo.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.Shell.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.ShellExecute.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.Windows.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32.cs delete mode 100644 WinDirStat.Net.Windows/Native/Win32Extensions.cs delete mode 100644 WinDirStat.Net.Windows/Services/Structures/WindowsScanFileInfo.cs delete mode 100644 WinDirStat.Net.Windows/Services/WindowsIconCacheService.cs delete mode 100644 WinDirStat.Net.Windows/Services/WindowsOSService.cs delete mode 100644 WinDirStat.Net.Windows/Services/WindowsScanningService.Mft.cs delete mode 100644 WinDirStat.Net.Windows/Services/WindowsScanningService.Native.cs delete mode 100644 WinDirStat.Net.Windows/Services/WindowsScanningService.Refresh.cs delete mode 100644 WinDirStat.Net.Windows/Services/WindowsScanningService.cs delete mode 100644 WinDirStat.Net.Windows/WinDirStat.Net.Windows.csproj delete mode 100644 WinDirStat.Net.Wpf/App.config delete mode 100644 WinDirStat.Net.Wpf/App.ico delete mode 100644 WinDirStat.Net.Wpf/App.xaml delete mode 100644 WinDirStat.Net.Wpf/App.xaml.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/CommandButton.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/CommandMenuItem.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/EditTextBox.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/ExtensionMethods.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/FileGridView.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/FileTreeNodeView.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/FileTreeView.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/FileTreeViewItem.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/GeneralAdorner.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/InsertMarker.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FileList/LinesRenderer.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FlashyProgressBar.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FocusBehavior.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/FocusExtension.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/GraphView.xaml delete mode 100644 WinDirStat.Net.Wpf/Controls/GraphView.xaml.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/ImageButton.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/ImageMenuItem.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/ListSettings.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/PercentageBar.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/RelayUIBinding.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/SortList/SortListView.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/SortList/SortView.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/SortList/SortViewColumn.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/SortList/SortViewKeys.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/SubtreePercentage.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/VisibleColumnDefinition.cs delete mode 100644 WinDirStat.Net.Wpf/Controls/VisibleRowDefinition.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/AttributesFormatter.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/ByteFormatter.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/CollapsedWhenBoolean.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/DirectoryExistsToBoolean.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/FileTimeFormatter.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/InverseBoolean.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/ItemCountFormatter.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/RadioButtonConverter.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/ScaleConverter.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/ScanTimeFormatter.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/TextToHorizontalAlignment.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/ZeroGridLengthWhenBoolean.cs delete mode 100644 WinDirStat.Net.Wpf/Converters/ZeroWhenBoolean.cs delete mode 100644 WinDirStat.Net.Wpf/MainWindow.xaml delete mode 100644 WinDirStat.Net.Wpf/MainWindow.xaml.cs delete mode 100644 WinDirStat.Net.Wpf/Properties/App.manifest delete mode 100644 WinDirStat.Net.Wpf/Properties/AssemblyInfo.cs delete mode 100644 WinDirStat.Net.Wpf/Resources/FileIcons/FileCollection.png delete mode 100644 WinDirStat.Net.Wpf/Resources/FileIcons/FreeSpace.png delete mode 100644 WinDirStat.Net.Wpf/Resources/FileIcons/Missing.png delete mode 100644 WinDirStat.Net.Wpf/Resources/FileIcons/Shortcut.png delete mode 100644 WinDirStat.Net.Wpf/Resources/FileIcons/UnknownSpace.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Close.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Cmd.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/CmdElevated.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Copy.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/CopyPath.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Cut.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Delete.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Elevate.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/EmptyRecycleBin.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Exit.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Expand.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Explore.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Open.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Paste.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/PowerShell.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/PowerShellElevated.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Properties.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/RecycleBin.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Redo.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/RefreshSelected.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Reload.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Run.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Save.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Search.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Settings.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/ShowFileTypes.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/ShowTotalSpace.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/ShowTreemap.png delete mode 100644 WinDirStat.Net.Wpf/Resources/Icons/Undo.png delete mode 100644 WinDirStat.Net.Wpf/Resources/ImageResources.cs delete mode 100644 WinDirStat.Net.Wpf/Services/ResourceImagesService.cs delete mode 100644 WinDirStat.Net.Wpf/Services/Structures/IWpfRelayCommand.cs delete mode 100644 WinDirStat.Net.Wpf/Services/Structures/WpfImage.cs delete mode 100644 WinDirStat.Net.Wpf/Services/Structures/WpfRelayCommand.cs delete mode 100644 WinDirStat.Net.Wpf/Services/Structures/WpfRelayCommandInfo.cs delete mode 100644 WinDirStat.Net.Wpf/Services/Structures/WpfRelayUICommand.cs delete mode 100644 WinDirStat.Net.Wpf/Services/Structures/WpfShortcut.cs delete mode 100644 WinDirStat.Net.Wpf/Services/Structures/WpfUITimer.cs delete mode 100644 WinDirStat.Net.Wpf/Services/Structures/WpfWindow.cs delete mode 100644 WinDirStat.Net.Wpf/Services/WpfBitmapFactory.cs delete mode 100644 WinDirStat.Net.Wpf/Services/WpfClipboardService.cs delete mode 100644 WinDirStat.Net.Wpf/Services/WpfUIService.cs delete mode 100644 WinDirStat.Net.Wpf/Services/WpfWindowDialogService.cs delete mode 100644 WinDirStat.Net.Wpf/Themes/Generic.xaml delete mode 100644 WinDirStat.Net.Wpf/Themes/SortView.xaml delete mode 100644 WinDirStat.Net.Wpf/Utils/DependencyObjectExtensions.cs delete mode 100644 WinDirStat.Net.Wpf/Utils/WindowExtensions.cs delete mode 100644 WinDirStat.Net.Wpf/Utils/WpfCasting.cs delete mode 100644 WinDirStat.Net.Wpf/Utils/WpfExtensions.cs delete mode 100644 WinDirStat.Net.Wpf/Utils/WpfUtils.cs delete mode 100644 WinDirStat.Net.Wpf/ViewModel/ViewModelLocator.cs delete mode 100644 WinDirStat.Net.Wpf/WinDirStat.Net.Wpf.csproj delete mode 100644 WinDirStat.Net.Wpf/Windows/ConfigureDialog.xaml delete mode 100644 WinDirStat.Net.Wpf/Windows/ConfigureDialog.xaml.cs delete mode 100644 WinDirStat.Net.Wpf/Windows/DriveSelectDialog.xaml delete mode 100644 WinDirStat.Net.Wpf/Windows/DriveSelectDialog.xaml.cs delete mode 100644 WinDirStat.Net.Wpf/Windows/FolderBrowserDialog.cs delete mode 100644 WinDirStat.Net/App.config delete mode 100644 WinDirStat.Net/App.ico delete mode 100644 WinDirStat.Net/App.xaml delete mode 100644 WinDirStat.Net/App.xaml.cs delete mode 100644 WinDirStat.Net/Controls/CommandButton.cs delete mode 100644 WinDirStat.Net/Controls/CommandMenuItem.cs delete mode 100644 WinDirStat.Net/Controls/FlashyProgressBar.cs delete mode 100644 WinDirStat.Net/Controls/GraphView.xaml delete mode 100644 WinDirStat.Net/Controls/GraphView.xaml.cs delete mode 100644 WinDirStat.Net/Controls/ImageButton.cs delete mode 100644 WinDirStat.Net/Controls/ImageMenuItem.cs delete mode 100644 WinDirStat.Net/Controls/PercentageBar.cs delete mode 100644 WinDirStat.Net/Controls/SubtreePercentage.cs delete mode 100644 WinDirStat.Net/Converters/AttributesFormatter.cs delete mode 100644 WinDirStat.Net/Converters/ByteFormatter.cs delete mode 100644 WinDirStat.Net/Converters/CollapsedWhenBoolean.cs delete mode 100644 WinDirStat.Net/Converters/DirectoryExistsToBoolean.cs delete mode 100644 WinDirStat.Net/Converters/EmptyWhenNegative.cs delete mode 100644 WinDirStat.Net/Converters/RadioButtonConverter.cs delete mode 100644 WinDirStat.Net/Converters/ScanTimeFormatter.cs delete mode 100644 WinDirStat.Net/Converters/TextToHorizontalAlignment.cs delete mode 100644 WinDirStat.Net/Converters/ZeroWhenBoolean.cs delete mode 100644 WinDirStat.Net/Drawing/ColorSpace.cs delete mode 100644 WinDirStat.Net/Drawing/ITreemapItem.cs delete mode 100644 WinDirStat.Net/Drawing/PreviewTreemapItem.cs delete mode 100644 WinDirStat.Net/Drawing/Treemap.cs delete mode 100644 WinDirStat.Net/Drawing/TreemapItem.cs delete mode 100644 WinDirStat.Net/Model/Data/Extensions/ExtensionRecord.cs delete mode 100644 WinDirStat.Net/Model/Data/Extensions/ExtensionRecordEvents.cs delete mode 100644 WinDirStat.Net/Model/Data/Extensions/ExtensionRecords.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/FileNode.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/FileNodeBase.Flags.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/FileNodeBase.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/FileNodeEvents.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/FileNodeFlags.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/FolderNode.Flags.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/FolderNode.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/FreeSpaceNode.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/RootNode.cs delete mode 100644 WinDirStat.Net/Model/Data/Nodes/UnknownNode.cs delete mode 100644 WinDirStat.Net/Model/Data/ScanState.cs delete mode 100644 WinDirStat.Net/Model/Data/SelectDrivesModel.cs delete mode 100644 WinDirStat.Net/Model/Data/WinDirStatModel.Scanning.Mft.cs delete mode 100644 WinDirStat.Net/Model/Data/WinDirStatModel.Scanning.Native.cs delete mode 100644 WinDirStat.Net/Model/Data/WinDirStatModel.Scanning.Private.cs delete mode 100644 WinDirStat.Net/Model/Data/WinDirStatModel.Scanning.cs delete mode 100644 WinDirStat.Net/Model/Data/WinDirStatModel.cs delete mode 100644 WinDirStat.Net/Model/IRelayUICommand.cs delete mode 100644 WinDirStat.Net/Model/ObservableObject.cs delete mode 100644 WinDirStat.Net/Model/RelayCommand.Generic.cs delete mode 100644 WinDirStat.Net/Model/RelayCommand.cs delete mode 100644 WinDirStat.Net/Model/RelayUIBinding.cs delete mode 100644 WinDirStat.Net/Model/RelayUICommand.Generic.cs delete mode 100644 WinDirStat.Net/Model/RelayUICommand.cs delete mode 100644 WinDirStat.Net/Model/Settings/WinDirStatSettings.Defaults.cs delete mode 100644 WinDirStat.Net/Model/Settings/WinDirStatSettings.IO.cs delete mode 100644 WinDirStat.Net/Model/Settings/WinDirStatSettings.cs delete mode 100644 WinDirStat.Net/Model/View/Comparers/DriveComparer.cs delete mode 100644 WinDirStat.Net/Model/View/Comparers/ExtensionComparer.cs delete mode 100644 WinDirStat.Net/Model/View/Comparers/FileComparer.cs delete mode 100644 WinDirStat.Net/Model/View/Comparers/SortComparer.cs delete mode 100644 WinDirStat.Net/Model/View/DriveSelectViewModel.cs delete mode 100644 WinDirStat.Net/Model/View/Drives/Collections/DriveCollection.cs delete mode 100644 WinDirStat.Net/Model/View/Drives/DriveViewModel.cs delete mode 100644 WinDirStat.Net/Model/View/Extensions/ExtensionRecordViewModel.cs delete mode 100644 WinDirStat.Net/Model/View/Extensions/ExtensionRecordsViewModel.cs delete mode 100644 WinDirStat.Net/Model/View/IconCache.Queue.cs delete mode 100644 WinDirStat.Net/Model/View/IconCache.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/Collections/EmptyFileNodeCollection.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/Collections/FileNodeCollection.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/Collections/IFileNodeCollection.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/FileNodeViewModel.Flags.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/FileNodeViewModel.FlatList.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/FileNodeViewModel.TreeNode.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/FileNodeViewModel.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/FileNodeViewModelFlags.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/TreeFlattener.cs delete mode 100644 WinDirStat.Net/Model/View/Nodes/TreeTraversal.cs delete mode 100644 WinDirStat.Net/Model/View/WinDirStatViewModel.Commands.cs delete mode 100644 WinDirStat.Net/Model/View/WinDirStatViewModel.Events.cs delete mode 100644 WinDirStat.Net/Model/View/WinDirStatViewModel.Scanning.cs delete mode 100644 WinDirStat.Net/Model/View/WinDirStatViewModel.cs delete mode 100644 WinDirStat.Net/Model/ViewModel.cs delete mode 100644 WinDirStat.Net/Properties/App.manifest delete mode 100644 WinDirStat.Net/Properties/AssemblyInfo.cs delete mode 100644 WinDirStat.Net/Properties/Settings.Designer.cs delete mode 100644 WinDirStat.Net/Properties/Settings.settings delete mode 100644 WinDirStat.Net/Resources/DimmedGraph.png delete mode 100644 WinDirStat.Net/Resources/FileIcons/FileCollection.png delete mode 100644 WinDirStat.Net/Resources/FileIcons/FreeSpace.png delete mode 100644 WinDirStat.Net/Resources/FileIcons/Shortcut.png delete mode 100644 WinDirStat.Net/Resources/FileIcons/UnknownSpace.png delete mode 100644 WinDirStat.Net/Resources/FileIcons/UnknownSpace2.png delete mode 100644 WinDirStat.Net/Resources/Icons/Cmd.png delete mode 100644 WinDirStat.Net/Resources/Icons/CmdElevated.png delete mode 100644 WinDirStat.Net/Resources/Icons/Copy.png delete mode 100644 WinDirStat.Net/Resources/Icons/Cut.png delete mode 100644 WinDirStat.Net/Resources/Icons/Delete.png delete mode 100644 WinDirStat.Net/Resources/Icons/DeleteFolder.png delete mode 100644 WinDirStat.Net/Resources/Icons/DeleteRecycleBin.png delete mode 100644 WinDirStat.Net/Resources/Icons/Elevate.png delete mode 100644 WinDirStat.Net/Resources/Icons/Exit.png delete mode 100644 WinDirStat.Net/Resources/Icons/Expand.png delete mode 100644 WinDirStat.Net/Resources/Icons/Explore.png delete mode 100644 WinDirStat.Net/Resources/Icons/Open.png delete mode 100644 WinDirStat.Net/Resources/Icons/Paste.png delete mode 100644 WinDirStat.Net/Resources/Icons/Path.png delete mode 100644 WinDirStat.Net/Resources/Icons/PowerShell.png delete mode 100644 WinDirStat.Net/Resources/Icons/PowerShellElevated.png delete mode 100644 WinDirStat.Net/Resources/Icons/Properties.png delete mode 100644 WinDirStat.Net/Resources/Icons/Recycle.png delete mode 100644 WinDirStat.Net/Resources/Icons/Redo.png delete mode 100644 WinDirStat.Net/Resources/Icons/RefreshSelected.png delete mode 100644 WinDirStat.Net/Resources/Icons/Reload.png delete mode 100644 WinDirStat.Net/Resources/Icons/Run.png delete mode 100644 WinDirStat.Net/Resources/Icons/Save.png delete mode 100644 WinDirStat.Net/Resources/Icons/Search.png delete mode 100644 WinDirStat.Net/Resources/Icons/Settings.png delete mode 100644 WinDirStat.Net/Resources/Icons/Undo.png delete mode 100644 WinDirStat.Net/Resources/Images.cs delete mode 100644 WinDirStat.Net/Settings/Geometry/Point2F.cs delete mode 100644 WinDirStat.Net/Settings/Geometry/Point2I.cs delete mode 100644 WinDirStat.Net/Settings/Geometry/Rectangle2I.cs delete mode 100644 WinDirStat.Net/Settings/Geometry/Rectangle2S.cs delete mode 100644 WinDirStat.Net/Settings/Geometry/Rgb24Color.cs delete mode 100644 WinDirStat.Net/Settings/Geometry/Rgba32Color.cs delete mode 100644 WinDirStat.Net/Settings/IconCacheMode.cs delete mode 100644 WinDirStat.Net/Settings/TreemapOptions.cs delete mode 100644 WinDirStat.Net/Settings/TreemapStyle.cs delete mode 100644 WinDirStat.Net/Sorting/SortListView.cs delete mode 100644 WinDirStat.Net/Sorting/SortView.cs delete mode 100644 WinDirStat.Net/Sorting/SortViewColumn.cs delete mode 100644 WinDirStat.Net/Sorting/SortViewKeys.cs delete mode 100644 WinDirStat.Net/Themes/Generic.xaml delete mode 100644 WinDirStat.Net/Themes/SortView.xaml delete mode 100644 WinDirStat.Net/TreeView/EditTextBox.cs delete mode 100644 WinDirStat.Net/TreeView/ExtensionMethods.cs delete mode 100644 WinDirStat.Net/TreeView/FileGridView.cs delete mode 100644 WinDirStat.Net/TreeView/FileTreeNodeView.cs delete mode 100644 WinDirStat.Net/TreeView/FileTreeView.cs delete mode 100644 WinDirStat.Net/TreeView/FileTreeViewItem.cs delete mode 100644 WinDirStat.Net/TreeView/GeneralAdorner.cs delete mode 100644 WinDirStat.Net/TreeView/InsertMarker.cs delete mode 100644 WinDirStat.Net/TreeView/LinesRenderer.cs delete mode 100644 WinDirStat.Net/Utils/BitField16.cs delete mode 100644 WinDirStat.Net/Utils/BitField32.cs delete mode 100644 WinDirStat.Net/Utils/BitmapUtils.cs delete mode 100644 WinDirStat.Net/Utils/ByteFormatter.cs delete mode 100644 WinDirStat.Net/Utils/EmptyEnumerator.cs delete mode 100644 WinDirStat.Net/Utils/ListExtensions.cs delete mode 100644 WinDirStat.Net/Utils/MathUtils.cs delete mode 100644 WinDirStat.Net/Utils/Native/Win32.FindFile.cs delete mode 100644 WinDirStat.Net/Utils/Native/Win32.ImageList.cs delete mode 100644 WinDirStat.Net/Utils/Native/Win32.SHGetFileInfo.cs delete mode 100644 WinDirStat.Net/Utils/Native/Win32.SHGetStockIconInfo.cs delete mode 100644 WinDirStat.Net/Utils/Native/Win32.Shell.cs delete mode 100644 WinDirStat.Net/Utils/Native/Win32.Windows.cs delete mode 100644 WinDirStat.Net/Utils/Native/Win32.cs delete mode 100644 WinDirStat.Net/Utils/Native/Win32Extensions.cs delete mode 100644 WinDirStat.Net/Utils/PathUtils.cs delete mode 100644 WinDirStat.Net/Utils/SpeedTester.cs delete mode 100644 WinDirStat.Net/Utils/TimedLock.cs delete mode 100644 WinDirStat.Net/Utils/WindowExtensions.cs delete mode 100644 WinDirStat.Net/Utils/WpfExtensions.cs delete mode 100644 WinDirStat.Net/WinDirStat.Net.csproj delete mode 100644 WinDirStat.Net/WinDirStatWindow.xaml delete mode 100644 WinDirStat.Net/WinDirStatWindow.xaml.cs delete mode 100644 WinDirStat.Net/Windows/DriveSelectDialog.xaml delete mode 100644 WinDirStat.Net/Windows/DriveSelectDialog.xaml.cs delete mode 100644 WinDirStat.Net/Windows/FolderBrowserDialog.cs diff --git a/WinDirStat.Net.Base/Model/Drives/DriveItem.cs b/WinDirStat.Net.Base/Model/Drives/DriveItem.cs deleted file mode 100644 index 647a29a..0000000 --- a/WinDirStat.Net.Base/Model/Drives/DriveItem.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Model.Drives { - /// An item containing basic information on a drive. - [Serializable] - public class DriveItem : IComparable, IComparable { - - #region Fields - - /// Gets the name/path of the drive. - public string Name { get; } - /// Gets the total size of the drive. - public long TotalSize { get; } - /// Gets the freespace on the drive in bytes. - public long FreeSpace { get; } - /// Gets the type of the drive. - public DriveType DriveType { get; } - /// Gets the partition format of the drive. - public string DriveFormat { get; } - - #endregion - - #region Constructors - - /// Constructs a using the . - /// - /// The information about the drive. - public DriveItem(DriveInfo info) { - Name = info.Name; - TotalSize = info.TotalSize; - FreeSpace = info.TotalFreeSpace; - DriveType = info.DriveType; - DriveFormat = info.DriveFormat; - } - - #endregion - - #region Properties - - /// Gets the used space on the drive in bytes. - public long UsedSpace => Math.Max(0L, TotalSize - FreeSpace); - - /// Gets the used percentage of the drive. - public double Percent => (double) UsedSpace / TotalSize; - - #endregion - - #region IComparable Implementation - - /// Compares this drive to another based on name in ascending order. - /// - /// The other drive to compare to. - /// The comparison result. - public int CompareTo(DriveItem other) { - int diff = other.TotalSize.CompareTo(TotalSize); - if (diff == 0) - return string.Compare(Name, other.Name, true); - return diff; - } - - /// Compares this drive to another based on name in ascending order. - /// - /// The other drive to compare to. - /// The comparison result. - int IComparable.CompareTo(object obj) { - return CompareTo((DriveItem) obj); - } - - #endregion - - #region ToString/DebuggerDisplay - - /// Gets the string representation of this item. - public override sealed string ToString() => Name; - - /// Gets the string used to represent the file in the debugger. - private string DebuggerDisplay => Name; - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Drives/DriveItems.cs b/WinDirStat.Net.Base/Model/Drives/DriveItems.cs deleted file mode 100644 index 8fd961d..0000000 --- a/WinDirStat.Net.Base/Model/Drives/DriveItems.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Model.Drives { - /// A collection of see s. - public class DriveItems : ObservablePropertyCollectionObject, IReadOnlyList { - - #region Fields - - /// The scanning service that contains this collection. - private readonly ScanningService scanning; - /// The collection of drives. - private readonly List drives; - - #endregion - - #region Constructors - - /// Constructs the list. - public DriveItems(ScanningService scanning) { - this.scanning = scanning; - drives = new List(); - } - - #endregion - - #region Refresh - - /// Refreshes the drive list. - public void Refresh() { - if (drives.Count > 0) { - List oldItems = drives.GetFullRange(); - drives.Clear(); - RaisePropertyChanged(nameof(Count)); - RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, oldItems, 0); - } - drives.AddRange(scanning.ScanDrives()); - drives.Sort(); - RaiseCollectionChanged(NotifyCollectionChangedAction.Add, drives.GetFullRange(), 0); - } - - #endregion - - #region Properties - - /// Gets the number of drives in the list. - public int Count => drives.Count; - - /// Gets the drive item at the specified index in the list. - public DriveItem this[int index] => drives[index]; - - #endregion - - #region IEnumerator Implementation - - /// Gets the enumerator for the drive items. - IEnumerator IEnumerable.GetEnumerator() { - return drives.GetEnumerator(); - } - /// Gets the enumerator for the drive items. - IEnumerator IEnumerable.GetEnumerator() { - return drives.GetEnumerator(); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Drives/Misc/DriveSelectMode.cs b/WinDirStat.Net.Base/Model/Drives/Misc/DriveSelectMode.cs deleted file mode 100644 index d499a57..0000000 --- a/WinDirStat.Net.Base/Model/Drives/Misc/DriveSelectMode.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Model.Drives { - /// The selection mode for drives. - [Serializable] - public enum DriveSelectMode { - /// All local drives are scanned. - [Description("All Local Drives")] - All, - /// Selected drives are scanned. - [Description("Individual Drives")] - Individual, - /// A folder path is scanned. - [Description("A Folder")] - Folder, - } -} diff --git a/WinDirStat.Net.Base/Model/Drives/Misc/DriveSelectResult.cs b/WinDirStat.Net.Base/Model/Drives/Misc/DriveSelectResult.cs deleted file mode 100644 index 81c2887..0000000 --- a/WinDirStat.Net.Base/Model/Drives/Misc/DriveSelectResult.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using WinDirStat.Net.Services; - -namespace WinDirStat.Net.Model.Drives { - /// The result returned from the drive select dialog. - public class DriveSelectResult { - - #region Fields - - /// The scanning service that contains this collection. - private readonly ScanningService scanning; - /// - /// The constant selected paths. Null when Mode is . - /// - private readonly string[] selectedPaths; - - /// The selection mode of the drive select result. - public DriveSelectMode Mode { get; } - - #endregion - - #region Constructors - - /// Constructs the . - public DriveSelectResult(ScanningService scanning, - DriveSelectMode mode, - string[] selectedDrives, - string folderPath) - { - this.scanning = scanning; - Mode = mode; - if (mode == DriveSelectMode.Individual) { - if (selectedDrives == null) - throw new ArgumentNullException(nameof(selectedDrives)); - selectedPaths = selectedDrives; - } - else if (mode == DriveSelectMode.Folder) { - selectedPaths = new[] { - folderPath ?? throw new ArgumentNullException(nameof(folderPath)), - }; - } - } - - #endregion - - #region Accessors - - /// Gets the result path of the drive select operation. - /// - /// Returns the paths of the result. - public string[] GetResultPaths() { - if (Mode == DriveSelectMode.All) { - return scanning.ScanDriveNames(); - } - else { - return selectedPaths; - } - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Extensions/ExtensionItem.cs b/WinDirStat.Net.Base/Model/Extensions/ExtensionItem.cs deleted file mode 100644 index f2b1eff..0000000 --- a/WinDirStat.Net.Base/Model/Extensions/ExtensionItem.cs +++ /dev/null @@ -1,277 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.Model.Extensions { - /// A container for information about a file extension. - [Serializable] - [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class ExtensionItem : IComparable, IComparable { - - #region Constants - - /// The used for file tree items that are not files. - public static readonly ExtensionItem NotAFile = new ExtensionItem(); - - /// The string used to represent an empty extension. - public const string EmptyExtension = "*"; - - #endregion - - #region Fields - - /// The collection containing this extension. - private readonly ExtensionItems extensions; - - /// Gets the name of the extension with the dot. - public string Extension { get; } - /// Gets the total size of all the files that use this extension. - public long Size { get; private set; } - /// Gets the number of files that use this extension. - public int FileCount { get; private set; } - /// Gets the color to use in the treemap for files with this extension. - private Rgb24Color color; - - #endregion - - #region Constructors - - /// Constructs the not-a-file extension. - private ExtensionItem() { - extensions = null; - Extension = string.Empty; - color = Rgb24Color.Black; - } - - /// Constructs an with the specified extension. - /// - /// The collection containing this extension. - /// The pre-normalized extension for this item. - internal ExtensionItem(ExtensionItems extensions, string normalizedExtension) { - this.extensions = extensions; - Extension = normalizedExtension; - color = new Rgb24Color(150, 150, 150); - } - - #endregion - - #region ViewModel Events - - /// Notifies any view models watching this item of important changes to the item. - [field: NonSerialized] - public event ExtensionItemEventHandler Changed; - - /// Gets if the item is being watched by a view model. - public bool IsWatched => Changed != null; - - protected void RaiseChanged(ExtensionItemEventArgs e) { - Changed?.Invoke(this, e); - } - protected void RaiseChanged(ExtensionItemAction action) { - Changed?.Invoke(this, new ExtensionItemEventArgs(action)); - } - protected void RaiseChanged(ExtensionItemAction action, int index) { - Changed?.Invoke(this, new ExtensionItemEventArgs(action, index)); - } - - public object GetViewModel() { - ExtensionItemEventArgs e = new ExtensionItemEventArgs(ExtensionItemAction.GetViewModel); - RaiseChanged(e); - return e.ViewModel; - } - - public TViewModel GetViewModel() where TViewModel : class { - ExtensionItemEventArgs e = new ExtensionItemEventArgs(ExtensionItemAction.GetViewModel); - RaiseChanged(e); - return e.ViewModel as TViewModel; - } - - #endregion - - #region Properties - - /// Gets the color to use in the treemap for files with this extension. - public Rgb24Color Color { - get => color; - /*internal set { - color = value; - RaiseChanged(ExtensionItemAction.ColorChanged); - }*/ - } - - /// Gets this extension's size relative to the total used space. - public double Percent { - get => (double) Size / extensions.TotalSize; - } - - /// Gets if this extension is the empty extension with nothing after the dot. - public bool IsEmptyExtension { - get => Extension == EmptyExtension; - } - - #endregion - - #region Color - - /// Sets the new color of the extension item. - /// - /// The new color. - /// The index of the extension in the sorted list. - internal void SetColor(Rgb24Color color, int index) { - this.color = color; - RaiseChanged(ExtensionItemAction.ColorChanged, index); - } - - #endregion - - #region Files - - /// Adds the file to the extension data. - /// - /// The size of the file to add. - internal void AddFile(long size) { - FileCount++; - Size += size; - extensions.TotalSize += size; - extensions.TotalFileCount++; - } - - /// Refreshes the file size with the extension. - /// - /// The new size of the file to refresh. - /// The old size of the file to refresh. - internal void RefreshFile(long size, long oldSize) { - long diff = size - oldSize; - Size += diff; - extensions.TotalSize += diff; - } - - /// Removes the file from the extension data. - /// - /// The size of the file to remove. - internal void RemoveFile(long size) { - Debug.Assert(FileCount > 0); - FileCount--; - Size -= size; - extensions.TotalSize -= size; - extensions.TotalFileCount--; - if (FileCount == 0) - extensions.Remove(this); - } - - /// - /// Removes all files associated with this extension.. - /// - internal void ClearFiles() { - extensions.TotalSize -= Size; - extensions.TotalFileCount -= FileCount; - Size = 0; - FileCount = 0; - extensions.Remove(this); - } - - /// - /// Removes all files associated with this extension. Only call this during . - /// - internal void ClearFilesMinimal() { - Size = 0; - FileCount = 0; - } - - #endregion - - #region IComparable Implementation - - /// Compares this extension to another based on size in descending order. - /// - /// The other extension to compare to. - /// The comparison result. - public int CompareTo(ExtensionItem other) { - int diff = other.Size.CompareTo(Size); - if (diff == 0) - return string.Compare(Extension, other.Extension, true); - return diff; - } - - /// Compares this extension to another based on size in descending order. - /// - /// The other extension to compare to. - /// The comparison result. - int IComparable.CompareTo(object obj) { - return CompareTo((ExtensionItem) obj); - } - - #endregion - - #region ToString/DebuggerDisplay - - /// Gets the string representation of this item. - public override sealed string ToString() => $"[{FileCount:N0}]: {Extension}"; - - /// Gets the string used to represent the file in the debugger. - private string DebuggerDisplay => $"[{FileCount:N0}]: {Extension}"; - - #endregion - - #region Static Methods - - /// Normalizes the extension for consistency. - /// - /// The extension to normalize. - /// A normalized extension. - public static string NormalizeExtension(string extension) { - int length = extension.Length; - if (length > 0) { - if (extension[0] == '.') { - if (length > 1) - return extension.ToLower(); - else // '.' is equivilant to an empty extension - return EmptyExtension; - } - else if (extension[0] != '*' || length > 1) { - // Needs a dot - return "." + extension.ToLower(); - } - } - // Empty string, empty extension - return EmptyExtension; - } - - /// Normalizes the extension for consistency. - /// - /// The extension to normalize. - public static void NormalizeExtension(ref string extension) { - extension = NormalizeExtension(extension); - } - - /// Gets the extension from the file path and normalizes it. - /// - /// The file path to normalize the extension of. - /// A normalized extension. - public static string GetAndNormalizeExtension(string path) { - // Code modified from Path.cs: Path.GetExtension(string) - int length = path.Length; - for (int i = length; --i >= 0;) { - char ch = path[i]; - if (ch == '.') { - if (i != length - 1) - return path.Substring(i, length - i).ToLower(); - else - return EmptyExtension; - } - if (ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar) - break; - } - return EmptyExtension; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Extensions/ExtensionItems.cs b/WinDirStat.Net.Base/Model/Extensions/ExtensionItems.cs deleted file mode 100644 index 42bc93b..0000000 --- a/WinDirStat.Net.Base/Model/Extensions/ExtensionItems.cs +++ /dev/null @@ -1,230 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Utils; -using static WinDirStat.Net.Model.Extensions.ExtensionItem; - -namespace WinDirStat.Net.Model.Extensions { - /// - /// A collection that maintains information about all extensions encountered while scanning the file - /// tree. - /// - public class ExtensionItems : ObservablePropertyCollectionObject, IReadOnlyList { - - #region Fields - - /// The scanning service that contains this collection. - private readonly ScanningService scanning; - /// The program settings service. - private readonly SettingsService settings; - /// The map of in-use extensions. - private readonly Dictionary extensions; - /// The map of unused extensions. - private readonly Dictionary unusedExtensions; - /// The list of extensions sorted by size descending after the scan. - private readonly List sortedExtensions; - - /// the Total size of all files in the file tree. - private long totalSize; - /// The total number of files in the file tree. - private long totalFileCount; - - #endregion - - #region Constructors - - /// Constructs the list. - public ExtensionItems(ScanningService scanning, - SettingsService settings) - { - this.scanning = scanning; - this.settings = settings; - extensions = new Dictionary(); - unusedExtensions = new Dictionary(); - sortedExtensions = new List(); - - scanning.PropertyChanged += OnScanningPropertyChanged; - settings.PropertyChanged += OnSettingsPropertyChanged; - } - - #endregion - - #region Event Handlers - - private void OnScanningPropertyChanged(object sender, PropertyChangedEventArgs e) { - switch (e.PropertyName) { - case nameof(ScanningService.ProgressState): - if (scanning.ProgressState == ScanProgressState.Ended && !scanning.IsRefreshing) - Validate(); - break; - case nameof(ScanningService.IsRefreshing): - if (!scanning.IsScanning) - Validate(); - break; - } - } - - private void OnSettingsPropertyChanged(object sender, PropertyChangedEventArgs e) { - switch (e.PropertyName) { - case nameof(SettingsService.FilePalette): - if (!scanning.IsScanning && !scanning.IsRefreshing) - RefreshPalette(); - break; - } - } - - #endregion - - #region Properties - - /// Gets the total size of all files in the file tree. - public long TotalSize { - get => totalSize; - internal set => Set(ref totalSize, value); - } - /// Gets the total number of files in the file tree. - public long TotalFileCount { - get => totalFileCount; - internal set => Set(ref totalFileCount, value); - } - - /// Gets the number of extensions in the file tree. - public int Count => sortedExtensions.Count; - /// Gets the number of unused extensions in the file tree. - public int UnusedCount => unusedExtensions.Count; - - /// Gets the extension item at the specified index (in the list ordered by size). - public ExtensionItem this[int index] => sortedExtensions[index]; - /// Gets the existing extension item of the specified extension. - public ExtensionItem this[string extension] => extensions[NormalizeExtension(extension)]; - - #endregion - - #region Collection - - /// Gets the existing extension item or creates one and adds it to the list. - /// - /// The extension to get or add an item for. - /// The extension item with the specified extension. - public ExtensionItem GetOrAdd(string extension) { - NormalizeExtension(ref extension); - if (!extensions.TryGetValue(extension, out ExtensionItem item)) { - bool unusedFound = unusedExtensions.TryGetValue(extension, out item); - if (unusedFound) - unusedExtensions.Remove(extension); - else - item = new ExtensionItem(this, extension); - Debug.Assert(item != null); - extensions.Add(extension, item); - sortedExtensions.Add(item); - if (unusedFound) - RaisePropertyChanged(nameof(UnusedCount)); - RaisePropertyChanged(nameof(Count)); - RaiseCollectionChanged(NotifyCollectionChangedAction.Add, item, sortedExtensions.Count - 1); - } - return item; - } - - /// Gets the existing extension item or creates one and adds it to the list. - /// - /// The path to get the extension from. - /// The extension item with the specified extension. - public ExtensionItem GetOrAddFromPath(string path) { - return GetOrAdd(GetAndNormalizeExtension(path)); - } - - /// Removes the extension item from the list. - /// - /// The extension item to remove - /// True if the extension item was contained in the list and removed. - internal bool Remove(ExtensionItem item) { - if (extensions.Remove(item.Extension)) { - int index = sortedExtensions.IndexOf(item); - sortedExtensions.RemoveAt(index); - unusedExtensions.Add(item.Extension, item); - RaisePropertyChanged(nameof(Count)); - RaisePropertyChanged(nameof(UnusedCount)); - RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, item, index); - return true; - } - return false; - } - - /// Removes the specified item with the specified extension from the list. - /// - /// The extension of the item to remove - /// True if the extension was contained in the list and removed. - internal bool Remove(string extension) { - NormalizeExtension(ref extension); - if (extensions.TryGetValue(extension, out ExtensionItem item)) { - unusedExtensions.Add(extension, item); - extensions.Remove(extension); - int index = sortedExtensions.IndexOf(item); - sortedExtensions.RemoveAt(index); - RaisePropertyChanged(nameof(Count)); - RaisePropertyChanged(nameof(UnusedCount)); - RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, item, index); - return true; - } - return false; - } - - /// Removes all extensions from the list. - internal void Clear() { - List oldItems = sortedExtensions.GetFullRange(); - sortedExtensions.Clear(); - foreach (ExtensionItem item in oldItems) { - item.ClearFilesMinimal(); - unusedExtensions.Add(item.Extension, item); - } - extensions.Clear(); - TotalSize = 0; - TotalFileCount = 0; - RaisePropertyChanged(nameof(Count)); - RaisePropertyChanged(nameof(UnusedCount)); - RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, oldItems, 0); - } - - #endregion - - #region Validation - - /// Validates the extensions and sorts them in size descending order. - private void Validate() { - sortedExtensions.Sort(); - RefreshPalette(); - //RaiseCollectionChanged(NotifyCollectionChangedAction.Reset); - } - - /// Refreshes the extensions file palette. - private void RefreshPalette() { - int count = sortedExtensions.Count; - for (int i = 0; i < count; i++) { - sortedExtensions[i].SetColor(settings.GetFilePaletteColor(i), i); - } - } - - #endregion - - #region IEnumerator Implementation - - /// Gets the enumerator for the extension items. - IEnumerator IEnumerable.GetEnumerator() { - return sortedExtensions.GetEnumerator(); - } - /// Gets the enumerator for the extension items. - IEnumerator IEnumerable.GetEnumerator() { - return sortedExtensions.GetEnumerator(); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Extensions/Misc/ExtensionItemEvents.cs b/WinDirStat.Net.Base/Model/Extensions/Misc/ExtensionItemEvents.cs deleted file mode 100644 index b36e453..0000000 --- a/WinDirStat.Net.Base/Model/Extensions/Misc/ExtensionItemEvents.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Model.Extensions { - /// The event action type for . - public enum ExtensionItemAction { - // State - /// The preview color of the extension changed. - ColorChanged, - - // Accessors - /// Requests the view watching this node to show itself. - GetViewModel, - } - - /// The event arguments for . - public class ExtensionItemEventArgs { - /// The action to notify the view model of. - public ExtensionItemAction Action { get; } - /// Gets the index of the extension item in the sorted list. - public int Index { get; } - /// - /// The view model if is . - /// - public object ViewModel { get; set; } - - /// - /// Constructs the that just require an action. - /// - public ExtensionItemEventArgs(ExtensionItemAction action) { - Action = action; - Index = -1; - } - - /// - /// Constructs the that require an action and index. - /// - public ExtensionItemEventArgs(ExtensionItemAction action, int index) { - Action = action; - Index = index; - } - } - - /// The event handler for . - /// - /// The that sent this changed event. - /// The for this changed event. - public delegate void ExtensionItemEventHandler(ExtensionItem sender, ExtensionItemEventArgs e); -} diff --git a/WinDirStat.Net.Base/Model/Files/FileItem.cs b/WinDirStat.Net.Base/Model/Files/FileItem.cs deleted file mode 100644 index c75e6c2..0000000 --- a/WinDirStat.Net.Base/Model/Files/FileItem.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Services; - -namespace WinDirStat.Net.Model.Files { - /// The file tree item that identifies an actual file. - [Serializable] - public class FileItem : FileItemBase { - - #region Fields - - /// Gets the extension item of the file. - public override sealed ExtensionItem ExtensionItem { get; } - - #endregion - - #region Constructors - - /// Constructs the with a . - /// - /// The file information. - /// The extension information. - public FileItem(FileSystemInfo info, ExtensionItem extension) - : base(info, FileItemType.File, FileItemFlags.FileType) - { - Debug.Assert(extension != null); - ExtensionItem = extension; - } - - /// Constructs the with a . - /// - /// The file information. - /// The extension information. - public FileItem(IScanFileInfo info, ExtensionItem extension) - : base(info, FileItemType.File, FileItemFlags.FileType) - { - Debug.Assert(extension != null); - ExtensionItem = extension; - } - - #endregion - - #region FileItemBase Overrides - - /// - /// Gets the extension of the file. Empty extensions are always returned with a '.'. - /// - public override sealed string Extension => ExtensionItem.Extension; - - #endregion - - #region FileItemBase Override Methods - - /// Refreshes the file. Returns true if it still exists. - /// - /// True if the file still exists. - public override sealed bool Refresh() { - FileInfo info = new FileInfo(FullName); - if (info.Exists && !info.Attributes.HasFlag(FileAttributes.Directory)) { - Attributes = info.Attributes; - - long oldSize = Size; - if (!info.Attributes.HasFlag(FileAttributes.ReparsePoint)) - Size = info.Length; - else - Size = 0L; - ExtensionItem.RefreshFile(Size, oldSize); - - LastWriteTimeUtc = info.LastWriteTimeUtc; - - return RefreshFinal(true); - } - ExtensionItem.RemoveFile(Size); - return RefreshFinal(false); - } - - /// Checks if the file still exists. - /// - /// True if the file exists. - public override sealed bool CheckExists() => CheckExistsFinal(File.Exists(FullName)); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Files/FileItemBase.cs b/WinDirStat.Net.Base/Model/Files/FileItemBase.cs deleted file mode 100644 index 34bcbdd..0000000 --- a/WinDirStat.Net.Base/Model/Files/FileItemBase.cs +++ /dev/null @@ -1,596 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Runtime.CompilerServices; -using System.Text; - -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Structures; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Model.Files { - /// The abstract base class for all file tree items. - [Serializable] - [DebuggerDisplay("{DebuggerDisplay,nq}")] - public abstract class FileItemBase : IComparable, IComparable, ITreemapItem { - - #region Constants - - /// - /// The static list of empty children to use for empty lists. This should never be modified. - /// - private protected static readonly List EmptyChildren = new List(); - - #endregion - - #region Fields - - // Fields and property fields are both stored here to keep track of memory usage - // ViewModel Events also has one event that will take up space - - /// Gets the type of this file item. - public FileItemType Type { get; } - /// The volatile state of the file. - private protected FileItemStates state; - /// The constant flags of the file. - private protected FileItemFlags flags; - - /// Gets the parent containing this file. - public FolderItem Parent { get; internal set; } - /// - /// Gets the UTC time of when the file was last written to. - /// If this is a container, it returns the most recent time of all children. - /// - public DateTime LastWriteTimeUtc { get; private protected set; } - /// Gets the name of the file. - public string Name { get; } - /// Gets the total size of the file and all of its children. - public long Size { get; private protected set; } - /// Gets the rectangle of the file for drawing in the treemap. - public Rectangle2S Rectangle { get; set; } - - #endregion - - #region Constructors - - /// Constructs the without any file info. - /// - /// The name of the item. - /// The type of the item. - /// The flags for the item (except ). - private protected FileItemBase(string name, FileItemType type, FileItemFlags flags) { - if (flags != FileItemFlags.None) - this.flags |= (flags & FileItemFlags.TypeFlagsMask); - if (type == FileItemType.Volume) - name = PathUtils.AddDirectorySeparator(name); - - Name = name; - Type = type; - state |= FileItemStates.Exists; - } - - /// Constructs the with a . - /// - /// The file information. - /// The type of the item. - /// The flags for the item (except ). - private protected FileItemBase(FileSystemInfo info, FileItemType type, FileItemFlags flags) - : this(info.Name, type, flags) - { - LastWriteTimeUtc = info.LastWriteTimeUtc; - Attributes = info.Attributes; - - if (!info.Attributes.HasFlag(FileAttributes.Directory) && - !info.Attributes.HasFlag(FileAttributes.ReparsePoint) && - info is FileInfo fileInfo) - Size = fileInfo.Length; - - if (!info.Exists) { - state &= ~FileItemStates.Exists; - Attributes = 0; - LastWriteTimeUtc = DateTime.MinValue; - } - } - - /// Constructs the with a . - /// - /// The file information. - /// The type of the item. - /// The flags for the item (except ). - private protected FileItemBase(IScanFileInfo info, FileItemType type, FileItemFlags flags) - : this(info.Name, type, flags) - { - LastWriteTimeUtc = info.LastWriteTimeUtc; - Attributes = info.Attributes; - - if (!info.IsDirectory && !info.IsSymbolicLink) - Size = info.Size; - } - - #endregion - - #region ViewModel Events - - // TODO: Eventually determine if we can move this to FolderItem - - /// Notifies any view models watching this item of important changes to the file. - [field: NonSerialized] - public event FileItemEventHandler Changed; - - /// Gets if the file is being watched by a view model. - public bool IsWatched => Changed != null; - - protected void RaiseChanged(FileItemEventArgs e) { - Changed?.Invoke(this, e); - } - protected void RaiseChanged(FileItemAction action) { - Changed?.Invoke(this, new FileItemEventArgs(action)); - } - protected void RaiseChanged(FileItemAction action, int index) { - Changed?.Invoke(this, new FileItemEventArgs(action, index)); - } - protected void RaiseChanged(FileItemAction action, List children, int index) { - Changed?.Invoke(this, new FileItemEventArgs(action, children, index)); - } - protected void RaiseChanged(FileItemAction action, IEnumerable children, int index) { - Changed?.Invoke(this, new FileItemEventArgs(action, children, index)); - } - protected void RaiseChanged(FileItemAction action, FileItemBase child, int index) { - Changed?.Invoke(this, new FileItemEventArgs(action, child, index)); - } - - public object GetViewModel() { - FileItemEventArgs e = new FileItemEventArgs(FileItemAction.GetViewModel); - RaiseChanged(e); - return e.ViewModel; - } - - public TViewModel GetViewModel() where TViewModel : class { - FileItemEventArgs e = new FileItemEventArgs(FileItemAction.GetViewModel); - RaiseChanged(e); - return e.ViewModel as TViewModel; - } - - #endregion - - #region Virtual Methods - - /// Refreshes the file. Returns true if it still exists. - /// - /// True if the file still exists. - public virtual bool Refresh() => true; - - /// Checks if the file still exists. - /// - /// True if the file exists. - public virtual bool CheckExists() => true; - - /// - /// Must be called at the end of in order to raise a Refresh change. - /// For file types only. - /// - /// - /// True if the file exists. - /// The passed parameter. - protected bool RefreshFinal(bool existsNew) { - Exists = existsNew; - if (IsWatched) - RaiseChanged(FileItemAction.Refreshed); - return existsNew; - } - - /// - /// Must be called at the end of in order to raise a Exists change. - /// For file types only. - /// - /// - /// True if the file exists. - /// The passed parameter. - protected bool CheckExistsFinal(bool existsNew) { - if (Exists != existsNew) { - Exists = existsNew; - if (IsWatched) - RaiseChanged(FileItemAction.Exists); - } - return existsNew; - } - - #endregion - - #region Virtual Properties - - /// Returns true if this folder has any children. - public virtual bool HasChildren => false; - /// - /// Gets the list of children for this folder. - /// This list is only for fast access and should never be modified. - /// - internal virtual List Children => EmptyChildren; - - /// - /// Gets the number of files and directories this folder contains. Returns -1 if this is not a - /// container. - /// - public virtual int ItemCount => -1; - /// - /// Gets the number of files this folder contains. Returns -1 if this is not a container. - /// - public virtual int FileCount { - get => -1; - protected set => throw InvalidSet(); - } - /// - /// Gets the number of directories this folder contains. Returns -1 if this is not a container. - /// - public virtual int SubdirCount { - get => -1; - protected set => throw InvalidSet(); - } - - /// - /// Gets the extension item of the file. - /// Returns if this is not a file. - /// - public virtual ExtensionItem ExtensionItem => ExtensionItem.NotAFile; - /// - /// Gets the extension of the file. Empty file extensions are always returned with a '.'. - /// Returns if this is not a file. - /// - public virtual string Extension => string.Empty; - - #endregion - - #region Properties - - /// Finds the absolute root node. - public RootItem Root { - get { - if (IsAbsoluteRootType) - return (RootItem) this; - else - return Parent.Root; - } - } - - /// Gets the file root node - public FolderItem FileRoot { - get { - if (IsFileRootType) - return (RootItem) this; - else - return Parent.Root; - } - } - - /// - /// Gets the folder/drive parent of the node. - /// This is used to skip FileCollection containers. - /// - public FolderItem FileParent { - get { - if (Parent != null && Parent.Type == FileItemType.FileCollection) - return Parent.Parent; - return Parent; - } - } - - /// - /// Gets the local time of when the file was last written to. - /// If this is a container, it returns the most recent time of all children. - /// - public DateTime LastWriteTime => LastWriteTimeUtc.ToLocalTime(); - - /// Gets the visible level of the item in the tree. - public int VisibleLevel => Parent != null ? Parent.VisibleLevel + 1 : 0; - - /// Gets the file level of the item in the tree. - public int FileLevel => Parent != null ? (Parent.FileLevel + (Parent.IsFileType ? 1 : 0)) : 0; - - /// Gets the path of the file. - public string FullName { - get { - if (IsFileRootType) - return ((RootItem) this).RootPath; - else if (IsFileType) - return PathUtils.CombineNoChecks(Parent.FullName, Name); - else if (Type != FileItemType.Computer) - return Parent.FullName; - else - return "::{20d04fe0-3aea-1069-a2d8-08002b30309d}";// Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); - } - } - - /// Gets this file's size relative to the parent's size. - public double Percent { - get { - if (IsAbsoluteRootType) - return 1d; - else if (Parent.Size == 0) - return 0d; - else - return (double) Size / Parent.Size; - } - } - - /// Gets if the file has a size of zero. - public bool IsEmptySize => Size == 0; - - /// Gets if this file is a shortcut. - public bool IsShortcut => IsReparsePointFile || (Extension == ".lnk"); - - /// Gets the attributes for this file. - public FileAttributes Attributes { - get { - FileAttributes attr = 0; - if (IsReadOnlyFile) attr |= FileAttributes.ReadOnly; - if (IsHiddenFile) attr |= FileAttributes.Hidden; - if (IsSystemFile) attr |= FileAttributes.System; - if (IsArchiveFile) attr |= FileAttributes.Archive; - if (IsCompressedFile) attr |= FileAttributes.Compressed; - if (IsEncryptedFile) attr |= FileAttributes.Encrypted; - if (IsReparsePointFile) attr |= FileAttributes.ReparsePoint; - if (IsTemporaryFile) attr |= FileAttributes.Temporary; - return attr; - } - private protected set { - IsReadOnlyFile = value.HasFlag(FileAttributes.ReadOnly); - IsHiddenFile = value.HasFlag(FileAttributes.Hidden); - IsSystemFile = value.HasFlag(FileAttributes.System); - IsArchiveFile = value.HasFlag(FileAttributes.Archive); - IsCompressedFile = value.HasFlag(FileAttributes.Compressed); - IsEncryptedFile = value.HasFlag(FileAttributes.Encrypted); - IsReparsePointFile = value.HasFlag(FileAttributes.ReparsePoint); - IsTemporaryFile = value.HasFlag(FileAttributes.Temporary); - } - } - /// Gets the file attributes as a displayable string. - public string AttributesString { - get { - StringBuilder str = new StringBuilder(); - if (IsReadOnlyFile) str.Append('R'); - if (IsHiddenFile) str.Append('H'); - if (IsSystemFile) str.Append('S'); - if (IsArchiveFile) str.Append('A'); - if (IsCompressedFile) str.Append('C'); - if (IsEncryptedFile) str.Append('E'); - return str.ToString(); - } - } - /// Gets the file attributes as an integer to use for sorting. - public short SortAttributes => unchecked((short) (flags & FileItemFlags.SortAttributesMask)); - - #endregion - - #region Constant Flags - - /// This file has the attribute. - public bool IsReadOnlyFile { - get => flags.HasFlag(FileItemFlags.ReadOnly); - private set => flags = flags.SetFlag(FileItemFlags.ReadOnly, value); - } - /// This file has the attribute. - public bool IsHiddenFile { - get => flags.HasFlag(FileItemFlags.Hidden); - private set => flags = flags.SetFlag(FileItemFlags.Hidden, value); - } - /// This file has the attribute. - public bool IsSystemFile { - get => flags.HasFlag(FileItemFlags.System); - private set => flags = flags.SetFlag(FileItemFlags.System, value); - } - /// This file has the attribute. - public bool IsArchiveFile { - get => flags.HasFlag(FileItemFlags.Archive); - private set => flags = flags.SetFlag(FileItemFlags.Archive, value); - } - /// This file has the attribute. - public bool IsCompressedFile { - get => flags.HasFlag(FileItemFlags.Compressed); - private set => flags = flags.SetFlag(FileItemFlags.Compressed, value); - } - /// This file has the attribute. - public bool IsEncryptedFile { - get => flags.HasFlag(FileItemFlags.Encrypted); - private set => flags = flags.SetFlag(FileItemFlags.Encrypted, value); - } - /// This file has the attribute. - public bool IsReparsePointFile { - get => flags.HasFlag(FileItemFlags.ReparsePoint); - private set => flags = flags.SetFlag(FileItemFlags.ReparsePoint, value); - } - /// This file has the attribute. - public bool IsTemporaryFile { - get => flags.HasFlag(FileItemFlags.Temporary); - private set => flags = flags.SetFlag(FileItemFlags.Temporary, value); - } - - /// True if this directory is case sensitive. - public bool CaseSensitive { - get => flags.HasFlag(FileItemFlags.CaseSensitive); - private protected set => flags = flags.SetFlag(FileItemFlags.CaseSensitive, value); - } - /// True if this type can contain other nodes. - public bool IsContainerType { - get => flags.HasFlag(FileItemFlags.ContainerType); - private set => flags = flags.SetFlag(FileItemFlags.ContainerType, value); - } - /// True if this is a real file system node. - public bool IsFileType { - get => flags.HasFlag(FileItemFlags.FileType); - private set => flags = flags.SetFlag(FileItemFlags.FileType, value); - } - /// True if this node contains the root path for the file tree. - public bool IsFileRootType { - get => flags.HasFlag(FileItemFlags.FileRootType); - private set => flags = flags.SetFlag(FileItemFlags.FileRootType, value); - } - /// True if this node never has a parent. A computer node is always of this type. - public bool IsAbsoluteRootType { - get => flags.HasFlag(FileItemFlags.AbsoluteRootType); - private set => flags = flags.SetFlag(FileItemFlags.AbsoluteRootType, value); - } - /// True if this node is an absolute or file root. - public bool IsAnyRootType { - get => (flags & (FileItemFlags.FileRootType | FileItemFlags.AbsoluteRootType)) != 0; - } - - #endregion - - #region State Flags - - /// - /// This lock is static because these values are not accessed often and only within two threads. - /// (mostly in just the async thread) - /// - private static readonly object stateLock = new object(); - - /// Gets if the folder and all its children have been fully scanned. - public bool IsDone { - get { - lock (stateLock) - return state.HasFlag(FileItemStates.Done); - } - private protected set { - lock (stateLock) - state = state.SetFlag(FileItemStates.Done, value); - } - } - /// Gets if the folder needs to be validated. - public bool IsInvalidated { - get { - lock (stateLock) - return state.HasFlag(FileItemStates.Invalidated); - } - private protected set { - lock (stateLock) { - // Perform two operations in the same lock - if (value) - state &= ~FileItemStates.Done; - state = state.SetFlag(FileItemStates.Invalidated, value); - } - } - } - /// Gets if the folder is currently validating. - public bool IsValidating { - get { - lock (stateLock) - return state.HasFlag(FileItemStates.Validating); - } - private protected set { - lock (stateLock) { - // Perform two operations in the same lock - if (value) - state &= ~FileItemStates.Invalidated; - state = state.SetFlag(FileItemStates.Validating, value); - } - } - } - /// Gets if the file exists in the system. - public bool Exists { - get { - lock (stateLock) - return state.HasFlag(FileItemStates.Exists); - } - private protected set { - bool changed = false; - lock (stateLock) { - changed = value != Exists; - state = state.SetFlag(FileItemStates.Exists, value); - } - if (changed && IsWatched) - RaiseChanged(FileItemAction.Exists); - } - } - - #endregion - - #region ITreemapItem Implementation - - /// Gets if this treemap item is a leaf that should be drawn. - public bool IsLeaf => !IsContainerType; - - /// Gets the color of this treemap item leaf. - public Rgb24Color Color { - get { - switch (Type) { - case FileItemType.File: return ExtensionItem.Color; - case FileItemType.FreeSpace: return new Rgb24Color(100, 100, 100); - case FileItemType.Unknown: return new Rgb24Color(255, 255, 0); - default: return Rgb24Color.Black; - } - } - } - - /// Gets the number of children in this treemap item. - public virtual int ChildCount => 0; - - /// Gets the child at the specified index in the treemap item. - public virtual FileItemBase this[int index] => throw InvalidCall(); - /// Gets the child at the specified index in the treemap item. - ITreemapItem ITreemapItem.this[int index] => this[index]; - - /// Gets the number of children in this treemap item. - Rectangle2I ITreemapItem.Rectangle { - get => Rectangle; - set => Rectangle = (Rectangle2S) value; - } - - #endregion - - #region Exception Helpers - - /// - /// Throws an stating the calling method cannot be called due - /// to lack of support from this class. - /// - private Exception InvalidCall([CallerMemberName] string name = null) { - return new InvalidOperationException($"{name} cannot be called because this item does not " + - $"support it!"); - } - /// - /// Throws an stating the calling property cannot be set due - /// to lack of support from this class. - /// - private Exception InvalidSet([CallerMemberName] string name = null) { - return new InvalidOperationException($"{name} cannot be set because this item does not " + - $"support it!"); - } - - #endregion - - #region IComparable Implementation - - /// Compares this file to another based on size in descending order. - /// - /// The other file to compare to. - /// The comparison result. - public int CompareTo(FileItemBase other) { - int diff = other.Size.CompareTo(Size); - if (diff == 0) - return string.Compare(Name, other.Name, true); - return diff; - } - - /// Compares this file to another based on size in descending order. - /// - /// The other file to compare to. - /// The comparison result. - int IComparable.CompareTo(object obj) { - return CompareTo((FileItemBase) obj); - } - - #endregion - - #region ToString/DebuggerDisplay - - /// Gets the string representation of this item. - public override string ToString() => $"{Type}: {Name}"; - - /// Gets the string used to represent the file in the debugger. - private string DebuggerDisplay => Name; - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Files/FolderItem.cs b/WinDirStat.Net.Base/Model/Files/FolderItem.cs deleted file mode 100644 index ae23b18..0000000 --- a/WinDirStat.Net.Base/Model/Files/FolderItem.cs +++ /dev/null @@ -1,1142 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Model.Files { - /// The base class for containing all other file items. - /// - /// Rules for Folder structure: - /// Folders/Volumes can store files in 3 possible ways: - /// A) 0-1 files, unlimited containers - /// B) unlimited files, 0 containers - /// C) 1 file collection (with 2+ files), 1+ containers - /// If more than one file is found then we know containers are not being stored. - /// - [Serializable] - [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class FolderItem : FileItemBase { - - #region Fields - - /// - /// The list of children in the folder. - /// Always use the list modification methods to add or remove from the list. This is important - /// because they account for if is being used. - /// - protected volatile List children = EmptyChildren; - - /// Gets the number of files this folder contains. - public override sealed int FileCount { get; protected set; } - /// Gets the number of directories this folder contains. - public override sealed int SubdirCount { get; protected set; } - - #endregion - - #region Constructors - - /// Constructs a file collection . - private FolderItem() - : base(StringConstants.FileCollectionName, FileItemType.FileCollection, - FileItemFlags.ContainerType) - { - // File collections are only created when adding children to them - EnsureChildren(); - } - - /// Constructs the without any file info. - /// - /// The name of the item. - /// The type of the item. - /// The flags for the item (except ). - private protected FolderItem(string name, FileItemType type, FileItemFlags flags) - : base(name, type, flags) - { - } - - /// Constructs the with a . - /// - /// The file information. - /// The type of the item. - /// The flags for the item (except ). - private protected FolderItem(FileSystemInfo info, FileItemType type, FileItemFlags flags) - : base(info, type, flags) - { - //CaseSensitive = DirectoryCaseSensitivity.IsCaseSensitive(info.FullName); - } - - /// Constructs the with a . - /// - /// The file information. - /// The type of the item. - /// The flags for the item (except ). - private protected FolderItem(IScanFileInfo info, FileItemType type, FileItemFlags flags) - : base(info, type, flags) - { - //CaseSensitive = DirectoryCaseSensitivity.IsCaseSensitive(info.FullName); - } - - /// - /// Constructs the directory with a . - /// - /// - /// The file information. - /// The type of the item. - /// The flags for the item (except ). - public FolderItem(FileSystemInfo info) - : base(info, FileItemType.Directory, FileItemFlags.ContainerType | FileItemFlags.FileType) - { - } - - /// - /// Constructs the directory with a . - /// - /// - /// The file information. - /// The type of the item. - /// The flags for the item (except ). - public FolderItem(IScanFileInfo info) - : base(info, FileItemType.Directory, FileItemFlags.ContainerType | FileItemFlags.FileType) - { - } - - #endregion - - #region ViewModel Events (Unused) - /* - // TODO: Eventually determine if we can move this to FolderItem - - /// Notifies any view models watching this item of important changes to the file. - [field: NonSerialized] - public event FileItemEventHandler Changed; - - /// Gets if the file is being watched by a view model. - public bool IsWatched { - get => Changed != null; - } - - protected void RaiseChanged(FileItemEventArgs e) { - Changed?.Invoke(this, e); - } - protected void RaiseChanged(FileItemAction action) { - Changed?.Invoke(this, new FileItemEventArgs(action)); - } - protected void RaiseChanged(FileItemAction action, int index) { - Changed?.Invoke(this, new FileItemEventArgs(action, index)); - } - protected void RaiseChanged(FileItemAction action, List children, int index) { - Changed?.Invoke(this, new FileItemEventArgs(action, children, index)); - } - protected void RaiseChanged(FileItemAction action, FileItemBase child, int index) { - Changed?.Invoke(this, new FileItemEventArgs(action, child, index)); - } - - public object GetViewModel() { - FileItemEventArgs e = new FileItemEventArgs(FileItemAction.GetView); - RaiseChanged(e); - return e.ViewModel; - } - - public TViewModel GetViewModel() { - FileItemEventArgs e = new FileItemEventArgs(FileItemAction.GetView); - RaiseChanged(e); - return (TViewModel) e.ViewModel; - } - */ - #endregion - - #region FileItemBase Overrides - - /// Returns true if this folder has any children. - public override sealed bool HasChildren => children.Count > 0; - /// Gets the list of children for this folder. - /// This list is only for fast access and should never be modified. - /// - internal override sealed List Children => children; - - /// Gets the number of fils and directories this folder contains. - public override sealed int ItemCount => FileCount + SubdirCount; - - #endregion - - #region ITreemapItem Overrides - - /// Gets the number of children in this container. - public override sealed int ChildCount => children.Count; - - /// Gets the child at the specified index in the container. - public override sealed FileItemBase this[int index] => children[index]; - - #endregion - - #region Helper Properties - - /// Returns true if the folder is storing at least 2 files and 0 containers. - private bool IsStoringMultipleFiles { - get { - // Always called from a File Folder, for a file folder. - // This is why the return strange. - if (Type == FileItemType.FileCollection) - return false; - // If true, another file means containers are not being stored. - bool fileFound = false; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (!child.IsContainerType) { - if (child.Type == FileItemType.File) { - if (!fileFound) - fileFound = true; - else - return true; - } - } - else { - return false; - } - } - return false; - } - } - /// Returns true if the folder is storing any number of containers. - private bool IsStoringContainers { - get { - // Always called from a File Folder, for a file folder. - // This is why the return strange. - if (Type == FileItemType.FileCollection) - return true; - // If true, another file means containers are not being stored. - bool fileFound = false; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (!child.IsContainerType) { - if (child.Type == FileItemType.File) { - if (!fileFound) - fileFound = true; - else - return false; - } - } - else { - return true; - } - } - return false; - } - } - - /// Returns true if the folder is storing more than 1 container. - private bool IsStoringMultipleContainers { - get { - // Always called from a File Folder, for a file folder. - // This is why the return strange. - if (Type == FileItemType.FileCollection) - return true; - // If true, another file means containers are not being stored. - bool fileFound = false; - bool containerFound = false; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (!child.IsContainerType) { - if (child.Type == FileItemType.File) { - if (!fileFound) - fileFound = true; - else - return false; - } - } - else if (!containerFound) { - containerFound = true; - } - else { - return true; - } - } - return false; - } - } - - /// Returns true if the folder is storing just 1 container. - private bool IsStoringOneContainer { - get { - // Always called from a File Folder, for a file folder. - // This is why the return strange. - if (Type == FileItemType.FileCollection) - return true; - // If true, another file means containers are not being stored. - bool fileFound = false; - bool containerFound = false; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (!child.IsContainerType) { - if (child.Type == FileItemType.File) { - if (!fileFound) - fileFound = true; - else - return false; - } - } - else if (!containerFound) { - containerFound = true; - } - else { - return false; - } - } - return containerFound; - } - } - - - /// - /// Gets if the folder is using for its list. - /// - internal protected bool IsEmpty => children == EmptyChildren; - - #endregion - - #region Item Finders - - /// Gets the file collection for this folder. - /// - /// The folder's file collection, or null if it does not exist. - public FolderItem GetFileCollection() { - if (Type == FileItemType.FileCollection) - return this; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (child.Type == FileItemType.FileCollection) - return (FolderItem) child; - } - return null; - } - - /// Gets the first file in this folder. - /// - /// The folder's first file, or null if one does not exist. - public FileItem GetFirstFile() { - // Always called from a File Folder, for a file folder. - // This is why the return strange. - if (Type == FileItemType.FileCollection) - return null; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (child.Type == FileItemType.File) - return (FileItem) child; - } - return null; - } - - /// Gets the first file in this folder and checks if there are multiple files. - /// - /// The output result of if there are multiple files. - /// The folder's only file, or null if there is not exactly one file. - public FileItem GetFirstFile(out bool multipleFiles) { - multipleFiles = false; - // Always called from a File Folder, for a file folder. - // This is why the return strange. - if (Type == FileItemType.FileCollection) - return null; - FileItem firstFile = null; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (firstFile == null) { - if (child.Type == FileItemType.File) - firstFile = (FileItem) child; - } - else if (child.Type == FileItemType.File) { - // Multiple files encountered, we're not storing a single file - multipleFiles = true; - return firstFile; - } - else if (child.IsContainerType) { - // Container encountered, we must be storing a single file - return firstFile; - } - } - return firstFile; - } - - /*/// Gets the only file in this folder. - /// - /// The folder's only file, or null if there is not exactly one file. - public FileItem GetSingleFile() { - // Always called from a File Folder, for a file folder. - // This is why the return strange. - if (Type == FileItemType.FileCollection) - return null; - FileItem firstFile = null; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (firstFile == null) { - if (child.Type == FileItemType.File) - firstFile = (FileItem) child; - } - else if (child.Type == FileItemType.File) { - // Multiple files encountered, we're not storing a single file - return null; - } - else if (child.IsContainerType) { - // Container encountered, we must be storing a single file - return firstFile; - } - } - return firstFile; - }*/ - - #endregion - - #region Add/Remove Item - - /// Adds the item to the container. - /// - /// The item to add. - public void AddItem(FileItemBase item) { - FolderItem fileCollection = null; - FileItem firstFile = null; - // Finding these items is not relevant when adding items like FreeSpace or Unknown - if (item.Type == FileItemType.File || (item.IsContainerType && !item.IsAnyRootType)) { - fileCollection = GetFileCollection(); - firstFile = GetFirstFile(); - } - AddItem(item, ref fileCollection, ref firstFile); - } - - /// - /// Adds the item to the container and keeps track of the file collection and single file. - /// - /// - /// The item to add. - /// - /// The container's file collection. Keep track of this when scanning this directory. - /// - /// - /// The container's first file. Keep track of this when scanning this directory. - /// - public void AddItem(FileItemBase item, ref FolderItem fileCollection, ref FileItem firstFile) { - if (Type == FileItemType.FileCollection) - throw new InvalidOperationException($"Cannot call {nameof(AddItem)} from a File Collection!"); - - // We know we're adding an item to children, make sure it's setup - EnsureChildren(); - - lock (children) { - if (item.Type == FileItemType.File) { - // Add the file to the extensions - item.ExtensionItem.AddFile(item.Size); - - if (fileCollection != null) { - fileCollection.Add(item); - fileCollection.Invalidate(); - // Item added to file collection, do not continue - Debug.Assert(IsInvalidated); - return; - } - else if (firstFile == null) { - // Our first file! Let's celebrate by keeping track of it. - // If more files are added then it will no longer be tracked. - firstFile = (FileItem) item; - } - else if (IsStoringContainers) { - // We've hit our limit of only one visible file when a - // folder is storing non-files. Move to FileCollection. - fileCollection = new FolderItem(); - Remove(firstFile); - Add(fileCollection); - fileCollection.Add(firstFile); - fileCollection.Add(item); - fileCollection.Invalidate(); - firstFile = null; - // Item added to file collection, do not continue - Debug.Assert(IsInvalidated); - return; - } - // Removed after file -> firstFile (and was unassigned when holding more files) - // file is only non-null when one file is being stored (with or without other files) - /*else { - bool storingContainers = IsStoringContainers; - //children.Count == 0 is wrong, I forgot about Free/Unknown Space - if (children.Count == 0 || (firstFile == null && storingContainers)) { - // Our first file! Let's celebrate by keeping track of it. - // If more files are added then it will no longer be tracked. - firstFile = (FileItem) item; - } - else if (firstFile != null) { - if (storingContainers) { - // We've hit our limit of only one visible file when a - // folder is storing non-files. Move to FileCollection. - fileCollection = new FolderItem(); - Remove(firstFile); - Add(fileCollection); - fileCollection.Add(firstFile); - fileCollection.Add(item); - fileCollection.Invalidate(); - firstFile = null; - // Item added to file collection, do not continue - return; - } - firstFile = null; - } - }*/ - } - else if (item.IsContainerType && IsStoringMultipleFiles) { - // Setup file collection if the folder needs to store a container item - Debug.Assert(fileCollection == null); - fileCollection = new FolderItem(); - List files = ClearAndGetFiles(); - Add(fileCollection); - fileCollection.AddRange(files); - fileCollection.Invalidate(); - firstFile = null; - } - - Add(item); - Invalidate(); - - Debug.Assert(IsInvalidated); - } - } - - /// Removes the item from the container. - /// - /// The item to remove. - public void RemoveItem(FileItemBase item) { - FolderItem fileCollection = null; - //FileItem firstFile = null; - // Finding these items is not relevant when adding items like FreeSpace or Unknown - if (item.Type == FileItemType.File || (item.IsContainerType && !item.IsAnyRootType)) { - fileCollection = GetFileCollection(); - //firstFile = GetFirstFile(); - } - RemoveItem(item, ref fileCollection/*, ref firstFile*/); - } - - /// - /// Removes the item from the container and keeps track of the file collection and single file. - /// - /// - /// The item to remove. - /// - /// The container's file collection. Keep track of this when scanning this directory. - /// - /// - /// The container's single file. Keep track of this when scanning this directory. - /// - public void RemoveItem(FileItemBase item, ref FolderItem fileCollection/*, ref FileItem firstFile*/) { - if (Type == FileItemType.FileCollection) - throw new InvalidOperationException($"Cannot call {nameof(AddItem)} from a File Collection!"); - - lock (children) { - if (item.Type == FileItemType.File) { - // Remove the file from the extensions - item.ExtensionItem.RemoveFile(item.Size); - - if (fileCollection != null) { - fileCollection.Remove(item); - if (fileCollection.children.Count == 1) { - // Once we go down to one file, we'll no longer need the file collection - //firstFile = (FileItem) fileCollection.children[0]; - FileItemBase firstFile = fileCollection.children[0]; - fileCollection.RemoveAt(0); - Remove(fileCollection); - Add(firstFile); - Invalidate(); - // It's dead Jim, remove the reference - fileCollection = null; - } - else { - // Standard procedure, no changes in structure - fileCollection.Invalidate(); - } - return; - } - } - else if (item.IsContainerType) { - // Recursively remove all of the container's children - ((FolderItem) item).RecurseClearChildren(); - - if (fileCollection != null && IsStoringContainers) { - // No more containers, open the gate for files to return back to folder. - // Also remember to remove the no-longer-in-use file collection. - Remove(item); - List files = fileCollection.ClearAndGetChildren(); - //firstFile = (FileItem) files[0]; - Remove(fileCollection); - AddRange(files); - Invalidate(); - // It's dead Jim, remove the reference - fileCollection = null; - return; - } - } - - Remove(item); - Invalidate(); - - // Set children back to EmptyChildren if we removed the last item - EnsureEmptyChildren(); - } - } - - /// - /// Recursively clears this folder's children from the file tree and any other associations. - /// - private protected void RecurseClearChildren() { - foreach (FileItemBase child in children) { - if (child is FolderItem subdir && !subdir.IsEmpty) - subdir.RecurseClearChildren(); - else if (child.Type == FileItemType.File) - child.ExtensionItem.RemoveFile(child.Size); - } - Clear(); - } - - /*/// - /// Removes this folder's files from the file tree and any other associations. - /// - /// Handles changes to the folder structure like normally removing an item. - /// - public void ClearFileItems() { - if (IsEmpty) - return; - - lock (children) { - FolderItem fileCollection = GetFileCollection(); - if (fileCollection != null) - ClearFileCollectionItems(fileCollection); - } - }*/ - - /// - /// Recursively removes this folder's children from the file tree and any other associations. - /// - /// Handles changes to the folder structure like normally removing an item. - /// - public void ClearItems() { - if (IsEmpty) - return; - - int count; - - List subdirs = new List(); - lock (children) { - count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (child is FolderItem subdir && child.Type != FileItemType.FileCollection) - subdirs.Add(subdir); - } - } - - // Clear all subdirectories outside of the children - // lock to prevent the UI from freezing. - count = subdirs.Count; - for (int i = 0; i < count; i++) { - subdirs[i].ClearItems(); - } - - lock (children) { - FolderItem fileCollection = null; - for (int i = 0; i < children.Count; i++) { - FileItemBase child = children[i]; - /*if (child is FolderItem subdir && !subdir.IsEmpty) { - if (subdir.Type == FileItemType.FileCollection) { - ClearFileCollectionItems(ref fileCollection); - continue; - } - else { - subdir.ClearItems(); - } - }*/ - // File Collections do not get removed - // through RemoveItem so let's continue - if (child.Type == FileItemType.FileCollection) - fileCollection = (FolderItem) child; - else if (child.Type == FileItemType.File) - child.ExtensionItem.RemoveFile(child.Size); - //RemoveAt(0); - //RemoveAt(i); - //RemoveItem(child, ref fileCollection); - //i--; - } - Clear(); - children = EmptyChildren; - fileCollection?.ClearFileCollectionItems(); - FileCount = 0; - SubdirCount = 0; - Size = 0; - } - } - - private void ClearFileCollectionItems() { - lock (children) { - for (int i = 0; i < children.Count; i++) { - FileItemBase child = children[i]; - child.ExtensionItem.RemoveFile(child.Size); - } - Clear(); - children = EmptyChildren; - } - } - - #endregion - - #region List Modification - - /// Adds the item to the container. - /// - /// The item to add. - protected void Add(FileItemBase item) { - //EnsureChildren(); - int index = children.Count; - children.Add(item); - item.Parent = this; - if (IsWatched) - RaiseChanged(FileItemAction.ChildrenAdded, item, index); - } - - /// Adds or removes the item from the container based on a conditional value. - /// - /// The item to add or remove. - /// The condition to add the item instead of removing it. - protected void AddOrRemove(FileItemBase item, bool addCondition) { - int index = children.IndexOf(item); - if (addCondition && index == -1) - Add(item); - else if (!addCondition && index != -1) - RemoveAt(index); - } - - /// Adds the items to the container. - /// - /// The items to add. - protected void AddRange(IEnumerable items) { - //EnsureChildren(); - int index = children.Count; - children.AddRange(items); - foreach (FileItemBase item in items) - item.Parent = this; - if (IsWatched) - RaiseChanged(FileItemAction.ChildrenAdded, items.ToList(), index); - } - - /// Removes the items from the container. - /// - /// The items to remove. - protected void RemoveRange(IEnumerable items) { - foreach (FileItemBase item in items) { - children.Remove(item); - item.Parent = null; - } - if (IsWatched) - RaiseChanged(FileItemAction.ChildrenRemoved, items.ToList(), -1); - } - - /// Removes the item from the container. - /// - /// The item to remove. - /// true if the item existed and was removed. - protected bool Remove(FileItemBase item) { - if (children.Remove(item)) { - item.Parent = null; - if (IsWatched) - RaiseChanged(FileItemAction.ChildrenRemoved, item, -1); - return true; - } - return false; - } - - /// Removes the item at the specified index in the container. - /// - /// The index of the item to remove. - protected void RemoveAt(int index) { - FileItemBase item = children[index]; - children.RemoveAt(index); - item.Parent = null; - if (IsWatched) - RaiseChanged(FileItemAction.ChildrenRemoved, item, index); - } - - /// Removes the items at the specified index in the container. - /// - /// The index of the items to remove. - /// The number of items to remove. - protected void RemoveRange(int index, int count) { - List items = children.GetRange(index, count); - children.RemoveRange(index, count); - for (int i = 0; i < count; i++) - items[i].Parent = null; - if (IsWatched) - RaiseChanged(FileItemAction.ChildrenRemoved, items.GetFullRange(), index); - } - - /// Clears the list. - protected void Clear() { - int count = children.Count; - if (count > 0) { - for (int i = 0; i < count; i++) - children[i].Parent = null; - if (IsWatched) { - List oldChildren = children.GetFullRange(); - children.Clear(); - //children = EmptyChildren; - RaiseChanged(FileItemAction.ChildrenRemoved, oldChildren, 0); - } - else { - children.Clear(); - //children = EmptyChildren; - } - } - } - - /// Clears the list and returns the range that was cleared. - private List ClearAndGetChildren() { - int count = children.Count; - if (count > 0) { - for (int i = 0; i < count; i++) - children[i].Parent = null; - List oldChildren = children.GetFullRange(); - children.Clear(); - if (IsWatched) - RaiseChanged(FileItemAction.ChildrenRemoved, oldChildren, 0); - return oldChildren; - } - return children;//EmptyChildren; - } - - /// Clears the list of files and returns the files that were cleared. - private List ClearAndGetFiles() { - int count = children.Count; - if (count > 0) { - List oldChildren = new List(); - for (int i = 0; i < children.Count; i++) { - FileItemBase child = children[i]; - if (child.Type == FileItemType.File) { - children[i].Parent = null; - oldChildren.Add(child); - children.RemoveAt(i); - i--; - } - } - if (IsWatched) - RaiseChanged(FileItemAction.ChildrenRemoved, oldChildren, -1); - return oldChildren; - } - return children;//EmptyChildren; - } - - /// Ensures the children are setup so that they can be locked. - protected void EnsureChildren() { - if (IsEmpty) - children = new List(4); - } - - /// Ensures the children are setup so that they can be locked. - /// - /// The capacity of the new list. - protected void EnsureChildren(int capacity) { - if (IsEmpty) - children = new List(capacity); - } - - /// - /// Ensures the children are assigned to if nothing is - /// contained in them. - /// - protected void EnsureEmptyChildren() { - if (!IsEmpty) { - lock (children) { - if (children.Count == 0) - children = EmptyChildren; - } - } - } - - #endregion - - #region Validation - - /// - /// Marks the folder as . Which means all subitems have been - /// scanned. - /// - public void Finish() { - IsDone = true; - if (IsWatched) - RaiseChanged(FileItemAction.Done); - } - - /// Fully validates the file item tree from this folder and above. - public void UpdwardsFullValidate() { - // Something to validate - if (!IsEmpty) { - ValidateImpl(true); - lock (children) { - children.Sort(); - children.Minimize(); - } - } - Parent?.FullValidateImpl(); - } - - /// - /// Upwards invalidates this folder and every ancestor and marks it as needing validation in the - /// future. - /// - protected void Invalidate() { - if (!IsInvalidated) { - // This is automatically set inside the same lock when IsInvalidated is set to true - //IsDone = false; - IsInvalidated = true; - if (IsWatched) - RaiseChanged(FileItemAction.Invalidated); - Parent?.Invalidate(); - } - } - - /// - /// Validates the container and all invalidated children. - /// For use when scanning is still underway, but the UI wants to be updated. - /// - private protected bool ValidateImpl(bool force) { - if (!IsInvalidated || (IsValidating && !force)) - return false; - while (IsValidating) - Thread.Sleep(1); - - // This is automatically set inside the same lock when IsValidating is set to true - //IsInvalidated = false; - IsValidating = true; - - if (IsEmpty) { - // If we're validating and empty, it means something was removed - Size = 0; - if (IsFileType) { - DirectoryInfo directoryInfo = new DirectoryInfo(FullName); - // Use the directory's LastWriteTime when empty - LastWriteTimeUtc = directoryInfo.LastWriteTimeUtc; - } - else { - LastWriteTimeUtc = DateTime.MinValue; - } - if (IsWatched) - RaiseChanged(FileItemAction.ValidatedSortOrder); - IsValidating = false; - return true; - } - - // True, if any of the sort orders that can change, have changed - bool sortOrderChanged = false; - long oldSize = Size; - DateTime oldLastChangeTime = LastWriteTimeUtc; - bool thisIsDone = IsDone; - bool isDone = true; - - lock (children) { - UnknownItem unknown = null; - FileItemBase freeSpace = null; - FileCount = 0; - SubdirCount = 0; - Size = 0; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (child.Type == FileItemType.Unknown) { - // Don't count the size for this because it will - // be updated based on the remaining size. - unknown = (UnknownItem) child; - continue; - } - else if (child.Type == FileItemType.FreeSpace) { - // Don't count the size for this because it will - // be excluded when updating unknown's size. - freeSpace = child; - continue; - } - if (child is FolderItem childFolder) { - sortOrderChanged |= childFolder.ValidateImpl(force); - if (!thisIsDone && isDone) - isDone = childFolder.IsDone; - } - Size += child.Size; - //LastAccessTime = Max(LastAccessTime, child.LastAccessTime); - LastWriteTimeUtc = MaxDateTime(LastWriteTimeUtc, child.LastWriteTimeUtc); - if (child.Type == FileItemType.File || child.Type == FileItemType.FreeSpace) { - FileCount++; - } - else { - FileCount += child.FileCount; - SubdirCount += child.SubdirCount; - if (child.Type != FileItemType.FileCollection) { - SubdirCount++; - } - } - } - if (unknown != null) { - unknown.UpdateSize(Size); - Size += unknown.Size; - } - if (freeSpace != null) { - Size += freeSpace.Size; - } - sortOrderChanged |= (oldSize != Size); - - if (!thisIsDone && isDone) - Finish(); - } - - IsValidating = false; - if (IsWatched) { - if (sortOrderChanged) - RaiseChanged(FileItemAction.ValidatedSortOrder); - else - RaiseChanged(FileItemAction.Validated); - } - return sortOrderChanged || (oldLastChangeTime != LastWriteTimeUtc); - } - - /// Fully validates the file item tree and prepares it for use. - private protected void FullValidateImpl() { - // Nothing to validate - if (IsEmpty) - return; - - lock (children) { - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (child is FolderItem folder) - folder.FullValidateImpl(); - } - children.Sort(); - children.Minimize(); - } - } - - /// Gets the maximum of two s. - private static DateTime MaxDateTime(DateTime a, DateTime b) { - return (a > b ? a : b); - } - - #endregion - - #region ToString/DebuggerDisplay - - /// Gets the string representation of this item. - public override string ToString() { - if (Type == FileItemType.FileCollection) - return $"{Type}[{children.Count:N0}]"; - return $"{Type}[{children.Count:N0}]: {Name}"; - } - - /// Gets the string used to represent the file in the debugger. - private string DebuggerDisplay { - get { - if (Type == FileItemType.FileCollection) - return $"[{children.Count:N0}]: "; - return $"[{children.Count:N0}]: {Name}"; - } - } - - #endregion - - #region Override Methods - - /// Refreshes the file. Returns true if it still exists. - /// - /// True if the file still exists. - public override bool Refresh() { - DirectoryInfo info = new DirectoryInfo(FullName); - // Remove all of our children first, they will be repopulated - ClearItems(); - if (info.Exists && info.Attributes.HasFlag(FileAttributes.Directory)) { - //CaseSensitive = DirectoryCaseSensitivity.IsCaseSensitive(info.FullName); - Attributes = info.Attributes; - Size = 0L; - LastWriteTimeUtc = info.LastWriteTimeUtc; - - return RefreshFinal(true); - } - return RefreshFinal(false); - } - - /// Checks if the file still exists. - /// - /// True if the file exists. - public override bool CheckExists() { - if (Type == FileItemType.FileCollection) - return true; - - if (Directory.Exists(FullName)) { - return CheckExistsFinal(true); - } - RecurseClearChildren(); - return CheckExistsFinal(false); - } - - #endregion - - #region Static Helpers - - /// - /// Removes all files in the enumeration whose ancestors are also in the enumeration. - /// - /// - /// The enumeration with ancestor conflicts removed. - public static FileItemBase[] IsolateAncestores(IEnumerable files) { - // TODO: This can probably be optimized more - List fileList = files.ToList(); - for (int i = 0; i < fileList.Count; i++) { - FileItemBase file = fileList[i]; - bool hasAncestor = false; - FolderItem ancestor = file.FileParent; - while (ancestor != null && !hasAncestor) { - for (int j = 0; j < fileList.Count; j++) { - if (ancestor == fileList[j]) { - hasAncestor = true; - fileList.RemoveAt(i); - i--; - break; - } - } - ancestor = ancestor.FileParent; - } - } - return fileList.ToArray(); - } - - /*/// Gets if the file contains the specified ancestor. - /// - /// The file to check the ancestors of. - /// The ancestor to check with. - public bool ContainsAncestor(FileItemBase file, FolderItem ancestor) { - - }*/ - - /// Gets the ancestores for the file from bottom to top. - /// - /// The file to get the ancestores of. - /// The ancestors of the file. - public static IEnumerable GetAncestores(FileItemBase file) { - FolderItem parent = file.Parent; - while (parent != null) { - yield return parent; - parent = parent.Parent; - } - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Files/FreeSpaceItem.cs b/WinDirStat.Net.Base/Model/Files/FreeSpaceItem.cs deleted file mode 100644 index e6953e9..0000000 --- a/WinDirStat.Net.Base/Model/Files/FreeSpaceItem.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Model.Files { - /// The file tree item that displays the amount of unused space in the drive. - [Serializable] - [DebuggerDisplay("{DebuggerDisplay,nq}")] - public sealed class FreeSpaceItem : FileItemBase { - - #region Fields - - /// The containing this space. - private readonly RootItem rootParent; - - #endregion - - #region Constructors - - /// Constructs the . - /// - /// The containing this space. - internal FreeSpaceItem(RootItem rootParent) - : base(StringConstants.FreeSpaceName, FileItemType.FreeSpace, FileItemFlags.None) - { - this.rootParent = rootParent; - LastWriteTimeUtc = DateTime.MinValue; - UpdateSize(); - } - - #endregion - - #region Helper Properties - - /// Gets the root path of . - private string VolumePath => rootParent.RootPath; - - #endregion - - #region Updating - - /// Updates the size of the free space. - internal void UpdateSize() { - if (rootParent.Type == FileItemType.Computer) { - Size = 0; - List children = rootParent.Children; - lock (children) { - int count = children.Count; - for (int i = 0; i < count; i++) { - if (children[i] is RootItem root && root.FreeSpace != null) { - root.FreeSpace.UpdateSize(); - Size += root.FreeSpace.Size; - } - } - } - } - else if (rootParent.Type == FileItemType.Volume) { - try { - DriveInfo driveInfo = new DriveInfo(VolumePath); - Size = driveInfo.TotalFreeSpace; - } - catch { - Size = 0; - } - } - } - - #endregion - - #region ToString/DebuggerDisplay - - /// Gets the string representation of this item. - public override string ToString() => ""; - - /// Gets the string used to represent the file in the debugger. - private string DebuggerDisplay => ""; - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Files/Misc/FileItemEnums.cs b/WinDirStat.Net.Base/Model/Files/Misc/FileItemEnums.cs deleted file mode 100644 index 44afbf7..0000000 --- a/WinDirStat.Net.Base/Model/Files/Misc/FileItemEnums.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System; -using System.ComponentModel; -using System.IO; - -namespace WinDirStat.Net.Model.Files { - /// The different types of file tree items. - [Serializable] - public enum FileItemType : byte { - /// This item is the computer that stores all scanned volumes. - Computer = 0, - /// This item is a volume that contains the entire file tree. - Volume = 1, - /// - /// This item is a directory that stores its files and subdirs. It can also be a root type. - /// - Directory = 2, - /// This item is a normal file and is treated as a treemap leaf. - File = 3, - /// - /// This item is a container for files when a folder is storing files and folders. - /// See 's remarks for how files and folders are separated. - /// - FileCollection = 4, - /// This item is the free space for a root. This may optionally be hidden. - FreeSpace = 5, - /// This item is the unidentified space for a root. This may optionally be hidden. - Unknown = 6, - } - - /// The modifiable states of a file tree item. - [Serializable] - [Flags] - internal enum FileItemStates : byte { - /// No states are set. - None = 0, - - /// The container is done scanning all subdirs. - Done = (1 << 0), - /// - /// The container is invalidated and needs to have its size and other members validated when needed. - /// - Invalidated = (1 << 1), - /// - /// The container is in the process of validating, this prevents more than one validation operation - /// from occurring at the same time. - /// - Validating = (1 << 2), - /// The file still exists in the system. - Exists = (1 << 3), - } - - /// The constant flags of a file tree item. - [Serializable] - [Flags] - internal enum FileItemFlags : ushort { - /// No flags are set. - None = 0, - - // Sortable FileAttributes (Bit order is important here) - /// This file has the attribute. - Encrypted = (1 << 0), - /// This file has the attribute. - Compressed = (1 << 1), - /// This file has the attribute. - Archive = (1 << 2), - /// This file has the attribute. - System = (1 << 3), - /// This file has the attribute. - Hidden = (1 << 4), - /// This file has the attribute. - ReadOnly = (1 << 5), - - // Other FileAttributes - /// This file has the attribute. - ReparsePoint = (1 << 6), - /// This file has the attribute. - Temporary = (1 << 7), - - // Type Flags - /// The directory is case-sensitive. - CaseSensitive = (1 << 11), - /// The item can contain children. - ContainerType = (1 << 12), - /// The item is a real file, directory, or volume. - FileType = (1 << 13), - /// The item is a root and a volume or directory. - FileRootType = (1 << 14), - /// - /// The item is the top level root. This can be set at the same time as . - /// - AbsoluteRootType = (1 << 15), - - /// The mask for all type flags. - [Browsable(false)] - TypeFlagsMask = 0xF800, - /// The mask for all used in sorting. - [Browsable(false)] - SortAttributesMask = 0x003F, - /// The mask for all . - [Browsable(false)] - AttributesMask = 0x00FF, - } - - /// - /// Extensions for settings individual flags in and . - /// - internal static class FileItemFlagsExtensions { - /// Enables or disables the specified flag. - /// - /// The flags to modify - /// The flag(s) to set. - /// True if the flags should be set - /// The modified flags. - public static FileItemStates SetFlag(this FileItemStates flags, FileItemStates flag, bool value) { - if (value) - return flags | flag; - else - return flags & ~flag; - } - - /// Enables or disables the specified flag. - /// - /// The flags to modify - /// The flag(s) to set. - /// True if the flags should be set - /// The modified flags. - public static FileItemFlags SetFlag(this FileItemFlags flags, FileItemFlags flag, bool value) { - if (value) - return flags | flag; - else - return flags & ~flag; - } - } -} diff --git a/WinDirStat.Net.Base/Model/Files/Misc/FileItemEvent.cs b/WinDirStat.Net.Base/Model/Files/Misc/FileItemEvent.cs deleted file mode 100644 index 128f61a..0000000 --- a/WinDirStat.Net.Base/Model/Files/Misc/FileItemEvent.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Model.Files { - /// The event action type for . - public enum FileItemAction { - - // State - /// The node state has been marked is invalidated. - Invalidated, - /// The node state has been validated to reflect its children. - Validated, - /// Properties that require a visual resort have changed during validation. - ValidatedSortOrder, - /// The node and all children have been fully scanned. - Done, - /// The file's existance state has changed. - Exists, - /// The node was refreshed, and non-standard sort properties may have changed. - /// Exists may also have been changed when this action is received. - Refreshed, - - // Children - /// Children have been added to the node. - ChildrenAdded, - /// Children have been removed from the node. - ChildrenRemoved, - /// Children have been cleared. - ChildrenCleared, - - // Accessors - /// Requests the view model watching this node to show itself. - GetViewModel, - } - - /// The event arguments for . - public class FileItemEventArgs { - /// The action to notify the view model of. - public FileItemAction Action { get; } - /// The children that were introduced or removed. - public List Children { get; } - /// The index of the introduced children. - public int Index { get; } - /// - /// The view model if is . - /// - public object ViewModel { get; set; } - - /// Constructs the that just require an action. - public FileItemEventArgs(FileItemAction action) : this(action, -1) { - } - - /// - /// Constructs the that require an action and index. - /// - public FileItemEventArgs(FileItemAction action, int index) { - Action = action; - Index = index; - } - - /// - /// Constructs the that represent changes to children. - /// - public FileItemEventArgs(FileItemAction action, List children, int index = -1) - : this(action, index) - { - Children = children; - } - - /// - /// Constructs the that represent changes to children. - /// - public FileItemEventArgs(FileItemAction action, IEnumerable children, int index = -1) - : this(action, index) - { - Children = children.ToList(); - } - - /// - /// Constructs the that represent changes to a child. - /// - public FileItemEventArgs(FileItemAction action, FileItemBase child, int index = -1) - : this(action, index) - { - Children = new List { child }; - } - } - - /// The event handler for . - /// - /// The that sent this changed event. - /// The for this changed event. - public delegate void FileItemEventHandler(FileItemBase sender, FileItemEventArgs e); -} diff --git a/WinDirStat.Net.Base/Model/Files/Misc/IScanFileInfo.cs b/WinDirStat.Net.Base/Model/Files/Misc/IScanFileInfo.cs deleted file mode 100644 index 89c6c88..0000000 --- a/WinDirStat.Net.Base/Model/Files/Misc/IScanFileInfo.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Model.Files { - /// An interface revealing information needed to construct file tree items. - public interface IScanFileInfo { - - #region FileInfo Properties - - /// Gets the name of the file. - string Name { get; } - /// Gets the full path of the file. - string FullName { get; } - /// Gets the size of the file. - long Size { get; } -#if WINDOWS - /// Gets the attributes of the file. - FileAttributes Attributes { get; } -#endif - /// Gets the UTC creation time of the file. - DateTime CreationTimeUtc { get; } - /// Gets the UTC last access time of the file. - DateTime LastAccessTimeUtc { get; } - /// Gets the UTC last write time of the file. - DateTime LastWriteTimeUtc { get; } - - #endregion - - #region Helpers Properties - - /// Gets if the file is a directory. - bool IsDirectory { get; } - /// Gets if the file is a symbolic link. - bool IsSymbolicLink { get; } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Files/RootItem.cs b/WinDirStat.Net.Base/Model/Files/RootItem.cs deleted file mode 100644 index 36b5dc9..0000000 --- a/WinDirStat.Net.Base/Model/Files/RootItem.cs +++ /dev/null @@ -1,230 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Model.Files { - /// - /// A root file tree item that is either the absolute root, a file root (volume/folder), or both. - /// If this root is not a file root, it's children must all be s. - /// - [Serializable] - public class RootItem : FolderItem, IDisposable { - - #region Fields - - /// Gets the service used for scanning the file tree. - private readonly ScanningService scanning; - - /// Gets the root path of the container. This includes the name of the item. - public string RootPath { get; private set; } - /// Gets the free space item associated with this root. - public FreeSpaceItem FreeSpace { get; private set; } - /// Gets the unknown space item associated with this root. - public UnknownItem Unknown { get; private set; } - /// The cached total size of the drive. - public long CachedTotalSize { get; private set; } - /// The cached free space of the drive. - public long CachedFreeSpace { get; private set; } - - #endregion - - #region Constructors - - /// Constructs the as a Computer. - /// - /// The service used for scanning the file tree. - public RootItem(ScanningService scanning) - : base(StringConstants.ComputerName, FileItemType.Computer, - FileItemFlags.ContainerType | FileItemFlags.AbsoluteRootType) - { - this.scanning = scanning; - scanning.SpaceChanged += UpdateSpace; - SetupRoot(); - } - - /// Constructs the with a . - /// - /// The service used for scanning the file tree. - /// The file information. - /// True if there is no containing this. - public RootItem(ScanningService scanning, DirectoryInfo info, bool isAbsoluteRoot) - : base(info, GetType(info.FullName), GetFlags(isAbsoluteRoot)) - { - this.scanning = scanning; - if (isAbsoluteRoot) - scanning.SpaceChanged += UpdateSpace; - RootPath = Path.GetFullPath(info.FullName); - if (Type == FileItemType.Volume) - RootPath = PathUtils.AddDirectorySeparator(RootPath); - SetupRoot(); - } - - private void SetupRoot() { - if (Type == FileItemType.Volume || Type == FileItemType.Computer) { - FreeSpace = new FreeSpaceItem(this); - Unknown = new UnknownItem(this); - if (scanning.ShowFreeSpace) - Add(FreeSpace); - if (scanning.ShowUnknown) - Add(Unknown); - if (Type == FileItemType.Volume) { - DriveInfo driveInfo = new DriveInfo(RootPath); - CachedTotalSize = driveInfo.TotalSize; - CachedFreeSpace = driveInfo.TotalFreeSpace; - } - } - } - - private static FileItemType GetType(string path) { - return (PathUtils.IsPathRoot(path) ? FileItemType.Volume : FileItemType.Directory); - } - - private static FileItemFlags GetFlags(bool isAbsoluteRoot) { - return (isAbsoluteRoot ? FileItemFlags.AbsoluteRootType : FileItemFlags.None) | - FileItemFlags.FileRootType | FileItemFlags.FileType | FileItemFlags.ContainerType; - } - - #endregion - - #region Validation - - /// - /// Validates the file tree and all invalidated children. - /// For use when scanning is still underway, but the UI wants to be updated. - /// - public void BasicValidate() { - ValidateImpl(false); - } - - /// Fully validates the file item tree and prepares it for use. - public void FullValidate() { - ValidateImpl(true); - FullValidateImpl(); - } - - /// Validates changes to the roots only. For use when space display has been changed. - private void RootValidate() { - ValidateImpl(true); - if (IsEmpty) - return; - - lock (children) { - if (Type == FileItemType.Computer) { - int count = children.Count; - for (int i = 0; i < count; i++) { - if (children[i] is RootItem root) - root.RootValidate(); - } - } - children.Sort(); - children.Minimize(); - } - } - - #endregion - - public long GetUsedSize() { - long usedSize = 0; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - if (child.Type != FileItemType.FreeSpace && child.Type != FileItemType.Unknown) - usedSize += child.Size; - } - return usedSize; - } - - private void UpdateSpace(object sender, EventArgs e) { - if (IsEmpty) - return; - - if (Type == FileItemType.Computer) { - int count = children.Count; - for (int i = 0; i < count; i++) { - if (children[i] is RootItem root) - root.UpdateSpace(sender, e); - } - } - - // ShowTotalSpace means only the absolute root will show space - // !ShowTotalSpace means only the file root will show space - // We do this check because absolute roots can also be file roots - bool baseShow = (IsAbsoluteRootType && scanning.ShowTotalSpace) || - (IsFileRootType && !scanning.ShowTotalSpace); - - // Create some children so we can lock things down - EnsureChildren(2); - - lock (children) { - AddOrRemove(FreeSpace, scanning.ShowFreeSpace && baseShow); - AddOrRemove(Unknown, scanning.ShowUnknown && baseShow); - - // If nothing was added or removed and children was created, - // children was never set back to empty. - EnsureEmptyChildren(); - - Invalidate(); - } - - if (IsAbsoluteRootType) - RootValidate(); - } - - #region Override Methods - - /// Refreshes the item. Returns true if it still exists. - /// - /// True if the file still exists. - /*public override bool Refresh() { - DirectoryInfo info = new DirectoryInfo(FullName); - if (info.Exists && !info.Attributes.HasFlag(FileAttributes.Directory)) { - Attributes = info.Attributes; - - long oldSize = Size; - if (!info.Attributes.HasFlag(FileAttributes.ReparsePoint)) - Size = info.Length; - else - Size = 0L; - ExtensionItem.RefreshFile(Size, oldSize); - - LastWriteTimeUtc = info.LastWriteTimeUtc; - - return true; - } - ExtensionItem.RemoveFile(Size); - return false; - - }*/ - - /// Checks if it still exists. - /// - /// True if the file exists. - public override sealed bool CheckExists() { - if (Type == FileItemType.Computer) - return true; - - if (Directory.Exists(FullName)) { - return (Exists = true); - } - RecurseClearChildren(); - return (Exists = false); - } - - #endregion - - #region IDisposable Implementation - - /// Disposes of the root node's hooked events. - public void Dispose() { - if (IsAbsoluteRootType) - scanning.SpaceChanged -= UpdateSpace; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Model/Files/UnknownItem.cs b/WinDirStat.Net.Base/Model/Files/UnknownItem.cs deleted file mode 100644 index 7c97e60..0000000 --- a/WinDirStat.Net.Base/Model/Files/UnknownItem.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Model.Files { - /// The file tree item that displays the amount of unidentified space in the drive. - [Serializable] - [DebuggerDisplay("{DebuggerDisplay,nq}")] - public sealed class UnknownItem : FileItemBase { - - #region Fields - - /// The containing this space. - private readonly RootItem rootParent; - - #endregion - - #region Constructors - - /// Constructs the . - /// - /// The containing this space. - internal UnknownItem(RootItem rootParent) - : base(StringConstants.UnknownName, FileItemType.Unknown, FileItemFlags.None) - { - this.rootParent = rootParent; - LastWriteTimeUtc = DateTime.MinValue; - UpdateSize(0); - } - - #endregion - - #region Helper Properties - - /// Gets the root path of . - private string VolumePath => rootParent.RootPath; - - #endregion - - #region Updating - - /// - /// Updates the size of the unknown space based on the amount of used space. - /// - /// The space of the root item excluding free and unknown space. - internal void UpdateSize(long usedSpace) { - if (rootParent.Type == FileItemType.Computer) { - Size = 0; - List children = rootParent.Children; - lock (children) { - int count = children.Count; - for (int i = 0; i < count; i++) { - if (children[i] is RootItem root && root.Unknown != null) { - root.Unknown.UpdateSize(root.GetUsedSize()); - Size += root.Unknown.Size; - } - } - } - } - else if (rootParent.Type == FileItemType.Volume) { - try { - DriveInfo driveInfo = new DriveInfo(VolumePath); - Size = driveInfo.TotalSize - driveInfo.TotalFreeSpace - usedSpace; - // In the rare case that our used space is larger than the actual used space - if (Size < 0) - Size = 0; - } - catch { - Size = 0; - } - } - } - - #endregion - - #region ToString/DebuggerDisplay - - /// Gets the string representation of this item. - public override string ToString() => ""; - - /// Gets the string used to represent the file in the debugger. - private string DebuggerDisplay => ""; - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ObservableCollectionObject.cs b/WinDirStat.Net.Base/ObservableCollectionObject.cs deleted file mode 100644 index 636b1ed..0000000 --- a/WinDirStat.Net.Base/ObservableCollectionObject.cs +++ /dev/null @@ -1,230 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; - -namespace WinDirStat.Net { - /// A base class for objects of which the collection must be observable. - public abstract class ObservableCollectionObject : INotifyCollectionChanged { - - #region Fields - - /// True if the collection is raising a event. - protected bool IsRaisingEvent { get; set; } - - #endregion - - #region Events - - /// Occurs after the collection's items change. - public event NotifyCollectionChangedEventHandler CollectionChanged; - - #endregion - - #region RaiseCollectionChanged (EventArgs) - - /// Invokes the event. - /// - /// The arguments for the event. - protected void InvokeCollectionChanged(NotifyCollectionChangedEventArgs e) { - CollectionChanged?.Invoke(this, e); - } - - /// Raises a new event. - /// - /// The arguments for the event. - protected virtual void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) { - //Debug.Assert(!isRaisingEvent); - ThrowOnReentrancy(); - IsRaisingEvent = true; - try { - CollectionChanged?.Invoke(this, e); - } - finally { - IsRaisingEvent = false; - } - } - - #endregion - - #region RaiseCollectionChanged (Reset) - - /// - /// Raises a new event that describes a change. - /// - /// - /// The action that caused the event (must be Reset). - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action) { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action)); - } - - #endregion - - #region RaiseCollectionChanged (Change) - - /// - /// Raises a new event that describes a one-item change. - /// - /// - /// - /// The action that caused the event; can only be Reset, Add or Remove action. - /// - /// The item affected by the change. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object changedItem) { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItem)); - } - - /// - /// Raises a new event that describes a one-item change. - /// - /// - /// The action that caused the event. - /// The item affected by the change. - /// The index where the change occurred. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object changedItem, - int index) { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItem, index)); - } - - /// - /// Raises a new event that describes a multi-item change. - /// - /// - /// The action that caused the event. - /// The items affected by the change. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList changedItems) { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItems)); - } - - /// - /// Raises a new event that describes a multi-item change. - /// - /// - /// The action that caused the event. - /// The items affected by the change. - /// The index where the change occurred. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList changedItems, - int startingIndex) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItems, startingIndex)); - } - - #endregion - - #region RaiseCollectionChanged (Replace) - - /// - /// Raises a new event that describes a one-item Replace event. - /// - /// - /// Can only be a Replace action. - /// The new item replacing the original item. - /// The original item that is replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object newItem, - object oldItem) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem)); - } - - /// - /// Raises a new event that describes a one-item Replace event. - /// - /// - /// Can only be a Replace action. - /// The new item replacing the original item. - /// The original item that is replaced. - /// The index of the item being replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object newItem, - object oldItem, int index) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index)); - } - - /// - /// Raises a new event that describes a multi-item Replace event. - /// - /// - /// Can only be a Replace action. - /// The new items replacing the original items. - /// The original items that are replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList newItems, - IList oldItems) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItems, oldItems)); - } - - /// - /// Raises a new event that describes a multi-item Replace event. - /// - /// - /// Can only be a Replace action. - /// The new items replacing the original items. - /// The original items that are replaced. - /// The starting index of the items being replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList newItems, - IList oldItems, int index) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItems, oldItems, index)); - } - - #endregion - - #region RaiseCollectionChanged (Move) - - /// - /// Raises a new event that describes a one-item Move event. - /// - /// - /// Can only be a Move action. - /// The item affected by the change. - /// The new index for the changed item. - /// The old index for the changed item. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object changedItem, - int index, int oldIndex) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItem, index, oldIndex)); - } - - /// - /// Raises a new event that describes a multi-item Move event. - /// - /// - /// Can only be a Replace action. - /// The new items replacing the original items. - /// The original items that are replaced. - /// The starting index of the items being replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList changedItems, - int index, int oldIndex) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItems, index, oldIndex)); - } - - #endregion - - #region ThrowOnReentrancy - - /// - /// Throws an exception if the user is attempting to modify the list during a event. - /// - /// - /// - /// The user is attempting to modify the list during a event. - /// - protected void ThrowOnReentrancy() { - if (IsRaisingEvent) - throw new InvalidOperationException($"Collection cannot be modified during a " + - $"{nameof(CollectionChanged)} event!"); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ObservableObjectEx.cs b/WinDirStat.Net.Base/ObservableObjectEx.cs deleted file mode 100644 index e25ddb3..0000000 --- a/WinDirStat.Net.Base/ObservableObjectEx.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; - -namespace WinDirStat.Net { - /// An observable object with extra raise property changed methods. - public class ObservableObjectEx : ObservableObject { - - /// Raises the property as changed if the condition is true. - /// - /// The condition for raising the changed event. - /// The name of the property. - /// True if the property was changed. - protected bool RaisePropertyChangedIf(bool condition, [CallerMemberName] string propertyName = null) { - RaisePropertyChanged(propertyName); - return condition; - } - } -} diff --git a/WinDirStat.Net.Base/ObservablePropertyCollectionObject.cs b/WinDirStat.Net.Base/ObservablePropertyCollectionObject.cs deleted file mode 100644 index 645f28a..0000000 --- a/WinDirStat.Net.Base/ObservablePropertyCollectionObject.cs +++ /dev/null @@ -1,223 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; - -namespace WinDirStat.Net { - /// A base class for objects of which the collection must be observable. - public abstract class ObservablePropertyCollectionObject : ObservableObject, INotifyCollectionChanged { - - #region Fields - - /// True if the collection is raising a event. - protected bool IsRaisingEvent { get; set; } - - #endregion - - #region Events - - /// Occurs after the collection's items change. - public event NotifyCollectionChangedEventHandler CollectionChanged; - - #endregion - - #region RaiseCollectionChanged (EventArgs) - - /// Raises a new event. - /// - /// The arguments for the event. - protected void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) { - //Debug.Assert(!isRaisingEvent); - ThrowOnReentrancy(); - IsRaisingEvent = true; - try { - CollectionChanged?.Invoke(this, e); - } - finally { - IsRaisingEvent = false; - } - } - - #endregion - - #region RaiseCollectionChanged (Reset) - - /// - /// Raises a new event that describes a change. - /// - /// - /// The action that caused the event (must be Reset). - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action) { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action)); - } - - #endregion - - #region RaiseCollectionChanged (Change) - - /// - /// Raises a new event that describes a one-item change. - /// - /// - /// - /// The action that caused the event; can only be Reset, Add or Remove action. - /// - /// The item affected by the change. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object changedItem) { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItem)); - } - - /// - /// Raises a new event that describes a one-item change. - /// - /// - /// The action that caused the event. - /// The item affected by the change. - /// The index where the change occurred. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object changedItem, - int index) { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItem, index)); - } - - /// - /// Raises a new event that describes a multi-item change. - /// - /// - /// The action that caused the event. - /// The items affected by the change. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList changedItems) { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItems)); - } - - /// - /// Raises a new event that describes a multi-item change. - /// - /// - /// The action that caused the event. - /// The items affected by the change. - /// The index where the change occurred. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList changedItems, - int startingIndex) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItems, startingIndex)); - } - - #endregion - - #region RaiseCollectionChanged (Replace) - - /// - /// Raises a new event that describes a one-item Replace event. - /// - /// - /// Can only be a Replace action. - /// The new item replacing the original item. - /// The original item that is replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object newItem, - object oldItem) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem)); - } - - /// - /// Raises a new event that describes a one-item Replace event. - /// - /// - /// Can only be a Replace action. - /// The new item replacing the original item. - /// The original item that is replaced. - /// The index of the item being replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object newItem, - object oldItem, int index) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index)); - } - - /// - /// Raises a new event that describes a multi-item Replace event. - /// - /// - /// Can only be a Replace action. - /// The new items replacing the original items. - /// The original items that are replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList newItems, - IList oldItems) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItems, oldItems)); - } - - /// - /// Raises a new event that describes a multi-item Replace event. - /// - /// - /// Can only be a Replace action. - /// The new items replacing the original items. - /// The original items that are replaced. - /// The starting index of the items being replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList newItems, - IList oldItems, int index) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItems, oldItems, index)); - } - - #endregion - - #region RaiseCollectionChanged (Move) - - /// - /// Raises a new event that describes a one-item Move event. - /// - /// - /// Can only be a Move action. - /// The item affected by the change. - /// The new index for the changed item. - /// The old index for the changed item. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, object changedItem, - int index, int oldIndex) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItem, index, oldIndex)); - } - - /// - /// Raises a new event that describes a multi-item Move event. - /// - /// - /// Can only be a Replace action. - /// The new items replacing the original items. - /// The original items that are replaced. - /// The starting index of the items being replaced. - protected void RaiseCollectionChanged(NotifyCollectionChangedAction action, IList changedItems, - int index, int oldIndex) - { - RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItems, index, oldIndex)); - } - - #endregion - - #region ThrowOnReentrancy - - /// - /// Throws an exception if the user is attempting to modify the list during a event. - /// - /// - /// - /// The user is attempting to modify the list during a event. - /// - protected void ThrowOnReentrancy() { - if (IsRaisingEvent) - throw new InvalidOperationException($"Collection cannot be modified during a " + - $"{nameof(CollectionChanged)} event!"); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ObservableVolatileObject.cs b/WinDirStat.Net.Base/ObservableVolatileObject.cs deleted file mode 100644 index a858af5..0000000 --- a/WinDirStat.Net.Base/ObservableVolatileObject.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net { - /// An observable object with volatile get and set. - public class ObservableVolatileObject : ObservableObjectEx { - - /// The lock for volatile properties. - protected readonly object volatileLock = new object(); - - /// Gets the property and ensures its under lock while accessing it. - /// - /// The type of the property. - /// The field to access. - /// The locked value of the field. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected T VolatileGet(ref T field) { - lock (volatileLock) - return field; - } - - /// Sets the property and ensures the property is not changed during the process. - /// - /// The type of the property. - /// The field of the property. - /// The new value of the property. - /// The name of the property. - /// True if the property was changed. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool VolatileSet(ref T field, T newValue, [CallerMemberName] string propertyName = null) { - lock (volatileLock) { - if (EqualityComparer.Default.Equals(field, newValue)) - return false; - field = newValue; - } - RaisePropertyChanged(propertyName); - return true; - } - - } -} diff --git a/WinDirStat.Net.Base/Rendering/BetterTreemapOptions.cs b/WinDirStat.Net.Base/Rendering/BetterTreemapOptions.cs deleted file mode 100644 index fd370c6..0000000 --- a/WinDirStat.Net.Base/Rendering/BetterTreemapOptions.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using WinDirStat.Net.Structures; -using WinDirStat.Net.Utils; - -#if DOUBLE -using Number = System.Double; -using Point2N = WinDirStat.Net.Structures.Point2D; -#else -using Number = System.Single; -using Point2N = WinDirStat.Net.Structures.Point2F; -#endif - -namespace WinDirStat.Net.Rendering { - /// A structure containing treemap rendering options. - [Serializable] - public struct BetterTreemapOptions { - - /// Squarification method - private TreemapStyle style; - /// 0..1.0 (default = 0.84) - private Number brightness; - /// 0..oo (default = 0.40) Factor "H" - private Number height; - /// 0..1.0 (default = 0.90) Factor "F" - private Number scaleFactor; - /// 0..1.0 (default = 0.15) Factor "Ia" - private Number ambientLight; - /// (-4.0,-4.0)..(+4.0,+4.0) (default = (-1.0,-1.0), negative = top-left - private Point2N lightSource; - - /// Squarification method - public TreemapStyle Style { - get => style; - set { - if (!Enum.IsDefined(typeof(TreemapStyle), value)) - throw new ArgumentException(nameof(Style)); - style = value; - } - } - /// Whether or not to draw grid lines - public bool Grid { get; set; } - /// Color of grid lines - public Rgb24Color GridColor { get; set; } - - /// 0..1.0 (default = 0.84) - public Number Brightness { - get => brightness; - set => brightness = MathUtils.Clamp(value, 0, 1); - } - /// 0..oo (default = 0.40) Factor "H" - public Number Height { - get => height; - set => height = Math.Max(value, 0); - } - /// 0..1.0 (default = 0.90) Factor "F" - public Number ScaleFactor { - get => scaleFactor; - set => scaleFactor = MathUtils.Clamp(value, 0, 1); - } - /// 0..1.0 (default = 0.15) Factor "Ia" - public Number AmbientLight { - get => ambientLight; - set => ambientLight = MathUtils.Clamp(value, 0, 1); - } - - /// (-4.0,-4.0)..(+4.0,+4.0) (default = (-1.0,-1.0), negative = top-left - public Point2N LightSource { - get => lightSource; - set { - LightSourceX = value.X; - LightSourceY = value.Y; - } - } - /// -4.0..+4.0 (default = -1.0), negative = left - public Number LightSourceX { - get => lightSource.X; - set => lightSource.X = MathUtils.Clamp(value, -4, 4); - } - /// -4.0..+4.0 (default = -1.0), negative = top - public Number LightSourceY { - get => lightSource.Y; - set => lightSource.Y = MathUtils.Clamp(value, -4, 4); - } - } -} diff --git a/WinDirStat.Net.Base/Rendering/ColorSpace.cs b/WinDirStat.Net.Base/Rendering/ColorSpace.cs deleted file mode 100644 index fc6af43..0000000 --- a/WinDirStat.Net.Base/Rendering/ColorSpace.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Structures; - -#if DOUBLE -using Number = System.Double; -#else -using Number = System.Single; -#endif - -namespace WinDirStat.Net.Rendering { - public static class ColorSpace { - - public const Number PaletteBrightness = (Number) 0.6; - - public static float GetBrightness(Rgb24Color color) { - return (color.R + color.G + color.B) / (Number) 255 / 3; - } - - public static Number GetBrightness(Rgba32Color color) { - return (color.R + color.G + color.B) / (Number) 255 / 3; - } - - public static Rgb24Color SetBrightness(Rgb24Color color, float brightness) { - Debug.Assert(brightness >= 0); - Debug.Assert(brightness <= 1); - - Number redf = color.R / 255f; - Number greenf = color.G / 255f; - Number bluef = color.B / 255f; - - Number f = 3 * brightness / (redf + greenf + bluef); - - int red = (int) (redf * f * 255); - int green = (int) (greenf * f * 255); - int blue = (int) (bluef * f * 255); - - NormalizeColor(ref red, ref green, ref blue); - - return new Rgb24Color(red, green, blue); - } - - public static Rgba32Color SetBrightness(Rgba32Color color, float brightness) { - Debug.Assert(brightness >= 0); - Debug.Assert(brightness <= 1); - - Number redf = color.R / 255f; - Number greenf = color.G / 255f; - Number bluef = color.B / 255f; - - Number f = 3 * brightness / (redf + greenf + bluef); - - int red = (int) (redf * f * 255); - int green = (int) (greenf * f * 255); - int blue = (int) (bluef * f * 255); - - NormalizeColor(ref red, ref green, ref blue); - - return new Rgba32Color(red, green, blue, color.A); - } - - public static Rgba32Color[] EqualizeColors(IEnumerable colors) { - List result = new List(); - foreach (Rgba32Color color in colors) - result.Add(SetBrightness(color, PaletteBrightness)); - return result.ToArray(); - } - - public static Rgb24Color[] EqualizeColors(IEnumerable colors) { - List result = new List(); - foreach (Rgb24Color color in colors) - result.Add(SetBrightness(color, PaletteBrightness)); - return result.ToArray(); - } - - public static void NormalizeColor(ref int red, ref int green, ref int blue) { - Debug.Assert(red + green + blue <= 3 * 255); - - if (red > 255) { - DistributeFirst(ref red, ref green, ref blue); - } - else if (green > 255) { - DistributeFirst(ref green, ref red, ref blue); - } - else if (blue > 255) { - DistributeFirst(ref blue, ref red, ref green); - } - } - - private static void DistributeFirst(ref int first, ref int second, ref int third) { - int h = (first - 255) / 2; - first = 255; - second += h; - third += h; - - if (second > 255) { - h = second - 255; - second = 255; - third += h; - Debug.Assert(third <= 255); - } - else if (third > 255) { - h = third - 255; - third = 255; - second += h; - Debug.Assert(second <= 255); - } - } - } -} diff --git a/WinDirStat.Net.Base/Rendering/ITreemapItem.cs b/WinDirStat.Net.Base/Rendering/ITreemapItem.cs deleted file mode 100644 index cf51e0a..0000000 --- a/WinDirStat.Net.Base/Rendering/ITreemapItem.cs +++ /dev/null @@ -1,26 +0,0 @@ -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.Rendering { - /// An interface for items to use in treemap rendering. - public interface ITreemapItem { - /// Gets if this treemap item is a leaf that should be drawn. - bool IsLeaf { get; } - - /// Gets the color of this treemap item leaf.Gets or sets the rectangular bounds of the treemap item in the treemap. - Rectangle2I Rectangle { get; set; } - - /// - /// Gets the file size of the treemap item. - /// The size of all children combined must match this value. - /// - long Size { get; } - - /// Gets the number of children in this treemap item. - int ChildCount { get; } - /// Gets the child at the specified index in the treemap item. - ITreemapItem this[int index] { get; } - } -} diff --git a/WinDirStat.Net.Base/Rendering/PreviewTreemapItem.cs b/WinDirStat.Net.Base/Rendering/PreviewTreemapItem.cs deleted file mode 100644 index 2717519..0000000 --- a/WinDirStat.Net.Base/Rendering/PreviewTreemapItem.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using WinDirStat.Net.Services; -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.Rendering { - /// An treemap item for previewing purposes only. - public class PreviewTreemapItem : ITreemapItem { - - #region Static Fields - - /// Gets the default preview treemap. - public static PreviewTreemapItem DefaultTreemap { get; } = Build(SettingsService.DefaultFilePalette); - - #endregion - - #region Fields - - /// The list of children in the treemap item. - private readonly List children; - /// Gets the color of this treemap item leaf.Gets or sets the rectangular bounds of the treemap item in the treemap. - private Rectangle2S rectangle; - /// - /// Gets the file size of the treemap item. - /// The size of all children combined must match this value. - /// - public long Size { get; private set; } - - #endregion - - #region Constructors - - /// Constructs an empty . - public PreviewTreemapItem() { - children = new List(); - Size = 0; - } - - /// Constructs a leaf. - /// - /// The size of the treemap item. - /// The color of the treemap item. - public PreviewTreemapItem(long size, Rgb24Color color) { - Size = size; - Color = color; - } - - /// Constructs a with the specified children. - /// - /// The children to populate the treemap item with. - public PreviewTreemapItem(IEnumerable children) { - this.children = children.ToList(); - Size = children.Sum(c => c.Size); - } - - #endregion - - #region Sort - - /// Validates the treemap item. - public void Validate() { - children.Sort((a, b) => b.Size.CompareTo(a.Size)); - int count = ChildCount; - for (int i = 0; i < count; i++) { - PreviewTreemapItem child = children[i]; - if (child.ChildCount != 0) - child.Validate(); - } - } - - #endregion - - #region Add - - /// Adds a leaf to the children. - /// - /// The size of the child treemap item. - /// The color of the child treemap item. - public void Add(long size, Rgb24Color color) { - children.Add(new PreviewTreemapItem(size, color)); - } - - /// Adds a to the children. - /// - /// The child treemap item to add. - public void Add(PreviewTreemapItem child) { - children.Add(child); - } - - /// Adds a collection of s to the children. - /// - /// The children to add to the treemap item. - public void Add(IEnumerable children) { - this.children.AddRange(children); - } - - #endregion - - #region Properties - - /// Gets if this treemap item is a leaf that should be drawn. - public bool IsLeaf => children == null; - - /// Gets or sets the rectangular bounds of the treemap item in the treemap. - public Rectangle2I Rectangle { - get => rectangle; - set => rectangle = (Rectangle2S) value; - } - - /// Gets the number of children in this treemap item. - public int ChildCount => (children != null ? children.Count : 0); - - /// Gets the child at the specified index in the treemap item. - public PreviewTreemapItem this[int index] => children[index]; - - /// Gets the child at the specified index in the treemap item. - ITreemapItem ITreemapItem.this[int index] => children[index]; - - #endregion - - #region Build Preview - - /// Gets the next color in the palette. - /// - /// The index to increment. - /// The palette to get the color from. - /// A color from the palette. - private static Rgb24Color NextColor(ref int index, IReadOnlyList palette) { - return palette[(index + 1 < palette.Count ? index++ : index)]; - } - - /// Builds a preview treemap for display purposes. - /// - /// The palette to use. - /// The root item of the preview treemap. - public static PreviewTreemapItem Build(IReadOnlyList palette) { - int col = 0; - Rgb24Color color; - - PreviewTreemapItem c4 = new PreviewTreemapItem(); - color = NextColor(ref col, palette); - for (int i = 0; i < 30; i++) - c4.Add(1 + 100 * i, color); - - PreviewTreemapItem c0 = new PreviewTreemapItem(); - for (int i = 0; i < 8; i++) - c0.Add(500 + 600 * i, NextColor(ref col, palette)); - - PreviewTreemapItem c1 = new PreviewTreemapItem(); - color = NextColor(ref col, palette); - for (int i = 0; i < 10; i++) - c1.Add(1 + 200 * i, color); - c0.Add(c1); - - PreviewTreemapItem c2 = new PreviewTreemapItem(); - color = NextColor(ref col, palette); - for (int i = 0; i < 160; i++) - c2.Add(1 + i, color); - - PreviewTreemapItem c3 = new PreviewTreemapItem(); - c3.Add(10000, NextColor(ref col, palette)); - c3.Add(c4); - c3.Add(c2); - c3.Add(6000, NextColor(ref col, palette)); - c3.Add(1500, NextColor(ref col, palette)); - - PreviewTreemapItem root = new PreviewTreemapItem(); - root.Add(c0); - root.Add(c3); - - root.Validate(); - return root; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Rendering/TreemapOptions.cs b/WinDirStat.Net.Base/Rendering/TreemapOptions.cs deleted file mode 100644 index da6694b..0000000 --- a/WinDirStat.Net.Base/Rendering/TreemapOptions.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using WinDirStat.Net.Structures; -using WinDirStat.Net.Utils; - -#if DOUBLE -using Number = System.Double; -using Point2N = WinDirStat.Net.Structures.Point2D; -#else -using Number = System.Single; -using Point2N = WinDirStat.Net.Structures.Point2F; -#endif - -namespace WinDirStat.Net.Rendering { - /// A structure containing treemap rendering options. - [Serializable] - public struct TreemapOptions { - - public static readonly TreemapOptions Default = new TreemapOptions { - Style = TreemapStyle.KDirStatStyle, - Grid = false, - GridColor = Rgb24Color.Black, - Brightness = (Number) 0.88, - Height = (Number) 0.38, - ScaleFactor = (Number) 0.91, - AmbientLight = (Number) 0.13, - LightSourceX = -1, - LightSourceY = -1, - }; - - /// Squarification method - public TreemapStyle Style; - /// Whether or not to draw grid lines - public bool Grid; - /// Color of grid lines - public Rgb24Color GridColor; - /// 0..1.0 (default = 0.84) - public Number Brightness; - /// 0..oo (default = 0.40) Factor "H" - public Number Height; - /// 0..1.0 (default = 0.90) Factor "F" - public Number ScaleFactor; - /// 0..1.0 (default = 0.15) Factor "Ia" - public Number AmbientLight; - /// -4.0..+4.0 (default = -1.0), negative = left - public Number LightSourceX; - /// -4.0..+4.0 (default = -1.0), negative = top - public Number LightSourceY; - - public int BrightnessPercent { - get => MathUtils.Round(Brightness * 100); - set => Brightness = value / (Number) 100; - } - public int HeightPercent { - get => MathUtils.Round(Height * 100); - set => Height = value / (Number) 100; - } - public int ScaleFactorPercent { - get => MathUtils.Round(ScaleFactor * 100); - set => ScaleFactor = value / (Number) 100; - } - public int AmbientLightPercent { - get => MathUtils.Round(AmbientLight * 100); - set => AmbientLight = value / (Number) 100; - } - public int LightSourceXPercent { - get => MathUtils.Round(LightSourceX * 100); - set => LightSourceX = value / (Number) 100; - } - public int LightSourceYPercent { - get => MathUtils.Round(LightSourceY * 100); - set => LightSourceY = value / (Number) 100; - } - public Point2I LightSourcePoint { - get => new Point2I(LightSourceXPercent, LightSourceYPercent); - set { - LightSourceXPercent = value.X; - LightSourceYPercent = value.Y; - } - } - } -} diff --git a/WinDirStat.Net.Base/Rendering/TreemapRenderer.DrawChildren.cs b/WinDirStat.Net.Base/Rendering/TreemapRenderer.DrawChildren.cs deleted file mode 100644 index 1a76ca3..0000000 --- a/WinDirStat.Net.Base/Rendering/TreemapRenderer.DrawChildren.cs +++ /dev/null @@ -1,192 +0,0 @@ -using System; -using System.Diagnostics; -using WinDirStat.Net.Structures; - -#if DOUBLE -using Number = System.Double; -using Point2N = WinDirStat.Net.Structures.Point2D; -#else -using Number = System.Single; -using Point2N = WinDirStat.Net.Structures.Point2F; -#endif - -namespace WinDirStat.Net.Rendering { - unsafe partial class TreemapRenderer { - - private void RecurseDrawGraph(Rgba32Color* bitmap, ITreemapItem item, Rectangle2I rc, - bool isroot, Number[] pSurface, Number h, uint flags) - { - Debug.Assert(rc.Width >= 0); - Debug.Assert(rc.Height >= 0); - Debug.Assert(item.Size > 0); - - item.Rectangle = rc; - - int gridWidth = options.Grid ? 1 : 0; - - if (rc.Width <= gridWidth || rc.Height <= gridWidth) - return; - - Number[] surface = new Number[] { 0, 0, 0, 0 }; - if (IsCushionShading) { - Array.Copy(pSurface, surface, pSurface.Length); - - if (!isroot) - AddRidge(rc, surface, h); - } - - if (item.IsLeaf) { - RenderLeaf(bitmap, item, surface); - } - else { - Debug.Assert(item.ChildCount > 0); - Debug.Assert(item.Size > 0); - - DrawChildren(bitmap, item, surface, h, flags); - } - } - - private void DrawChildren(Rgba32Color* bitmap, ITreemapItem parent, Number[] surface, Number h, uint flags) { - switch (options.Style) { - case TreemapStyle.KDirStatStyle: - KDirStat_DrawChildren(bitmap, parent, surface, h, flags); - break; - case TreemapStyle.SequoiaViewStyle: - throw new NotImplementedException("SequoiaViewStyle"); - //SequoiaView_DrawwChildren(bitmap, parent, surface, h, flags); - //break; - case TreemapStyle.SimpleStyle: - throw new NotImplementedException("SimpleStyle"); - //Simple_DrawwChildren(bitmap, parent, surface, h, flags); - //break; - } - } - - - private bool IsCushionShading { - get => options.AmbientLight < 1 && options.Height > 0 && options.ScaleFactor > 0; - } - - private void RenderLeaf(Rgba32Color* bitmap, ITreemapItem item, Number[] surface) { - Rectangle2I rc = item.Rectangle; - - if (options.Grid) { - rc.Y++; - rc.X++; - rc.Width--; - rc.Height--; - if (rc.Width <= 0 || rc.Height <= 0) - return; - } - - RenderRectangle(bitmap, rc, surface, item.Color); - } - - private void RenderRectangle(Rgba32Color* bitmap, Rectangle2I rc, Number[] surface, Rgba32Color color) { - Number brightness = options.Brightness; - - //color = ColorSpace.SetBrightness(color, PaletteBrightness); - //brightness *= (Number) 0.66; - - if (IsCushionShading) { - DrawCushion(bitmap, rc, surface, color, brightness); - } - else { - DrawSolidRect(bitmap, rc, color, brightness); - } - } - - private void DrawSolidRect(Rgba32Color* bitmap, Rectangle2I rc, Rgba32Color color, Number brightness) { - Number factor = brightness / ColorSpace.PaletteBrightness; - - int red = (int) (color.R * factor); - int green = (int) (color.G * factor); - int blue = (int) (color.B * factor); - color = new Rgba32Color(red, green, blue); - - ColorSpace.NormalizeColor(ref red, ref green, ref blue); - - for (int iy = rc.Top; iy < rc.Bottom; iy++) { - for (int ix = rc.Left; ix < rc.Right; ix++) { - bitmap[ix + iy * renderArea.Width] = color; - } - } - } - private void DrawCushion(Rgba32Color* bitmap, Rectangle2I rc, Number[] surface, Rgba32Color color, Number brightness) { - Number Ia = options.AmbientLight; - - Number Is = 1 - Ia; - - Number r = color.R; - Number g = color.G; - Number b = color.B; - - for (int iy = rc.Top; iy < rc.Bottom; iy++) { - for (int ix = rc.Left; ix < rc.Right; ix++) { - Number nx = (-(2 * surface[0] * (ix + (Number) 0.5) + surface[2])); - Number ny = (-(2 * surface[1] * (iy + (Number) 0.5) + surface[3])); - Number cosa = Math.Min(1, (Number) ((nx*lx + ny*ly + lz) / Math.Sqrt(nx*nx + ny*ny + 1))); - - Number pixel = Math.Max(0, Is * cosa); - - pixel += Ia; - Debug.Assert(pixel <= 1); - - // Now, pixel is the brightness of the pixel, 0...1.0. - - // Apply contrast. - // Not implemented. - // Costs performance and nearly the same effect can be - // made width the m_options->ambientLight parameter. - // pixel= pow(pixel, m_options->contrast); - - // Apply "brightness" - pixel *= brightness / ColorSpace.PaletteBrightness; - - int red = (int) (r * pixel); - int green = (int) (g * pixel); - int blue = (int) (b * pixel); - - ColorSpace.NormalizeColor(ref red, ref green, ref blue); - - bitmap[ix + iy * renderArea.Width] = new Rgba32Color(red, green, blue); - } - } - } - - private void AddRidge(Rectangle2I rc, Number[] surface, Number h) { - /* - Unoptimized: - - if(rc.Width() > 0) - { - surface[2] += 4 * h * (rc.right + rc.left) / (rc.right - rc.left); - surface[0] -= 4 * h / (rc.right - rc.left); - } - - if(rc.Height() > 0) - { - surface[3] += 4 * h * (rc.bottom + rc.top) / (rc.bottom - rc.top); - surface[1] -= 4 * h / (rc.bottom - rc.top); - } - */ - - // Optimized (gained 15 ms of 1030): - - int width = rc.Width; - int height = rc.Height; - - Debug.Assert(width > 0 && height > 0); - - Number h4 = 4 * h; - - Number wf = h4 / width; - surface[2] += wf * (rc.Right + rc.Left); - surface[0] -= wf; - - Number hf = h4 / height; - surface[3] += hf * (rc.Bottom + rc.Top); - surface[1] -= hf; - } - } -} diff --git a/WinDirStat.Net.Base/Rendering/TreemapRenderer.Highlighting.cs b/WinDirStat.Net.Base/Rendering/TreemapRenderer.Highlighting.cs deleted file mode 100644 index 4fd555a..0000000 --- a/WinDirStat.Net.Base/Rendering/TreemapRenderer.Highlighting.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Collections.Generic; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Structures; - -#if DOUBLE -using Number = System.Double; -using Point2N = WinDirStat.Net.Structures.Point2D; -#else -using Number = System.Single; -using Point2N = WinDirStat.Net.Structures.Point2F; -#endif - -namespace WinDirStat.Net.Rendering { - unsafe partial class TreemapRenderer { - - public void HighlightItems(IWriteableBitmap bitmap, Rectangle2I rc, Rgba32Color color, IEnumerable items) { - if (rc.Width <= 0 || rc.Height <= 0) - return; - - renderArea = rc; - - InitPixels(rc, Rgba32Color.Transparent); - - fixed (Rgba32Color* pBitmapBits = pixels) { - - foreach (FileItemBase item in items) - HighlightRectangle(pBitmapBits, item.Rectangle, color); - - bitmap.SetPixels(pBitmapBits); - } - } - - public void HighlightExtensions(IWriteableBitmap bitmap, Rectangle2I rc, FileItemBase root, Rgba32Color color, string extension) { - if (rc.Width <= 0 || rc.Height <= 0) - return; - - renderArea = rc; - - InitPixels(rc, Rgba32Color.Transparent); - - fixed (Rgba32Color* pBitmapBits = pixels) { - - RecurseHighlightExtensions(pBitmapBits, root, color, extension); - - bitmap.SetPixels(pBitmapBits); - } - } - - private void RecurseHighlightExtensions(Rgba32Color* bitmap, FileItemBase parent, Rgba32Color color, string extension) { - List children = parent.Children; - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = children[i]; - Rectangle2S rc = child.Rectangle; - if (rc.Width > 0 && rc.Height > 0) { - if (child.IsLeaf) { - if (child.Extension == extension) - HighlightRectangle(bitmap, rc, color); - } - else { - RecurseHighlightExtensions(bitmap, child, color, extension); - } - } - } - } - - private void HighlightRectangle(Rgba32Color* bitmap, Rectangle2I rc, Rgba32Color color) { - if (rc.Width >= 7 && rc.Height >= 7) { - FillRectangle(bitmap, Rectangle2I.FromLTRB(rc.Left, rc.Top, rc.Right, rc.Top + 3), color); - FillRectangle(bitmap, Rectangle2I.FromLTRB(rc.Left, rc.Bottom - 3, rc.Right, rc.Bottom), color); - FillRectangle(bitmap, Rectangle2I.FromLTRB(rc.Left, rc.Top + 3, rc.Left + 3, rc.Bottom - 3), color); - FillRectangle(bitmap, Rectangle2I.FromLTRB(rc.Right - 3, rc.Top + 3, rc.Right, rc.Bottom - 3), color); - } - else if (rc.Width == 1 && rc.Height == 1) { - bitmap[rc.Left + rc.Top * renderArea.Width] = color; - } - else if (rc.Width > 0 && rc.Height > 0) { - FillRectangle(bitmap, rc, color); - } - } - - private void FillRectangle(Rgba32Color* bitmap, Rectangle2I rc, Rgba32Color color) { - int bottom = rc.Bottom; - int right = rc.Right; - if (rc.Width >= rc.Height) { - for (int iy = rc.Top; iy < bottom; iy++) { - for (int ix = rc.Left; ix < right; ix++) { - bitmap[ix + iy * renderArea.Width] = color; - } - } - } - else { - for (int ix = rc.Left; ix < right; ix++) { - for (int iy = rc.Top; iy < bottom; iy++) { - bitmap[ix + iy * renderArea.Width] = color; - } - } - } - } - } -} diff --git a/WinDirStat.Net.Base/Rendering/TreemapRenderer.KDirStat.cs b/WinDirStat.Net.Base/Rendering/TreemapRenderer.KDirStat.cs deleted file mode 100644 index 7ff3298..0000000 --- a/WinDirStat.Net.Base/Rendering/TreemapRenderer.KDirStat.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Structures; - -#if DOUBLE -using Number = System.Double; -using Point2N = WinDirStat.Net.Structures.Point2D; -#else -using Number = System.Single; -using Point2N = WinDirStat.Net.Structures.Point2F; -#endif - -namespace WinDirStat.Net.Rendering { - unsafe partial class TreemapRenderer { - - private void KDirStat_DrawChildren(Rgba32Color* bitmap, ITreemapItem parent, Number[] surface, Number h, uint flags) { - Debug.Assert(parent.ChildCount > 0); - - Rectangle2I rc = parent.Rectangle; - List rows = new List(); - List childrenPerRow = new List(); - - Number[] childWidth = new Number[parent.ChildCount]; - - bool horizontalRows = KDirStat_ArrangeChildren(parent, childWidth, rows, childrenPerRow); - - int width = horizontalRows ? rc.Width : rc.Height; - int height = horizontalRows ? rc.Height : rc.Width; - Debug.Assert(width >= 0); - Debug.Assert(height >= 0); - - int c = 0; - Number top = horizontalRows ? rc.Top : rc.Left; - for (int row = 0; row < rows.Count; row++) { - Number fBottom = top + rows[row] * height; - int bottom = (int) fBottom; - if (row == rows.Count - 1) { - bottom = horizontalRows ? rc.Bottom : rc.Right; - } - Number left = horizontalRows ? rc.Left : rc.Top; - for (int i = 0; i < childrenPerRow[row]; i++, c++) { - ITreemapItem child = parent[c]; - Debug.Assert(childWidth[c] >= 0); - Number fRight = left + childWidth[c] * width; - int right = (int) fRight; - - bool lastChild = (i == childrenPerRow[row] - 1 || childWidth[c + 1] == 0); - - if (lastChild) - right = horizontalRows ? rc.Right : rc.Bottom; - - Rectangle2I rcChild; - if (horizontalRows) { - rcChild = Rectangle2I.FromLTRB((int) left, (int) top, right, bottom); - } - else { - rcChild = Rectangle2I.FromLTRB((int) top, (int) left, bottom, right); - } - -#if DEBUG - if (rcChild.Width > 0 && rcChild.Height > 0) { - //Rectangle2I test; - //test.IntersectRect(parent->TmiGetRectangle(), rcChild); - //Debug.Assert(test == rcChild); - } -#endif - RecurseDrawGraph(bitmap, child, rcChild, false, surface, h * options.ScaleFactor, 0); - - if (lastChild) { - i++; c++; - - if (i < childrenPerRow[row]) { - parent[c].Rectangle = Rectangle2I.FromLTRB(-1, -1, -1, -1); - } - - c += childrenPerRow[row] - i; - break; - } - - left = fRight; - } - top = fBottom; - } - } - - private bool KDirStat_ArrangeChildren(ITreemapItem parent, Number[] childWidth, List rows, List childrenPerRow) { - Debug.Assert(!parent.IsLeaf); - Debug.Assert(parent.ChildCount > 0); - - if (parent.Size == 0) { - rows.Add(1); - childrenPerRow.Add(parent.ChildCount); - for (int i = 0; i < parent.ChildCount; i++) { - childWidth[i] = 1 / parent.ChildCount; - } - return true; - } - - bool horizontalRows = parent.Rectangle.Width >= parent.Rectangle.Height; - - Number width = 1; - if (horizontalRows) { - if (parent.Rectangle.Height > 0) - width = (Number) parent.Rectangle.Width / parent.Rectangle.Height; - } - else { - if (parent.Rectangle.Width > 0) - width = (Number) parent.Rectangle.Height / parent.Rectangle.Width; - } - - int nextChild = 0; - while (nextChild < parent.ChildCount) { - rows.Add(KDirStat_CalculateNextRow(parent, nextChild, width, out int childrenUsed, childWidth)); - childrenPerRow.Add(childrenUsed); - nextChild += childrenUsed; - } - - return horizontalRows; - } - - private Number KDirStat_CalculateNextRow(ITreemapItem parent, int nextChild, Number width, out int childrenUsed, Number[] childWidth) { - int i = 0; - const Number minProportion = (Number) 0.4; - Debug.Assert(minProportion < 1); - - Debug.Assert(nextChild < parent.ChildCount); - Debug.Assert(width >= 1); - - Number mySize = parent.Size; - Debug.Assert(mySize > 0); - long sizeUsed = 0; - Number rowHeight = 0; - - for (i = nextChild; i < parent.ChildCount; i++) { - long childSize = parent[i].Size; - if (childSize == 0) { - Debug.Assert(i > nextChild); - break; - } - - sizeUsed += childSize; - Number virtualRowHeight = sizeUsed / mySize; - Debug.Assert(virtualRowHeight > 0); - Debug.Assert(virtualRowHeight <= 1); - - // Rectangle2I(mySize) = width * 1.0 - // Rectangle2I(childSize) = childWidth * virtualRowHeight - // Rectangle2I(childSize) = childSize / mySize * width - - Number childWidth_ = childSize / mySize * width / virtualRowHeight; - - if (childWidth_ / virtualRowHeight < minProportion) { - Debug.Assert(i > nextChild); // because width >= 1 and _minProportion < 1. - // For the first child we have: - // childWidth / rowHeight - // = childSize / mySize * width / rowHeight / rowHeight - // = childSize * width / sizeUsed / sizeUsed * mySize - // > childSize * mySize / sizeUsed / sizeUsed - // > childSize * childSize / childSize / childSize - // = 1 > _minProportion. - break; - } - rowHeight = virtualRowHeight; - } - Debug.Assert(i > nextChild); - - while (i < parent.ChildCount && parent[i].Size == 0) { - i++; - } - - childrenUsed = i - nextChild; - - for (i = 0; i < childrenUsed; i++) { - // Rectangle2I(1 * 1) = mySize - Number rowSize = mySize * rowHeight; - Number childSize = parent[nextChild + i].Size; - Number cw = childSize / rowSize; - Debug.Assert(cw >= 0); - childWidth[nextChild + i] = cw; - } - - return rowHeight; - } - - } -} diff --git a/WinDirStat.Net.Base/Rendering/TreemapRenderer.Sequoia.cs b/WinDirStat.Net.Base/Rendering/TreemapRenderer.Sequoia.cs deleted file mode 100644 index c38ab80..0000000 --- a/WinDirStat.Net.Base/Rendering/TreemapRenderer.Sequoia.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Structures; - -#if DOUBLE -using Number = System.Double; -using Point2N = WinDirStat.Net.Structures.Point2D; -#else -using Number = System.Single; -using Point2N = WinDirStat.Net.Structures.Point2F; -#endif - -namespace WinDirStat.Net.Rendering { - unsafe partial class TreemapRenderer { - - } -} diff --git a/WinDirStat.Net.Base/Rendering/TreemapRenderer.cs b/WinDirStat.Net.Base/Rendering/TreemapRenderer.cs deleted file mode 100644 index b58bd65..0000000 --- a/WinDirStat.Net.Base/Rendering/TreemapRenderer.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System; -using System.Diagnostics; -using WinDirStat.Net.Utils; -using WinDirStat.Net.Services; -using WinDirStat.Net.Structures; -using WinDirStat.Net.Services.Structures; - -#if DOUBLE -using Number = System.Double; -using Point2N = WinDirStat.Net.Structures.Point2D; -#else -using Number = System.Single; -using Point2N = WinDirStat.Net.Structures.Point2F; -#endif - -namespace WinDirStat.Net.Rendering { - /// A service for rendering WinDirStat treemaps. - public unsafe partial class TreemapRenderer { - - #region Fields - - /// The UI service. - private readonly IUIService ui; - - /// The last pixel array used for drawing. - private Rgba32Color[] pixels; - - /// The render options for the treemap. - private TreemapOptions options; - /// Calculated light position for the treemap. - private Number lx; - /// Calculated light position for the treemap. - private Number ly; - /// Calculated light position for the treemap. - private Number lz; - /// The render area for the current operation. - private Rectangle2I renderArea; - - #endregion - - #region Constructors - - /// Constructs the . - public TreemapRenderer(IUIService ui) { - this.ui = ui; - Options = TreemapOptions.Default; - } - - #endregion - - #region Properties - - /// Gets or sets the treemap options. - public TreemapOptions Options { - get => options; - set { - options = value; - - Number lx = options.LightSourceX; - Number ly = options.LightSourceY; - const Number lz = 10; - - Number lenght = (Number) Math.Sqrt(lx*lx + ly*ly + lz*lz); - this.lx = lx / lenght; - this.ly = ly / lenght; - this.lz = lz / lenght; - } - } - - #endregion - - private void InitPixels(Rectangle2I rc, Rgba32Color? background = null) { - int pixelCount = rc.Width * rc.Height; - if (pixels == null || pixels.Length != pixelCount) - pixels = new Rgba32Color[rc.Width * rc.Height]; - if (background.HasValue) - pixels.Memset(background.Value); - } - - [Conditional("DEBUG")] - private void RecurseCheckTree(ITreemapItem item) { - if (item.IsLeaf) { - Debug.Assert(item.ChildCount == 0); - } - else { - // TODO: check that children are sorted by size. - long sum = 0; - for (int i = 0; i < item.ChildCount; i++) { - ITreemapItem child = item[i]; - sum += child.Size; - RecurseCheckTree(child); - } - Debug.Assert(sum == item.Size); - } - } - - public void DrawTreemap(IWriteableBitmap bitmap, Rectangle2I rc, ITreemapItem root) { - RecurseCheckTree(root); - - Rectangle2I fullRc = rc; - - rc.Width--; - rc.Height--; - - if (rc.Width <= 0 || rc.Height <= 0) - return; - - renderArea = fullRc; - - if (root.Size == 0) - InitPixels(fullRc, Rgba32Color.Black); - else if (options.Grid) - InitPixels(fullRc, options.GridColor); - else - InitPixels(fullRc, new Rgba32Color(160, 160, 160)); - - fixed (Rgba32Color* pBitmapBits = pixels) { - - // Recursively draw the tree graph - if (root.Size > 0) { - Number[] surface = { 0, 0, 0, 0 }; - RecurseDrawGraph(pBitmapBits, root, rc, true, surface, options.Height, 0); - } - - bitmap.SetPixels(pBitmapBits); - } - } - - public void DrawColorPreview(IWriteableBitmap bitmap, Rectangle2I rc, Rgb24Color color) { - if (rc.Width <= 0 || rc.Height <= 0) - return; - - renderArea = rc; - - // That bitmap in turn will be created from this array - InitPixels(rc); - - fixed (Rgba32Color* pBitmapBits = pixels) { - - Number[] surface = { 0, 0, 0, 0 }; - - AddRidge(rc, surface, options.Height * options.ScaleFactor); - RenderRectangle(pBitmapBits, rc, surface, color); - - bitmap.SetPixels(pBitmapBits); - } - } - - public static ITreemapItem FindItemAtPoint(ITreemapItem item, Point2I p) { - if (item.IsLeaf) { - return item; - } - else { - for (int i = 0; i < item.ChildCount; i++) { - ITreemapItem child = item[i]; - Rectangle2I rcChild = child.Rectangle; - - if (rcChild.Contains(p)) - return FindItemAtPoint(child, p); - } - } - - return null; - } - } -} diff --git a/WinDirStat.Net.Base/Rendering/TreemapRendererFactory.cs b/WinDirStat.Net.Base/Rendering/TreemapRendererFactory.cs deleted file mode 100644 index 3694949..0000000 --- a/WinDirStat.Net.Base/Rendering/TreemapRendererFactory.cs +++ /dev/null @@ -1,32 +0,0 @@ -using WinDirStat.Net.Services; - -namespace WinDirStat.Net.Rendering { - /// A factory for treemap renderers. - public class TreemapRendererFactory { - - #region Fields - - /// The UI service. - private readonly IUIService ui; - - #endregion - - #region Constructors - - /// Constructs the. - public TreemapRendererFactory(IUIService ui) { - this.ui = ui; - } - - #endregion - - #region TreemapRenderer Factory - - /// Constructs a new . - public TreemapRenderer Create() { - return new TreemapRenderer(ui); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Rendering/TreemapStyle.cs b/WinDirStat.Net.Base/Rendering/TreemapStyle.cs deleted file mode 100644 index 9dcd4fc..0000000 --- a/WinDirStat.Net.Base/Rendering/TreemapStyle.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Rendering { - /// The types of render methods for treemaps. - [Serializable] - public enum TreemapStyle { - /// Horizontal/Vertical align. - [Description("KDirStat")] - KDirStatStyle = 0, - /// Corner align. - [Description("SequoiaView")] - SequoiaViewStyle = 1, - /// Dunno. - [Description("Simple")] - SimpleStyle = 2, - } -} diff --git a/WinDirStat.Net.Base/Services/IBitmapFactory.cs b/WinDirStat.Net.Base/Services/IBitmapFactory.cs deleted file mode 100644 index 5120114..0000000 --- a/WinDirStat.Net.Base/Services/IBitmapFactory.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.Services { - /// An interface for creating and loading bitmaps. - public interface IBitmapFactory { - - #region Create - - /// Creates a new writeable bitmap. - /// - /// The size of the bitmap. - /// The new writeable bitmap. - IWriteableBitmap CreateBitmap(Point2I size); - - #endregion - - #region From Source - - /// Loads a bitmap from the specified resource path. - /// - /// The resource path to load the bitmap from. - /// - /// The assembly to load the resource from. The calling assembly is used if null. - /// - /// The loaded bitmap. - IBitmap FromResource(string resourcePath, Assembly assembly = null); - - /// Loads a bitmap from the specified file path. - /// - /// The file path to load the bitmap from. - /// The loaded bitmap. - IBitmap FromFile(string filePath); - - /// Loads a bitmap from the specified stream. - /// - /// The stream to load the bitmap from. - /// The loaded bitmap. - IBitmap FromStream(Stream stream); - -#if WINDOWS - - /// Loads a bitmap from the specified icon handle. - /// - /// The handle of the icon to load. - /// The loaded bitmap. - IBitmap FromHIcon(IntPtr handle); - -#endif - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/IClipboardService.cs b/WinDirStat.Net.Base/Services/IClipboardService.cs deleted file mode 100644 index 0a41ce9..0000000 --- a/WinDirStat.Net.Base/Services/IClipboardService.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Services { - /// A service for interacting with the clipboard. - public interface IClipboardService { - - #region Text - - /// Gets the text assigned to the clipboard. - /// - /// A string if the clipboard has text assigned to it. - string GetText(); - /// Assigns text to the clipboard. - /// - /// The new text to assign to the clipboard. - void SetText(string text); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/IIconCacheService.cs b/WinDirStat.Net.Base/Services/IIconCacheService.cs deleted file mode 100644 index 8e49cfe..0000000 --- a/WinDirStat.Net.Base/Services/IIconCacheService.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections.Specialized; -using System.ComponentModel; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services { - /// A service for caching and looking up icons. - public interface IIconCacheService : INotifyPropertyChanged { - - #region Properties - - /// Gets the number of cached icons. - int Count { get; } - - #endregion - - #region Icon Properties - - /// Gets the default file icon. - IImage FileIcon { get; } - /// Gets the default folder icon. - IImage FolderIcon { get; } - /// Gets the default drive icon. - IImage VolumeIcon { get; } - /// Gets the default shortcut icon. - IImage ShortcutIcon { get; } - - #endregion - - #region Icon Caching - - /// Caches the icon of the specified file. - /// - /// The path of the file. - /// The cached icon on success, otherwise null. - IImage CacheIcon(string path); - /// Asynchronousy caches the icon of the specified file. - /// - /// The path of the file. - /// The method that returns the icon upon completion. - void CacheIconAsync(string path, ICacheIconCallback callback); - - /// Caches the icon and display name of the specified file. - /// - /// The path of the file. - /// The cached icon and icon on success, otherwise null. - IIconAndName CacheIconAndDisplayName(string path); - /// Asynchronousy caches the icon and display name of the specified file. - /// - /// The path of the file. - /// The method that returns the icon and name upon completion. - void CacheIconAndDisplayNameAsync(string path, ICacheIconAndNameCallback callback); - - /// Caches the file type's icon and type name. - /// - /// The extension of the file type. - /// The cached icon and type name on success, otherwise null. - IIconAndName CacheFileType(string extension); - /// Asynchronousy caches the file type's icon and type name. - /// - /// The extension of the file type. - /// The method that returns the icon and type name upon completion. - void CacheFileTypeAsync(string extension, ICacheIconAndNameCallback callback); - - /// Caches the special folder's icon and display name. - /// - /// The special folder type. - /// The cached icon and name on success, otherwise null. - IIconAndName CacheSpecialFolder(Environment.SpecialFolder folder); - /// Asynchronousy caches the special folder's icon and display name. - /// - /// The special folder type. - /// The method that returns the icon and name upon completion. - void CacheSpecialFolderAsync(Environment.SpecialFolder folder, ICacheIconAndNameCallback callback); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/IImagesService.cs b/WinDirStat.Net.Base/Services/IImagesService.cs deleted file mode 100644 index eaf42eb..0000000 --- a/WinDirStat.Net.Base/Services/IImagesService.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services { - /// A service for image references. - public interface IImagesService { - - #region File Icon Fields - - /// Gets the icon for file collection items. - IImage FileCollection { get; } - /// Gets the icon for free space items. - IImage FreeSpace { get; } - /// Gets the icon for unknown space items. - IImage UnknownSpace { get; } - /// Gets the icon for files that no longer exist. - IImage Missing { get; } - - #endregion - - } -} diff --git a/WinDirStat.Net.Base/Services/IMainCommandInfoService.cs b/WinDirStat.Net.Base/Services/IMainCommandInfoService.cs deleted file mode 100644 index 91d77a9..0000000 --- a/WinDirStat.Net.Base/Services/IMainCommandInfoService.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services { - public interface IMainCommandInfoService { - - #region File Menu - - IRelayUICommandInfo Open { get; } - IRelayUICommandInfo Save { get; } - IRelayUICommandInfo Reload { get; } - IRelayUICommandInfo Close { get; } - IRelayUICommandInfo Cancel { get; } - IRelayUICommandInfo Elevate { get; } - IRelayUICommandInfo Exit { get; } - - #endregion - - #region Context Menu/ToolBar - - IRelayUICommandInfo Expand { get; } - IRelayUICommandInfo Collapse { get; } - IRelayUICommandInfo OpenItem { get; } - IRelayUICommandInfo CopyPath { get; } - IRelayUICommandInfo Explore { get; } - IRelayUICommandInfo CommandPrompt { get; } - IRelayUICommandInfo PowerShell { get; } - IRelayUICommandInfo RefreshSelected { get; } - IRelayUICommandInfo DeleteRecycle { get; } - IRelayUICommandInfo DeletePermanently { get; } - IRelayUICommandInfo Properties { get; } - - #endregion - - #region Options Menu - - IRelayUICommandInfo ShowFreeSpace { get; } - IRelayUICommandInfo ShowUnknown { get; } - IRelayUICommandInfo ShowTotalSpace { get; } - IRelayUICommandInfo ShowFileTypes { get; } - IRelayUICommandInfo ShowTreemap { get; } - IRelayUICommandInfo ShowToolBar { get; } - IRelayUICommandInfo ShowStatusBar { get; } - IRelayUICommandInfo Configure { get; } - - #endregion - - #region Other - - IRelayUICommandInfo EmptyRecycleBin { get; } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/IOSService.cs b/WinDirStat.Net.Base/Services/IOSService.cs deleted file mode 100644 index fbf6fe0..0000000 --- a/WinDirStat.Net.Base/Services/IOSService.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services { - /// A service for OS-specific actions. - public interface IOSService { - - #region Privileges - - /// Gets if the current process has elevated privileges. - bool IsElevated { get; } - - /// Starts a new version of this process in an elevated environment. - void StartNewElevated(string arguments = ""); - - #endregion - - #region RunItem - - /// Opens the specified item using the default action. - /// - /// The file to open. - void RunItem(string file); - - #endregion - - #region Explore - - /// Opens the computer folder in Explorer. - void ExploreComputer(); - - /// Opens the folder in Explorer. - /// - /// The path of the folder to open. - void ExploreFolder(string folderPath); - - /// Opens the parent folder in Explorer and selects the file. - /// - /// The path of the file to select. - void ExploreFile(string filePath); - - /// Opens the properties window for the computer. - bool OpenComputerProperties(string filePath); - - /// Opens the properties window of the file. - /// The path of the file to view the properties of. - bool OpenProperties(string filePath); - - #endregion - - #region Console - - /// Opens the command prompt in the specified working directory. - /// - /// The working directory to open the command prompt in. - void OpenCommandPrompt(string directory); - - /// Opens PowerShell in the specified working directory. - /// - /// The working directory to open PowerShell in. - void OpenPowerShell(string directory); - - #endregion - - #region Delete/Recycle - - /// Permanently deletes the file. - /// - /// The path of the file to delete. - /// True if the operation was successful. - bool DeleteFile(string file); - - /// Sends the file or directory to the recycle bin. - /// - /// The path of the file to delete. - /// True if the operation was successful. - bool RecycleFile(string file); - - /// Deletes or recycles the file based on the conditional value. - /// - /// The path of the file to delete. - /// True if the file should be recycled. - /// True if the operation was successful. - bool DeleteOrRecycleFile(string file, bool recycle); - - /// Empties the recycle bin at the specified path. - /// - /// The window to own the dialogs. - /// The path of the recycle bin - /// True if the operation was successful. - bool EmptyRecycleBin(IWindow owner, string path = ""); - - /// Gets the stats about the specified recycle bin. - /// - /// The path of the recycle bin - /// The info about the recycle bin on success, otherwise null. - RecycleBinInfo GetRecycleBinInfo(string path); - - /// Gets the stats about every recycle bin. - /// - /// The info about the recycle bin on success, otherwise null. - RecycleBinInfo GetAllRecycleBinInfo(); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/IScanningService.cs b/WinDirStat.Net.Base/Services/IScanningService.cs deleted file mode 100644 index c5fdd27..0000000 --- a/WinDirStat.Net.Base/Services/IScanningService.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Model.Files; - -namespace WinDirStat.Net.Services { - - - - - /// A service for scanning a file tree. - public interface IScanningService : INotifyPropertyChanged, IDisposable { - - - - /// The available root item once the scan has fully started. - RootItem RootItem { get; } - - - event ScanEventHander Started; - event ScanEventHander Ended; - event EventHandler SpaceChanged; - - bool ShowFreeSpace { get; } - bool ShowUnknown { get; } - bool ShowTotalSpace { get; } - - ExtensionItems Extensions { get; } - - void Scan(params string[] rootPaths); - void ScanAsync(params string[] rootPaths); - void Close(bool waitForClose = false); - void CloseAsync(Action callback, bool runWhenAlreadyClosed = true); - void Cancel(bool waitForCancel = false); - void CancelAsync(Action callback, bool runWhenNotScanning = true); - void CancelAsync(ScanEventHander callback, bool runWhenNotScanning = true); - - TimeSpan ScanTime { get; } - TimeSpan ValidateTime { get; } - ScanState ScanState { get; } - ScanProgressState ProgressState { get; } - - bool CanDisplayProgress { get; } - double Progress { get; } - - bool IsScanning { get; } - bool IsScanningAndNotRefreshing { get; } - bool IsRefreshing { get; } - bool IsFinished { get; } - bool IsOpen { get; } - bool IsSuspended { get; set; } - bool IsAsync { get; } - Exception ExceptionResult { get; } - } -} diff --git a/WinDirStat.Net.Base/Services/ISettingsService.cs b/WinDirStat.Net.Base/Services/ISettingsService.cs deleted file mode 100644 index 5f280d7..0000000 --- a/WinDirStat.Net.Base/Services/ISettingsService.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.Services { - public interface ISettingsService : INotifyPropertyChanged { - - DriveSelectMode DriveSelectMode { get; set; } - string[] SelectedDrives { get; set; } - string SelectedFolderPath { get; set; } - - ThreadPriority RenderPriority { get; set; } - ThreadPriority ScanPriority { get; set; } - - TimeSpan RAMInterval { get; set; } - TimeSpan StatusInterval { get; set; } - TimeSpan ValidateInterval { get; set; } - - TreemapOptions TreemapOptions { get; set; } - Rgba32Color HighlightColor { get; set; } - - bool ShowUnknown { get; set; } - bool ShowFreeSpace { get; set; } - bool ShowTotalSpace { get; set; } - - bool ShowFileTypes { get; set; } - bool ShowTreemap { get; set; } - bool ShowToolBar { get; set; } - bool ShowStatusBar { get; set; } - - IconCacheMode IconCacheMode { get; set; } - - ReadOnlyCollection FilePalette { get; } - ReadOnlyCollection OriginalFilePalette { get; } - IList FilePalettePreviews { get; } - - Rgb24Color GetFilePaletteColor(int index); - void SetFilePalette(IEnumerable filePalette); - object GetFilePalettePreview(int index); - - ReadOnlyCollection SubtreePalette { get; } - - Rgb24Color GetSubtreePaletteColor(int level); - void SetSubtreePalette(IEnumerable subtreePalette); - - } -} diff --git a/WinDirStat.Net.Base/Services/IShortcutsService.cs b/WinDirStat.Net.Base/Services/IShortcutsService.cs deleted file mode 100644 index d7a44bf..0000000 --- a/WinDirStat.Net.Base/Services/IShortcutsService.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services { - /// A service for storing platform independent shortcuts. - public interface IShortcutsService { - - #region File Menu - - IShortcut Open { get; } - IShortcut Save { get; } - IShortcut Reload { get; } - IShortcut Close { get; } - IShortcut Cancel { get; } - IShortcut Elevate { get; } - IShortcut Exit { get; } - - #endregion - - #region Context Menu/Toolbar - - IShortcut Expand { get; } - IShortcut OpenItem { get; } - IShortcut CopyPath { get; } - IShortcut Explore { get; } - IShortcut CommandPrompt { get; } - IShortcut PowerShell { get; } - IShortcut RefreshSelected { get; } - IShortcut DeleteRecycle { get; } - IShortcut DeletePermanently { get; } - IShortcut Properties { get; } - - #endregion - - #region Options Menu - - IShortcut ShowFreeSpace { get; } - IShortcut ShowUnknown { get; } - IShortcut ShowTotalSpace { get; } - IShortcut ShowFileTypes { get; } - IShortcut ShowTreemap { get; } - IShortcut ShowToolBar { get; } - IShortcut ShowStatusBar { get; } - IShortcut Configure { get; } - - #endregion - - #region Other - - IShortcut EmptyRecycleBin { get; } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/IUIService.cs b/WinDirStat.Net.Base/Services/IUIService.cs deleted file mode 100644 index 507bc7d..0000000 --- a/WinDirStat.Net.Base/Services/IUIService.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services { - /// A service for all UI actions. - public interface IUIService { - - #region Dispatcher - - /// Invokes the action on the UI thread. - /// - /// The action to invoke. - void Invoke(Action action); - - /// Invokes the function on the UI thread. - /// - /// The function to invoke. - /// The result of the function. - T Invoke(Func action); - - /// Invokes the action asynchronously on the UI thread. - /// - /// The action to invoke. - /// True if the action should use normal priority. - void BeginInvoke(Action action, bool normalPriority); - - /// Checks if the current thread is the UI thread. - /// - /// True if the current thread is the UI thread. - bool CheckAccess(); - - #endregion - - #region Shutdown - - /// Shuts down the application. - void Shutdown(); - - event EventHandler ShuttingDown; - - #endregion - - #region Create Timer - - /// Creates a new stopped UI timer. - /// - /// The interval for the timer. - /// True if the timer runs at normal priority. - /// The callback on the timer tick event. - IUITimer CreateTimer(TimeSpan interval, bool normalPriority, Action callback); - /// Creates a new running UI timer. - /// - /// The interval for the timer. - /// True if the timer runs at normal priority. - /// The callback on the timer tick event. - /// The newly created timer. - IUITimer StartTimer(TimeSpan interval, bool normalPriority, Action callback); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/IWindowDialogService.cs b/WinDirStat.Net.Base/Services/IWindowDialogService.cs deleted file mode 100644 index 2494218..0000000 --- a/WinDirStat.Net.Base/Services/IWindowDialogService.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services { - /// A service for launching dialogs and showing messages. - public interface IWindowDialogService { - - /// Shows the dialog for selecting paths to scan. - /// - /// The owner window for this dialog. - /// The selected root paths on success, otherwise null. - DriveSelectResult ShowDriveSelect(IWindow owner); - - /// Shows the folder browser dialog to select a folder. - /// - /// The owner window for this dialog. - /// The description to display. - /// True if the new folder button is present. - /// The currently selected path. Use an empty string for nothing. - /// The selected path on success, otherwise null. - string ShowFolderBrowser(IWindow owner, string description, bool showNewFolder, string selectedPath = ""); - - /// Shows a message with no icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - MessageResult ShowMessage(IWindow owner, string message, string title, MessageButton button = MessageButton.OK); - - /// Shows a message with an information icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - MessageResult ShowInformation(IWindow owner, string message, string title, MessageButton button = MessageButton.OK); - - /// Shows a message with a question icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - MessageResult ShowQuestion(IWindow owner, string message, string title, MessageButton button = MessageButton.OK); - - /// Shows a message with a warning icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - MessageResult ShowWarning(IWindow owner, string message, string title, MessageButton button = MessageButton.OK); - - /// Shows a message with an error icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - MessageResult ShowError(IWindow owner, string message, string title, MessageButton button = MessageButton.OK); - } -} diff --git a/WinDirStat.Net.Base/Services/ImagesServiceBase.cs b/WinDirStat.Net.Base/Services/ImagesServiceBase.cs deleted file mode 100644 index 955a452..0000000 --- a/WinDirStat.Net.Base/Services/ImagesServiceBase.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services { - /// A service for image references. - public abstract class ImagesServiceBase { - - #region File Icon Fields - - /// Gets the icon for file collection items. - public IImage FileCollection { get; protected set; } - /// Gets the icon for free space items. - public IImage FreeSpace { get; protected set; } - /// Gets the icon for unknown space items. - public IImage UnknownSpace { get; protected set; } - /// Gets the icon for files that no longer exist. - public IImage Missing { get; protected set; } - - #endregion - - #region Icon Fields - - /// The icon for the Close command. - public IImage Close { get; protected set; } - /// The icon Command Prompt command. - public IImage Cmd { get; protected set; } - //public ImageSource CmdElevated { get; protected set; } - /// The icon Copy command. - public IImage Copy { get; protected set; } - /// The icon Cut command. - public IImage Cut { get; protected set; } - /// The icon Delete command. - public IImage Delete { get; protected set; } - /// The icon Elevate command. - public IImage Elevate { get; protected set; } - /// The icon Empty Recycle Bin command. - public IImage EmptyRecycleBin { get; protected set; } - /// The icon Exit command. - public IImage Exit { get; protected set; } - /// The icon Expand command. - public IImage Expand { get; protected set; } - /// The icon ExploreCommand command. - public IImage Explore { get; protected set; } - /// The icon Open command. - public IImage Open { get; protected set; } - /// The icon Paste command. - public IImage Paste { get; protected set; } - /// The icon Copy Path command. - public IImage CopyPath { get; protected set; } - /// The icon PowerShell command. - public IImage PowerShell { get; protected set; } - //public IImage PowerShellElevated { get; protected set; } - /// The icon Properties command. - public IImage Properties { get; protected set; } - /// The icon Recycle command. - public IImage RecycleBin { get; protected set; } - /// The icon Redo command. - public IImage Redo { get; protected set; } - /// The icon Reload command. - public IImage Reload { get; protected set; } - /// The icon Refresh Selected command. - public IImage RefreshSelected { get; protected set; } - /// The icon Run (Open Item) command. - public IImage Run { get; protected set; } - /// The icon Save command. - public IImage Save { get; protected set; } - /// The icon Search command. - public IImage Search { get; protected set; } - /// The icon Settings command. - public IImage Settings { get; protected set; } - /*/// The icon Show File Types command. - public IImage ShowFileTypes { get; protected set; }*/ - /// The icon Show Total Space command. - public IImage ShowTotalSpace { get; protected set; } - /// The icon Show Treemap command. - public IImage ShowTreemap { get; protected set; } - /// The icon Undo command. - public IImage Undo { get; protected set; } - - #endregion - - #region Fields - - /// The bitmap factory service. - protected IBitmapFactory BitmapFactory { get; } - /// Gets the UI service. - protected IUIService UI { get; } - - #endregion - - #region Constructors - - /// Constructs the . - public ImagesServiceBase(IBitmapFactory bitmapFactory, - IUIService ui) - { - BitmapFactory = bitmapFactory; - UI = ui; - - UI.Invoke(() => { - // Load file type icons with a different method - FileCollection = LoadFileIcon(nameof(FileCollection)); - FreeSpace = LoadFileIcon(nameof(FreeSpace)); - UnknownSpace = LoadFileIcon(nameof(UnknownSpace)); - Missing = LoadFileIcon(nameof(Missing)); - - // Load all unassigned icons with reflection - foreach (PropertyInfo propInfo in typeof(ImagesServiceBase).GetProperties()) { - if (propInfo.PropertyType == typeof(IImage) && propInfo.CanWrite) { - IImage value = (IImage) propInfo.GetValue(this); - if (value != null) - continue; - value = LoadIcon(propInfo.Name); - propInfo.SetValue(this, value); - } - } - }); - } - - #endregion - - #region Abstract Methods - - /// Loads the icon with the specified name. - /// - /// The name of the icon. - protected abstract IImage LoadIcon(string name); - - /// Loads the file icon with the specified name. - /// - /// The name of the file icon. - protected abstract IImage LoadFileIcon(string name); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/Implementation/CommandInfoService.cs b/WinDirStat.Net.Base/Services/Implementation/CommandInfoService.cs deleted file mode 100644 index 4d5cb94..0000000 --- a/WinDirStat.Net.Base/Services/Implementation/CommandInfoService.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Services.Implementation { - public abstract class CommandInfoService { - - private readonly Dictionary commandInfos; - - - public CommandInfoService() { - commandInfos = new Dictionary(); - } - - public void Initialize() { - foreach (PropertyInfo prop in GetType().GetProperties()) { - if (prop.PropertyType == typeof(IRelayUICommandInfo)) { - commandInfos.Add(prop.Name, (IRelayUICommandInfo) prop.GetValue(this)); - } - } - } - - public IRelayUICommandInfo this[string commandName] => commandInfos[commandName]; - - } -} diff --git a/WinDirStat.Net.Base/Services/Implementation/RelayCommandService.cs b/WinDirStat.Net.Base/Services/Implementation/RelayCommandService.cs deleted file mode 100644 index 6ae9711..0000000 --- a/WinDirStat.Net.Base/Services/Implementation/RelayCommandService.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Services.Implementation { - public abstract class RelayCommandService { - - /// - /// Creates a new with the specified info and actions. - /// - /// - /// The abstract information about the command. - /// The execution action. - /// The optional can execute function. - /// The constructed - public abstract IRelayCommand Create(IRelayCommandInfo info, Action execute, - Func canExecute = null); - - /// - /// Creates a new with the specified info and actions. - /// - /// - /// The parameter type of the command. - /// The abstract information about the command. - /// The execution action. - /// The optional can execute function. - /// The constructed - public abstract IRelayCommand Create(IRelayCommandInfo info, Action execute, - Func canExecute = null); - - /// - /// Creates a new with the specified info and actions. - /// - /// - /// The abstract information about the command. - /// The execution action. - /// The optional can execute function. - /// The constructed - public abstract IRelayUICommand Create(IRelayUICommandInfo info, Action execute, - Func canExecute = null); - - /// - /// Creates a new with the specified info and actions. - /// - /// - /// The parameter type of the command. - /// The abstract information about the command. - /// The execution action. - /// The optional can execute function. - /// The constructed - public abstract IRelayUICommand Create(IRelayUICommandInfo info, Action execute, - Func canExecute = null); - - } -} diff --git a/WinDirStat.Net.Base/Services/Implementation/ScanningService.cs b/WinDirStat.Net.Base/Services/Implementation/ScanningService.cs deleted file mode 100644 index 054d2d7..0000000 --- a/WinDirStat.Net.Base/Services/Implementation/ScanningService.cs +++ /dev/null @@ -1,895 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading; -using System.Windows; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Services { - /// A service for scanning a path's file tree. - public abstract partial class ScanningService : ObservableVolatileObject { - - #region Protected Classes - - /// A collection of parent folders and files to refresh. - protected class RefreshFiles { - /// The parent folder of the files. - public FolderItem Parent { get; } - /// The files in the parent folder to refresh. - public List Files { get; } - - /// Constructs the . - public RefreshFiles(FolderItem parent) { - Parent = parent; - Files = new List(); - } - - /// Constructs the . - public RefreshFiles(KeyValuePair> pair) { - Parent = pair.Key; - Files = pair.Value; - } - } - - #endregion - - #region Fields - - /// The program settings. - protected readonly SettingsService settings; - /// The OS specific service - protected readonly IOSService os; - /// The UI service - protected readonly IUIService ui; - - // Scan async - /// The cancellation token source for the asynchronous scan thread. - private CancellationTokenSource cancel; - /// The current asynchronous scan thread. - private Thread scanThread; - /// The lock object for scan thread setup. - private readonly object threadLock = new object(); - /// The lock object exclusively for accessing the resume event. - private readonly object resumeLock = new object(); - /// The timer for validating the file tree during a scan. - private readonly Timer validateTimer; - - // Scan progress - /// The total size that has been scanned so far. - private long totalScannedSize; - /// The total size for all scanned roots. - private long totalSize; - /// The total free space for all scanned roots. - private long totalFreeSpace; - /// True if all scanned roots are drives and thus have a definite used size. - private bool canDisplayProgress; - /// The watch for keeping track of the scan duration. - private readonly Stopwatch scanWatch; - /// A watch that keeps track of the time spent validating. - private readonly Stopwatch validateWatch; - /// True if validation has been requested on the scan thread. - private volatile bool validationRequested; - - // Scan state - /// The current state of the scan. - private ScanState scanState; - /// The current progress state of the scan. - private ScanProgressState progressState; - /// True if a refresh operation is in progress. - private bool isRefreshing; - /// The wait handle for resuming a scan. Set if the scan is not suspended. - private ManualResetEvent resumeEvent = new ManualResetEvent(true); - /// True if the UI refreshing should be supressed due to validation. - private bool suppressRefresh; - - // Scan result - /// The root item of the file tree being scanned. - private RootItem rootItem; - /// The resulting exception from the current scan. - private Exception exceptionResult; - /// Gets the extension item collection that records all encountered extensions. - public ExtensionItems Extensions { get; } - /// Gets the drive item collection that records the current drive list. - public DriveItems Drives { get; } - /// The root paths to scan. - private string[] rootPaths; - /// The files to refresh. - private RefreshFiles[] refreshFiles; - /// The result of the drive select dialog used for scanning. - private DriveSelectResult driveSelectResult; - - // Dispose - /// True if the scanning service has been disposed of. - private volatile bool disposed; - - #endregion - - #region Events - - /// Callbacks for when a scan has ended in any fashion. - public event ScanEventHander Ended; - /// Callbacks for . - private event ScanEventHander Cancelled; - - /// Called when the space settings have changed. - public event EventHandler SpaceChanged; - - #endregion - - #region Constructors - - /// Constructs the . - public ScanningService(SettingsService settings, - IOSService os, - IUIService ui) - { - this.settings = settings; - this.os = os; - this.ui = ui; - settings.PropertyChanged += OnSettingsPropertyChanged; - Extensions = new ExtensionItems(this, settings); - Drives = new DriveItems(this); - validateTimer = new Timer(OnValidateTick, null, Timeout.Infinite, Timeout.Infinite); - validateWatch = new Stopwatch(); - scanWatch = new Stopwatch(); - validationRequested = false; - } - - #endregion - - #region Event Handlers - - /// Called when the settings' properties have changed. - private void OnSettingsPropertyChanged(object sender, PropertyChangedEventArgs e) { - switch (e.PropertyName) { - case nameof(SettingsService.ShowFreeSpace): - case nameof(SettingsService.ShowUnknown): - case nameof(SettingsService.ShowTotalSpace): - bool shouldSet = !IsScanning && !IsRefreshing; - if (shouldSet) - IsRefreshing = true; - RaisePropertyChanged(e.PropertyName); - RaiseSpaceChanged(); - if (shouldSet) - IsRefreshing = false; - break; - case nameof(SettingsService.ScanPriority): - lock (volatileLock) { - if (IsAsync) - scanThread.Priority = settings.ScanPriority; - } - break; - case nameof(SettingsService.ValidateInterval): - // Same thing as performing an interval change - StartValidateTimer(); - break; - } - } - - #endregion - - #region Private Helpers - - /// Stops the validate timer. - private void StopValidateTimer() { - if (!disposed) - validateTimer.Change(Timeout.Infinite, Timeout.Infinite); - } - - /// Starts the validate timer. - private void StartValidateTimer() { - if (!disposed) - validateTimer.Change(settings.ValidateInterval, Timeout.InfiniteTimeSpan); - } - - /// Adds a request for the file tree to be validated. - private void OnValidateTick(object state) { - validationRequested = true; - } - - /// Raises the event. - private void RaiseSpaceChanged() { - SpaceChanged?.Invoke(this, EventArgs.Empty); - } - - /// Throws an exception if a scan is in progress. - [DebuggerStepThrough] - private void ThrowIfScanning() { - if (IsScanning) - throw new InvalidOperationException("Cannot start new scan while one is currently in progress!"); - } - - #endregion - - #region Public Scanning - - /// Begins a synchronous scan of the specified root paths. - public void Scan(DriveSelectResult result) { - if (result == null) - throw new ArgumentNullException(nameof(result)); - ThrowIfScanning(); - lock (threadLock) { - RootPaths = result.GetResultPaths(); - driveSelectResult = result; - ScanPrepare(false); - ScanThread(false, cancel.Token); - } - } - - /// Begins a asynchronous scan of the specified root paths. - public void ScanAsync(DriveSelectResult result) { - if (result == null) - throw new ArgumentNullException(nameof(result)); - ThrowIfScanning(); - lock (threadLock) { - RootPaths = result.GetResultPaths(); - driveSelectResult = result; - ScanPrepare(false); - scanThread = new Thread(() => ScanThread(false, cancel.Token)) { - Priority = settings.ScanPriority, - Name = "File Scan", - }; - scanThread.Start(); - } - } - - /// Closes the current scanned file tree. - /// - /// - /// Waits for the scan to fully close. DO NOT call this on the UI thread. - /// - public void Close(bool waitForClose = false) { - if (IsOpen) { - Cancel(waitForClose); - RootItem = null; - ClosedCleanup(); - ScanState = ScanState.NotStarted; - ProgressState = ScanProgressState.NotStarted; - Extensions.Clear(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - } - } - - /// - /// Closes the current scanned file tree if one exists and runs the callback if needed. - /// - /// - /// The callback to run after close has fininshed. - /// True if the callback is run when no file tree is open. - public void CloseAsync(Action callback, bool runWhenNotOpen = true) { - if (callback == null) - throw new ArgumentNullException(nameof(callback)); - if (IsScanning) { - CancelAsync(() => { - Close(true); - callback(); - }, true); - } - else if (IsOpen || runWhenNotOpen) { - Close(true); - callback(); - } - } - - /// Cancels the current scan if one exists. - /// - /// - /// Waits for the scan to fully complete. DO NOT call this on the UI thread. - /// - public void Cancel(bool waitForCancel = false) { - if (IsScanning && ScanState != ScanState.Cancelling) { - ScanState = ScanState.Cancelling; - CancellationTokenSource cancel = this.cancel; - ProgressState = ScanProgressState.Ending; - cancel.Cancel(); - // Make sure the wait handle resumes if suspended. - // Otherwise cancellation will never be reached. - IsSuspended = false; - while (waitForCancel && IsAsync) - Thread.Sleep(5); - } - } - - /// Cancels the current scan if one exists and runs the callback if needed. - /// - /// The callback to run after cancellation is fininshed. - /// True if the callback is run when no scan is running. - public void CancelAsync(Action callback, bool runWhenNotScanning = true) { - if (callback == null) - throw new ArgumentNullException(nameof(callback)); - CancelAsync((o, e) => callback(), runWhenNotScanning); - } - - /// Cancels the current scan if one exists and runs the callback if needed. - /// - /// The callback to run after cancellation is fininshed. - /// True if the callback is run when no scan is running. - public void CancelAsync(ScanEventHander callback, bool runWhenNotScanning = true) { - if (callback == null) - throw new ArgumentNullException(nameof(callback)); - if (IsScanning) { - if (ScanState != ScanState.Cancelling) { - Cancelled += new ScanEventHander(callback); - Cancel(false); - } - } - else if (runWhenNotScanning) { - callback(this, new ScanEventArgs(scanState, progressState)); - } - } - - #endregion - - #region Scan Prepare/Thread - - /// Prepares the scan before starting. - private void ScanPrepare(bool refreshing) { - lock (threadLock) { - IsSuspended = false; - IsRefreshing = refreshing; - refreshFiles = null; - CanDisplayProgress = false; - validateWatch.Reset(); - scanWatch.Reset(); - ProgressState = ScanProgressState.Starting; - ScanState = ScanState.Scanning; - TotalScannedSize = 0; - TotalSize = 0; - TotalFreeSpace = 0; - if (!refreshing) { - Extensions.Clear(); - RootItem = null; - } - validateWatch.Reset(); - RaisePropertyChanged(nameof(ScanTime)); - scanWatch.Start(); - cancel = new CancellationTokenSource(); - StartValidateTimer(); - } - } - - /// The root method for running the scan. - private void ScanThread(bool useRefreshFiles, CancellationToken token) { - Exception exception = null; - try { - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - if (useRefreshFiles) - Refresh(refreshFiles, token); - else - Scan(rootPaths, token); - RootItem?.FullValidate(); - } - catch (ThreadAbortException ex) { - exception = ex; - } - catch (Exception ex) { - Debug.WriteLine(ex); - exception = ex; - } - finally { - refreshFiles = null; - FinishedCleanup(); - StopValidateTimer(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - ProgressState = ScanProgressState.Ending; - cancel?.Dispose(); - cancel = null; - scanWatch?.Stop(); - scanThread = null; - - if (!disposed) { - RaisePropertyChanged(nameof(ScanTime)); - if (scanState == ScanState.Cancelling) { - // TODO: Should cancel remove all progress made? - //RootItem = null; - ScanState = ScanState.Cancelled; - } - else if (exception == null) { - ScanState = ScanState.Finished; - } - else { - RootItem = null; - ExceptionResult = exception; - ScanState = ScanState.Failed; - } - IsRefreshing = false; - ProgressState = ScanProgressState.Ended; - Ended?.Invoke(this, new ScanEventArgs(scanState, progressState, exception)); - if (scanState == ScanState.Cancelled) { - Cancelled?.Invoke(this, new ScanEventArgs(scanState, progressState, exception)); - Cancelled = null; - } - } - else { - IsRefreshing = false; - ExceptionResult = exception; - ScanState = ScanState.Failed; - } - } - } - - #endregion - - #region Root Space Properties - - /// Gets if free space items should be listed. - public bool ShowFreeSpace => settings.ShowFreeSpace; - /// Gets if unknown items should be listed. - public bool ShowUnknown => settings.ShowUnknown; - /// - /// Gets if free space and unknown items should be listed in the absolute or file root. - /// - public bool ShowTotalSpace => settings.ShowTotalSpace; - - #endregion - - #region Scan Properties - - /*/// Gets the result of the drive select dialog used for scanning. - public DriveSelectResult DriveSelectResult { - get => driveSelectResult; - set => Set(ref driveSelectResult, value); - }*/ - - /// Gets the root paths to scan. - public string[] RootPaths { - get => rootPaths; - set => Set(ref rootPaths, value); - } - - /// Gets the root item of the scanned/scanning file tree. - public RootItem RootItem { - get => VolatileGet(ref rootItem); - protected set { - lock (volatileLock) { - if (rootItem == value) - return; - // Unhooks the events from the IScanningService - rootItem?.Dispose(); - rootItem = value; - } - RaisePropertyChanged(); - } - } - - /// Gets how long the scan has been going on for. Or how long the scan took. - public TimeSpan ScanTime => scanWatch.Elapsed; - - /// Gets the amount of time taken to validate the file tree while scanning. - public TimeSpan ValidateTime => validateWatch.Elapsed; - - /// Gets the current state of the scan. - public ScanState ScanState { - get => scanState; - set { - bool suspendedChanged = false; - bool scanningChanged = false; - bool scanningNotRefreshingChanged = false; - bool finishedChanged = false; - bool openChanged = false; - lock (volatileLock) { - if (scanState == value) - return; - - bool suspendedBefore = IsSuspended; - bool scanningBefore = IsScanning; - bool scanningNotRefreshingBefore = IsScanningAndNotRefreshing; - bool finishedBefore = IsFinished; - bool openBefore = IsOpen; - - scanState = value; - - suspendedChanged = suspendedBefore != IsSuspended; - scanningChanged = scanningBefore != IsScanning; - scanningNotRefreshingChanged = scanningNotRefreshingBefore != IsScanningAndNotRefreshing; - finishedChanged = finishedBefore != IsFinished; - openChanged = openBefore != IsOpen; - - if (suspendedChanged) { - if (IsSuspended) - scanWatch.Stop(); - else - scanWatch.Start(); - } - } - RaisePropertyChanged(); - RaisePropertyChangedIf(suspendedChanged, nameof(IsSuspended)); - RaisePropertyChangedIf(scanningChanged, nameof(IsScanning)); - RaisePropertyChangedIf(scanningNotRefreshingChanged, nameof(IsScanningAndNotRefreshing)); - RaisePropertyChangedIf(finishedChanged, nameof(IsFinished)); - RaisePropertyChangedIf(openChanged, nameof(IsOpen)); - } - } - /// Gets the current progress state of the scan. - public ScanProgressState ProgressState { - get => VolatileGet(ref progressState); - protected set => VolatileSet(ref progressState, value); - } - - /// Gets if the scanner can guarantee some estimate of scan progress. - public bool CanDisplayProgress { - get => VolatileGet(ref canDisplayProgress); - protected set => VolatileSet(ref canDisplayProgress, value); - } - /// Gets the progress of the scan, or 1 if the scan is ended. - public double Progress { - get { - lock (volatileLock) { - if (canDisplayProgress) { - switch (progressState) { - case ScanProgressState.Started: - return (double) totalScannedSize / (totalSize - totalFreeSpace); - case ScanProgressState.Ending: - case ScanProgressState.Ended: - return 1d; - } - } - return 0d; - } - } - } - /// Gets if the scanner is scanning or cancelling a scan. - public bool IsScanning { - get { - lock (volatileLock) - return scanState == ScanState.Scanning || scanState == ScanState.Cancelling; - } - } - // Todo: We can probably remove this - /// Gets if the scanner is scanning or cancelling a scan, but not refreshing. - public bool IsScanningAndNotRefreshing { - get { - lock (volatileLock) - return (scanState == ScanState.Scanning || scanState == ScanState.Cancelling) && - !isRefreshing; - } - } - /// Gets if the scanner is refreshing. - public bool IsRefreshing { - get => VolatileGet(ref isRefreshing); - protected set => VolatileSet(ref isRefreshing, value); - } - /// Gets if the scanner has a successfully finished scan. - public bool IsFinished { - get => VolatileGet(ref scanState) == ScanState.Finished; - } - /// Gets if a finished or cancelled scanned file tree is open. - public bool IsOpen { - get { - lock (volatileLock) - return scanState == ScanState.Finished || scanState == ScanState.Cancelled; - } - } - /// Gets or sets if the current scan operation is suspended. - public bool IsSuspended { - get { - lock (resumeLock) { - if (!disposed) - return !resumeEvent.WaitOne(0); - } - return false; - } - set { - lock (resumeLock) { - lock (volatileLock) { - //if (!IsScanning) - // throw new InvalidOperationException("Cannot changed suspended state while not scanning!"); - if (IsSuspended == value) - return; - - if (!disposed) { - if (value) - resumeEvent.Reset(); - else - resumeEvent.Set(); - } - } - } - RaisePropertyChanged(); - } - } - /// Gets if an asynchronous scan thread is running. - public bool IsAsync { - get { - lock (volatileLock) - return scanThread != null && scanThread.IsAlive; - } - } - /// Gets if an asynchronous scan thread is running. - public Exception ExceptionResult { - get => VolatileGet(ref exceptionResult); - private set => VolatileSet(ref exceptionResult, value); - } - - /// Gets if the UI refreshing should be supressed due to validation. - public bool SuppressFileTreeRefresh { - get => VolatileGet(ref suppressRefresh); - private set => VolatileSet(ref suppressRefresh, value); - } - - #endregion - - #region IDisposable Implementation - - /// Disposes of the scanning service. - public void Dispose() { - if (!disposed) { - disposed = true; - scanThread?.Abort(); - validateTimer?.Dispose(); - resumeEvent.Dispose(); - } - } - - /// Disposes of the scanning service. - /*protected virtual void Dispose(bool disposing) { - }*/ - - #endregion - - #region Protected Properties - - /// Gets or sets the total size that has been scanned so far. - protected long TotalScannedSize { - get { lock (volatileLock) return totalScannedSize; } - set { lock (volatileLock) totalScannedSize = value; } - } - /// Gets or sets the total size for all scanned roots. - protected long TotalSize { - get { lock (volatileLock) return totalSize; } - set { lock (volatileLock) totalSize = value; } - } - /// Gets or sets the total free space for all scanned roots. - protected long TotalFreeSpace { - get { lock (volatileLock) return totalFreeSpace; } - set { lock (volatileLock) totalFreeSpace = value; } - } - - #endregion - - #region Protected Methods - - /// Checks if the scan operation is suspended and waits until resume if it is. - protected bool AsyncChecks(CancellationToken token) { - if (disposed) - return true; - - if (!resumeEvent.WaitOne(0)) { - StopValidateTimer(); - // Let's validate before suspension so that things are up to date - BasicValidate(); - resumeEvent.WaitOne(); - StartValidateTimer(); - validationRequested = false; - } - else if (validationRequested) { - StopValidateTimer(); - BasicValidate(); - StartValidateTimer(); - validationRequested = false; - } - return token.IsCancellationRequested; - } - - /// Performs a basic validation of the file tree being scanned. - private void BasicValidate() { - if (RootItem != null) { - ui.Invoke(() => { - Stopwatch validateWatch = Stopwatch.StartNew(); - SuppressFileTreeRefresh = true; - RootItem.BasicValidate(); - SuppressFileTreeRefresh = false; - TimeSpan validateTime = validateWatch.Elapsed; - Console.WriteLine($"Took {validateTime.TotalMilliseconds}ms to validate"); - }); - } - } - - #endregion - - #region Drives - - /// Scans and returns all valid drive items. - /// - /// All valid drive items. - public DriveItem[] ScanDrives() { - List drives = new List(); - DriveInfo[] driveInfos = DriveInfo.GetDrives(); - for (int i = 0; i < driveInfos.Length; i++) { - DriveInfo driveInfo = driveInfos[i]; - if (IsDriveValid(driveInfo)) - drives.Add(new DriveItem(driveInfo)); - } - return drives.ToArray(); - } - - /// Scans and returns all valid drive names. - /// - /// All valid drive names. - public string[] ScanDriveNames() { - List paths = new List(); - DriveInfo[] driveInfos = DriveInfo.GetDrives(); - for (int i = 0; i < driveInfos.Length; i++) { - DriveInfo driveInfo = driveInfos[i]; - if (IsDriveValid(driveInfo)) - paths.Add(driveInfo.Name); - } - return paths.ToArray(); - } - - /// Gets if the drive is valid for use. - /// - /// The drive to check. - /// True if the drive is valid. - public bool IsDriveValid(DriveInfo driveInfo) { - return driveInfo.IsReady && - driveInfo.DriveType != DriveType.Unknown && - driveInfo.DriveType != DriveType.NoRootDirectory; - } - - #endregion - - #region Abstract Methods - - /// Runs the scan process. - /// - /// The root paths to scan. - /// The scan cancellation token. - protected abstract void Scan(string[] rootPaths, CancellationToken token); - - protected abstract void Refresh(RefreshFiles[] refreshFiles, CancellationToken token); - - /// Cleanup called as a scan finishes. - protected abstract void FinishedCleanup(); - /// Cleanup called when a scanned file tree is closed. - protected abstract void ClosedCleanup(); - - #endregion - - #region File Management - - /// Permanently deletes the file. - /// - /// The path of the file to delete. - /// True if the operation was successful. - public bool DeleteFile(FileItemBase file) { - return DeleteOrRecycleFile(file, false); - } - - /// Sends the file or directory to the recycle bin. - /// - /// The path of the file to delete. - /// True if the operation was successful. - public bool RecycleFile(FileItemBase file) { - return DeleteOrRecycleFile(file, true); - } - - /// Deletes or recycles the file based on the conditional value. - /// - /// The path of the file to delete. - /// True if the file should be recycled. - /// True if the operation was successful. - public bool DeleteOrRecycleFile(FileItemBase file, bool recycle) { - ThrowIfScanning(); - if (!file.IsFileType || file.Type == FileItemType.Volume) - throw new InvalidOperationException("Can only delete files or folders"); - if (os.DeleteOrRecycleFile(file.FullName, recycle)) { - // File was successfully deleted, let's remove it from the file tree - // Set IsRefreshing to trigger any required UI invalidation - IsRefreshing = true; - FolderItem parent = file.Parent; - parent.RemoveItem(file); - parent.UpdwardsFullValidate(); - IsRefreshing = false; - return true; - } - return false; - } - - #endregion - - #region Public Refreshing - - /// Reloads the selected files. - /// - /// The files to reload. - public void RefreshFilesAsync(IEnumerable selectedFiles) { - if (!IsOpen) - throw new InvalidOperationException("No scan is open to refresh!"); - ThrowIfScanning(); - lock (threadLock) { - ScanPrepare(true); - scanThread = new Thread(() => RefreshThread(selectedFiles, cancel.Token)) { - Priority = settings.ScanPriority, - Name = "File Refresh", - }; - - // Measures to ensure garbage collection - //selectedFiles = null; - - scanThread.Start(); - } - } - - private void RefreshThread(IEnumerable selectedFiles, CancellationToken token) { - FileItemBase[] isolatedFiles = FolderItem.IsolateAncestores(selectedFiles); - if (isolatedFiles.Length > 0) { - if (isolatedFiles[0].IsAbsoluteRootType) { - // Just perform a full reload - ScanThread(false, token); - return; - } - - // Group all files into lists for each similar parent - Dictionary> refreshFilesMap = new Dictionary>(); - for (int i = 0; i < isolatedFiles.Length; i++) { - FileItemBase file = isolatedFiles[i]; - FolderItem parent = file.FileParent; - if (!refreshFilesMap.TryGetValue(parent, out List parentFiles)) { - parentFiles = new List(); - refreshFilesMap.Add(parent, parentFiles); - } - parentFiles.Add(file); - } - - // Convert the refresh files to an array - refreshFiles = new RefreshFiles[refreshFilesMap.Count]; - int index = 0; - foreach (var pair in refreshFilesMap) - refreshFiles[index++] = new RefreshFiles(pair); - - // Next remove the files' children from the tree - foreach (RefreshFiles parentFile in refreshFiles) { - FolderItem parent = parentFile.Parent; - FolderItem fileCollection = parent.GetFileCollection(); - int count = parentFile.Files.Count; - for (int i = 0; i < count; i++) { - if (parentFile.Files[i] is FolderItem folder) - folder.ClearItems(); - } - } - - // Measures to ensure garbage collection - selectedFiles = null; - isolatedFiles = null; - refreshFilesMap = null; - - if (AsyncChecks(token)) - return; - - ScanThread(true, token); - } - } - - /// Reloads the scanned file tree from the beginning. - public void ReloadAsync() { - if (!IsOpen) - throw new InvalidOperationException("No scan is open to reload!"); - ThrowIfScanning(); - lock (threadLock) { - ScanPrepare(true); - rootPaths = driveSelectResult.GetResultPaths(); - scanThread = new Thread(() => ScanThread(false, cancel.Token)) { - Priority = settings.ScanPriority, - Name = "File Reload", - }; - scanThread.Start(); - } - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/Implementation/SettingsService.Defaults.cs b/WinDirStat.Net.Base/Services/Implementation/SettingsService.Defaults.cs deleted file mode 100644 index f17dd39..0000000 --- a/WinDirStat.Net.Base/Services/Implementation/SettingsService.Defaults.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.Services { - partial class SettingsService { - /// The default file palette colors. - public static readonly ReadOnlyCollection DefaultFilePalette = - Array.AsReadOnly(new[] { - new Rgb24Color(0, 0, 255), - new Rgb24Color(255, 0, 0), - new Rgb24Color(0, 255, 0), - new Rgb24Color(0, 255, 255), - new Rgb24Color(255, 0, 255), - new Rgb24Color(255, 255, 0), - new Rgb24Color(150, 150, 255), - new Rgb24Color(255, 150, 150), - new Rgb24Color(150, 255, 150), - new Rgb24Color(150, 255, 255), - new Rgb24Color(255, 150, 255), - new Rgb24Color(255, 255, 150), - new Rgb24Color(255, 255, 255), - }); - - /// The default subtree percentage bar colors. - public static readonly ReadOnlyCollection DefaultSubtreePalette = - Array.AsReadOnly(new[] { - new Rgb24Color(64, 64, 140), - new Rgb24Color(140, 64, 64), - new Rgb24Color(64, 140, 64), - new Rgb24Color(140, 140, 64), - }); - - /*/// The default interval for updating the RAM usage. - public static readonly TimeSpan DefaultRAMInterval = TimeSpan.FromSeconds(1.0); - /// The default interval for updating the scan status. - public static readonly TimeSpan DefaultStatusInterval = TimeSpan.FromSeconds(0.05); - /// The default interval for updating the file tree in the UI. - public static readonly TimeSpan DefaultValidateInterval = TimeSpan.FromSeconds(2);*/ - - /// Resets the settings to their defaults. - public void Reset() { - // Drive Select - DriveSelectMode = DriveSelectMode.Individual; - SelectedDrives = new[] { @"C:\" }; - SelectedFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - - // CPU Usage - ScanPriority = ThreadPriority.Highest; - RenderPriority = ThreadPriority.AboveNormal; - RAMInterval = TimeSpan.FromSeconds(1.0); - StatusInterval = TimeSpan.FromSeconds(0.05); - ValidateInterval = TimeSpan.FromSeconds(1); - - // Space Display - ShowFreeSpace = false; - ShowUnknown = false; - ShowTotalSpace = false; - - // UI Display - ShowFileTypes = true; - ShowTreemap = true; - ShowToolBar = true; - ShowStatusBar = true; - IconCacheMode = IconCacheMode.Individual; - - // Treemap - TreemapOptions = TreemapOptions.Default; - HighlightColor = Rgba32Color.White; - - // File Palette - SetFilePalette(DefaultFilePalette); - - // Subtree Percentage - SetSubtreePalette(DefaultSubtreePalette); - } - } -} diff --git a/WinDirStat.Net.Base/Services/Implementation/SettingsService.cs b/WinDirStat.Net.Base/Services/Implementation/SettingsService.cs deleted file mode 100644 index e6f70ba..0000000 --- a/WinDirStat.Net.Base/Services/Implementation/SettingsService.cs +++ /dev/null @@ -1,339 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.Services { - /// The service for containing all program settings. - public partial class SettingsService : ObservableObjectEx { - - #region Fields - - /// The UI service. - private readonly IUIService ui; - /// The bitmap factory service. - private readonly IBitmapFactory bitmapFactory; - /// The treemap renderer. - private readonly TreemapRenderer treemap; - - // Drive Select - /// The default mode for selecting paths to scan. - protected DriveSelectMode driveSelectMode; - /// The selected drives from the individual list. - protected string[] selectedDrives; - /// The selected folder path. - protected string selectedFolderPath; - - // CPU Usage - /// The thread priority for scanning the file tree. - protected ThreadPriority scanPriority; - /// The thread priority for rendering the treemap. - protected ThreadPriority renderPriority; - /// How often the RAM Usage is updated. - protected TimeSpan ramInterval; - /// How often the scan status is updated. - protected TimeSpan statusInterval; - /// How often the scanned file tree is updated in the UI. - protected TimeSpan validateInterval; - - // Space Display - /// True if free space items are displayed for drives. - protected bool showFreeSpace; - /// True if unknown space items are displayed for drives. - protected bool showUnknown; - /// - /// True if space items should show one single root item instead of one for each individual drive. - /// - protected bool showTotalSpace; - - // UI Display - /// True if the file types list should be shown. - protected bool showFileTypes; - /// True if the treemap should be shown. - protected bool showTreemap; - /// True if the tool bar should be shown. - protected bool showToolBar; - /// True if the status bar should be shown. - protected bool showStatusBar; - /// The setting for how icons are cached for file tree items. - protected IconCacheMode iconCacheMode; - - // Treemap - /// The options for how the treemap is rendered. - protected TreemapOptions treemapOptions; - /// The treemap highlight color. - protected Rgba32Color highlightColor; - - // File Palette - /// The array of the original (not equalized) file palette colors. - protected Rgb24Color[] filePalette = new Rgb24Color[0]; - /// The array of the prepared (equalized) file palette colors. - protected Rgb24Color[] equalizedFilePalette = new Rgb24Color[0]; - /// The array of file palette preview images. - protected IImage[] filePalettePreviews = new IImage[0]; - - // Subtree Palette - /// The array of subtree percentage bar colors. - protected Rgb24Color[] subtreePalette = new Rgb24Color[0]; - - #endregion - - #region Constructors - - /// Constructs the . - public SettingsService(IUIService ui, - IBitmapFactory bitmapFactory, - TreemapRendererFactory treemapFactory) - { - this.ui = ui; - this.bitmapFactory = bitmapFactory; - treemap = treemapFactory.Create(); - Reset(); - } - - #endregion - - #region Drive Select - - /// Gets or sets the default mode for selecting paths to scan. - public DriveSelectMode DriveSelectMode { - get => driveSelectMode; - set => Set(ref driveSelectMode, value); - } - - /// Gets or sets the selected drives from the individual list. - public string[] SelectedDrives { - get => selectedDrives; - set { - if (value == null || value.Any(s => string.IsNullOrEmpty(s))) - throw new ArgumentNullException(nameof(SelectedDrives)); - Set(ref selectedDrives, value); - } - } - - /// Gets or sets the selected folder path. - public string SelectedFolderPath { - get => selectedFolderPath; - set => Set(ref selectedFolderPath, value); - } - - #endregion - - #region CPU Usage - - /// Gets or sets the thread priority for scanning the file tree. - public ThreadPriority ScanPriority { - get => scanPriority; - set => Set(ref scanPriority, value); - } - - /// Gets or sets the thread priority for rendering the treemap. - public ThreadPriority RenderPriority { - get => renderPriority; - set => Set(ref renderPriority, value); - } - - /// Gets or sets how often the RAM Usage is updated. - public TimeSpan RAMInterval { - get => ramInterval; - set => Set(ref ramInterval, value); - } - - /// Gets or sets how often the scan status is updated. - public TimeSpan StatusInterval { - get => statusInterval; - set => Set(ref statusInterval, value); - } - - /// Gets or sets how often the scanned file tree is updated in the UI. - public TimeSpan ValidateInterval { - get => validateInterval; - set => Set(ref validateInterval, value); - } - - #endregion - - #region Space Display - - /// Gets or sets if free space items are displayed for drives. - public bool ShowFreeSpace { - get => showFreeSpace; - set => Set(ref showFreeSpace, value); - } - - /// Gets or sets if unknown space items are displayed for drives. - public bool ShowUnknown { - get => showUnknown; - set => Set(ref showUnknown, value); - } - - /// - /// Gets or sets if space items should show one single root item instead of one for each individual - /// drive. - /// - public bool ShowTotalSpace { - get => showTotalSpace; - set => Set(ref showTotalSpace, value); - } - - #endregion - - #region UI Display - - /// Gets or sets if the file types list should be shown. - public bool ShowFileTypes { - get => showFileTypes; - set => Set(ref showFileTypes, value); - } - - /// Gets or sets if the treemap should be shown. - public bool ShowTreemap { - get => showTreemap; - set => Set(ref showTreemap, value); - } - - /// Gets or sets if the tool bar should be shown. - public bool ShowToolBar { - get => showToolBar; - set => Set(ref showToolBar, value); - } - - /// Gets or sets if the status bar should be shown. - public bool ShowStatusBar { - get => showStatusBar; - set => Set(ref showStatusBar, value); - } - - /// Gets or sets the setting for how icons are cached for file tree items. - public IconCacheMode IconCacheMode { - get => iconCacheMode; - set => Set(ref iconCacheMode, value); - } - - #endregion - - #region Treemap - - /// Gets or sets the options for how the treemap is rendered. - public TreemapOptions TreemapOptions { - get => treemapOptions; - set { - treemapOptions = value; - UpdateFilePalettePreviews(); - RaisePropertyChanged(); - } - } - - /// Gets or sets the treemap highlight color. - public Rgba32Color HighlightColor { - get => highlightColor; - set => Set(ref highlightColor, value); - } - - /// Gets the array of the prepared (equalized) file palette colors. - public ReadOnlyCollection FilePalette { - get => Array.AsReadOnly(equalizedFilePalette); - } - - /// Gets the array of the original (not equalized) file palette colors. - public ReadOnlyCollection OriginalFilePalette { - get => Array.AsReadOnly(filePalette); - } - - /// Gets the array of file palette preview images. - public ReadOnlyCollection FilePalettePreviews { - get => Array.AsReadOnly(filePalettePreviews); - } - - /// Gets the file palette color at the specified index. - /// - /// The index of the extension in the list ordered by size descending. - /// The color of the file palette. - public Rgb24Color GetFilePaletteColor(int index) { - return equalizedFilePalette[Math.Min(index, equalizedFilePalette.Length - 1)]; - } - - /// Gets the file palette color preview image at the specified index. - /// - /// The index of the extension in the list ordered by size descending. - /// The preview image of the file palette color. - public IImage GetFilePalettePreview(int index) { - return filePalettePreviews[Math.Min(index, filePalettePreviews.Length - 1)]; - } - - /// Sets the new file palette colors. - /// - /// The new collection of colors to use. - public void SetFilePalette(IEnumerable filePalette) { - this.filePalette = filePalette.ToArray(); - this.equalizedFilePalette = ColorSpace.EqualizeColors(filePalette); - UpdateFilePalettePreviews(); - RaisePropertyChanged(nameof(FilePalette)); - RaisePropertyChanged(nameof(OriginalFilePalette)); - } - - #endregion - - #region Subtree Percentage - - /// Gets the array of subtree percentage bar colors. - public ReadOnlyCollection SubtreePalette { - get => Array.AsReadOnly(subtreePalette); - } - - /// Gets the subtree percentage bar color at the specified level. - /// - /// The 0-indexed level. - /// The color of the subtree percentage bar. - public Rgb24Color GetSubtreePaletteColor(int level) { - return subtreePalette[level % subtreePalette.Length]; - } - - /// Sets the new subtree percentage bar colors. - /// - /// The new collection of colors to use. - public void SetSubtreePalette(IEnumerable subtreePalette) { - this.subtreePalette = subtreePalette.ToArray(); - RaisePropertyChanged(nameof(SubtreePalette)); - } - - #endregion - - #region Private Methods - - /// Updates the file palette previews after a change has been made to the list. - protected void UpdateFilePalettePreviews() { - if (filePalettePreviews == null) - filePalettePreviews = new IImage[filePalette.Length]; - else if (filePalette.Length != filePalettePreviews.Length) - Array.Resize(ref filePalettePreviews, filePalette.Length); - for (int i = 0; i < filePalettePreviews.Length; i++) { - DrawFilePalettePreview(ref filePalettePreviews[i], equalizedFilePalette[i]); - } - RaisePropertyChanged(nameof(FilePalettePreviews)); - } - - /// Draws a single file palette preview. - /// - /// The image reference to update. - protected void DrawFilePalettePreview(ref IImage image, Rgb24Color color) { - IWriteableBitmap bitmap = (IWriteableBitmap) image; - if (bitmap == null) { - bitmap = bitmapFactory.CreateBitmap(new Point2I(256, 13)); - image = bitmap; - } - treemap.DrawColorPreview(bitmap, new Rectangle2I(256, 13), color); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/RelayCommandService.cs b/WinDirStat.Net.Base/Services/RelayCommandService.cs deleted file mode 100644 index fb62ffc..0000000 --- a/WinDirStat.Net.Base/Services/RelayCommandService.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Services { - /// A service for creating relay commands to be loaded by the view model. - public class RelayCommandService { - - #region Abstract Create - - /// - /// Creates a new with the specified info and functions. - /// - /// - /// The abstract information about the command. - /// The execution action. - /// The optional can execute function. - /// The constructed - IRelayCommand CreateCommand(Action execute, Func canExecute = null, - bool keepTargetAlive = false); - - /// - /// Creates a new with the specified info and functions. - /// - /// - /// The parameter type of the command. - /// The abstract information about the command. - /// The execution action. - /// The optional can execute function. - /// The constructed - IRelayCommand CreateCommand(Action execute, Func canExecute = null, - bool keepTargetAlive = false); - - /// - /// Creates a new with the specified info and functions. - /// - /// - /// The abstract information about the command. - /// The execution action. - /// The optional can execute function. - /// The constructed - IRelayUICommand CreateCommand(IRelayUICommandInfo info, Action execute, Func canExecute = null, - bool keepTargetAlive = false); - - /// - /// Creates a new with the specified info and functions. - /// - /// - /// The parameter type of the command. - /// The abstract information about the command. - /// The execution action. - /// The optional can execute function. - /// The constructed - IRelayUICommand CreateCommand(IRelayUICommandInfo info, Action execute, - Func canExecute = null, bool keepTargetAlive = false); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IBrush.cs b/WinDirStat.Net.Base/Services/Structures/IBrush.cs deleted file mode 100644 index d49ba44..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IBrush.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace WinDirStat.Net.Services.Structures { - /// An interface for a UI-independent brush. - public interface IBrush { - - /// Gets the actual brush object. - object Brush { get; } - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IControl.cs b/WinDirStat.Net.Base/Services/Structures/IControl.cs deleted file mode 100644 index fcce779..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IControl.cs +++ /dev/null @@ -1,25 +0,0 @@ - -namespace WinDirStat.Net.Services.Structures { - /// An interface for storing the control. - public interface IControl { - - #region Properties - - /// Gets the actual window object. - object Control { get; } - /// Gets the window that contains this control. - IWindow Window { get; } - - #endregion - - #region Equals - - /// Gets if the two controls are referencing the same control. - /// - /// The control wrapper to compare. - /// True if the interfaces are referencing the same control. - bool Equals(IControl control); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IImage.cs b/WinDirStat.Net.Base/Services/Structures/IImage.cs deleted file mode 100644 index 9682a08..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IImage.cs +++ /dev/null @@ -1,48 +0,0 @@ -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.Services.Structures { - /// An interface for a UI-independent image. - public interface IImage { - - #region Properties - - /// Gets the actual image object. - object Source { get; } - - #endregion - } - - /// An interface for a UI-independent bitmap. - public interface IBitmap : IImage { - - #region Properties - - /// Gets the width of the bitmap. - int Width { get; } - /// Gets the height of the bitmap. - int Height { get; } - /// Gets the size of the bitmap. - Point2I Size { get; } - /// Gets the bounds of the bitmap. - Rectangle2I Bounds { get; } - - #endregion - } - - /// An interface for a UI-independent bitmap with writeable pixels. - public interface IWriteableBitmap : IBitmap { - - #region Pixels - - /// Creates a new array of pixels for populating the bitmap. - Rgba32Color[] CreatePixels(); - /// Gets the bitmap's pixels. - Rgba32Color[] GetPixels(); - /// Sets the bitmap's pixels. - void SetPixels(Rgba32Color[] pixels); - /// Sets the bitmap's pixels. - unsafe void SetPixels(Rgba32Color* pixels); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IRelayCommandInfo.Generic.cs b/WinDirStat.Net.Base/Services/Structures/IRelayCommandInfo.Generic.cs deleted file mode 100644 index ddeaffa..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IRelayCommandInfo.Generic.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Windows.Input; -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Services.Structures { - /// An interface with construction information for a . - public interface IRelayCommandInfo { - - /*#region Properties - - /// Gets an optional action to call before . - Action ExecuteBefore { get; } - /// Gets an optional action to call after . - Action ExecuteAfter { get; } - - /// Gets an optional function to call before . - Func CanExecuteBefore { get; } - /// Gets an optional function to call after . - Func CanExecuteAfter { get; } - - #endregion*/ - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IRelayCommandInfo.cs b/WinDirStat.Net.Base/Services/Structures/IRelayCommandInfo.cs deleted file mode 100644 index 32e578e..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IRelayCommandInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Windows.Input; -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Services.Structures { - /// An interface with construction information for a . - public interface IRelayCommandInfo { - - /*#region Properties - - /// Gets an optional action to call before . - Action ExecuteBefore { get; } - /// Gets an optional action to call after . - Action ExecuteAfter { get; } - - /// Gets an optional function to call before . - Func CanExecuteBefore { get; } - /// Gets an optional function to call after . - Func CanExecuteAfter { get; } - - #endregion*/ - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IRelayUICommandInfo.Generic.cs b/WinDirStat.Net.Base/Services/Structures/IRelayUICommandInfo.Generic.cs deleted file mode 100644 index 3d38b22..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IRelayUICommandInfo.Generic.cs +++ /dev/null @@ -1,14 +0,0 @@ -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Services.Structures { - /// An interface with construction information for a . - public interface IRelayUICommandInfo : IRelayCommandInfo { - - /// Gets the text to display for the command. - string Text { get; } - /// Gets the icon to display for the command. - IImage Icon { get; } - /// Gets the shortcut for the command. - IShortcut Shortcut { get; } - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IRelayUICommandInfo.cs b/WinDirStat.Net.Base/Services/Structures/IRelayUICommandInfo.cs deleted file mode 100644 index 4f7c004..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IRelayUICommandInfo.cs +++ /dev/null @@ -1,14 +0,0 @@ -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Services.Structures { - /// An interface with construction information for a . - public interface IRelayUICommandInfo : IRelayCommandInfo { - - /// Gets the text to display for the command. - string Text { get; } - /// Gets the icon to display for the command. - IImage Icon { get; } - /// Gets the shortcut for the command. - IShortcut Shortcut { get; } - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IShortcut.cs b/WinDirStat.Net.Base/Services/Structures/IShortcut.cs deleted file mode 100644 index 50d332c..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IShortcut.cs +++ /dev/null @@ -1,15 +0,0 @@ - -namespace WinDirStat.Net.Services.Structures { - /// An interface for a shortcut implementation. - public interface IShortcut { - - /// The actual shortcut object. - object Shortcut { get; } - - /// Gets the display text for the shortcut. - string DisplayText { get; } - - /// Gets the display image for the shortcut. - IImage DisplayImage { get; } - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IUITimer.cs b/WinDirStat.Net.Base/Services/Structures/IUITimer.cs deleted file mode 100644 index 61fd84c..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IUITimer.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; - -namespace WinDirStat.Net.Services.Structures { - /// An interface for a UI timer. - public interface IUITimer { - - #region Properties - - /// Gets or sets the callback method for the timer. - Action Callback { get; set; } - /// Gets or sets the interval for the timer. - TimeSpan Interval { get; set; } - /// Gets or sets if the timer is running. - bool IsRunning { get; set; } - - #endregion - - #region Start/Stop - - /// Starts the timer. - void Start(); - /// Stops the timer. - void Stop(); - /// Restarts the timer. - void Restart(); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/IWindow.cs b/WinDirStat.Net.Base/Services/Structures/IWindow.cs deleted file mode 100644 index 57dce52..0000000 --- a/WinDirStat.Net.Base/Services/Structures/IWindow.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; - -namespace WinDirStat.Net.Services.Structures { - /// An interface for storing the window. - public interface IWindow { - - #region Properties - - /// Gets the actual window object. - object Window { get; } - /// Gets the window that owns this window. - IWindow Owner { get; } - /// Gets the children owned by this window. - IWindow[] Children { get; } - /// Gets the handle for the window. - IntPtr Handle { get; } - /// Gets or sets the dialog result. - bool DialogResult { get; set; } - - #endregion - - #region Close - - /// Closes the window. - void Close(); - - /// Called when the window is closed. - event EventHandler Closed; - - #endregion - - #region Equals - - /// Gets if the two windows are referencing the same window. - /// - /// The window wrapper to compare. - /// True if the interfaces are referencing the same window. - bool Equals(IWindow window); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/Implementation/IconCache.cs b/WinDirStat.Net.Base/Services/Structures/Implementation/IconCache.cs deleted file mode 100644 index d9b4bfe..0000000 --- a/WinDirStat.Net.Base/Services/Structures/Implementation/IconCache.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.ComponentModel; - -namespace WinDirStat.Net.Services.Structures { - /// How icons are stored and displayed. - [Serializable] - public enum IconCacheMode : byte { - /// Don't show icons. - [Description("Don't show icons")] - None, - /// Use default icons (File/Folder/Drive/Computer). - [Description("Use default icons")] - Basic, - /// Use file type icons. - [Description("Use file type icons")] - FileType, - /// Use individual icons. - [Description("Individual icons")] - Individual, - /// Use individual icons with overlays. - //[Description("Individual icons with overlays")] - //IndividualOverlays, - } - - /// The states for caching an icon. - public enum IconCacheState : byte { - /// The icon has not been cached yet. - NotCached, - /// An asynchronous operation is running to cache the icon. - Caching, - /// The icon has been cached at its highest level. - Cached, - } - - /// A structure containing both a cached icon and name. - public class IIconAndName { - /// The returned icon. - public IImage Icon { get; } - /// The returned name. - public string Name { get; } - - /// Constructs a new . - /// - /// The icon to use. - /// The name to use. - public IIconAndName(IImage icon, string name) { - Icon = icon; - Name = name; - } - } - - /// The callback delegate for caching an icon. - /// - /// The returned icon. - public delegate void ICacheIconCallback(IImage icon); - /// The callback delegate for caching an icon and name. - /// - /// The returned icon and name. - public delegate void ICacheIconAndNameCallback(IIconAndName iconName); -} diff --git a/WinDirStat.Net.Base/Services/Structures/Implementation/Message.cs b/WinDirStat.Net.Base/Services/Structures/Implementation/Message.cs deleted file mode 100644 index f573308..0000000 --- a/WinDirStat.Net.Base/Services/Structures/Implementation/Message.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Services.Structures { - /// Specifies result from a dialog message box. - public enum MessageResult { - /// The message box returns no result. - None = 0, - /// The result value of the message box is OK. - OK = 1, - /// The result value of the message box is Cancel. - Cancel = 2, - /// The result value of the message box is Yes. - Yes = 6, - /// The result value of the message box is No. - No = 7, - } - - /// Specifies the buttons that are displayed on a dialog message. - public enum MessageButton { - /// The message box displays an OK button. - OK = 0, - /// The message box displays OK and Cancel buttons. - OKCancel = 1, - /// The message box displays Yes and No buttons. - YesNo = 4, - /// The message box displays Yes, No, and Cancel buttons. - YesNoCancel = 3, - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/Implementation/RecyleBinInfo.cs b/WinDirStat.Net.Base/Services/Structures/Implementation/RecyleBinInfo.cs deleted file mode 100644 index 22b4bb2..0000000 --- a/WinDirStat.Net.Base/Services/Structures/Implementation/RecyleBinInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Services.Structures { - /// Information on the contents of the Recycle Bin. - public class RecycleBinInfo { - /// Gets the owner of the Recycle Bin. May be null. - public string Owner { get; } - /// Gets the total number of items in the Recycle Bin. - public long ItemCount { get; } - /// Gets the total size of all items in the Recycle Bin. - public long Size { get; } - - /// Constructs the . - /// - /// The total number of items in the Recycle Bin. - /// The total size of items in the Recycle Bin. - public RecycleBinInfo(long itemCount, long size) { - ItemCount = itemCount; - Size = size; - } - - /// Constructs the . - /// - /// The owner of the Recycle Bin. Can be null. - /// The total number of items in the Recycle Bin. - /// The total size of items in the Recycle Bin. - public RecycleBinInfo(string owner, long itemCount, long size) { - Owner = owner; - ItemCount = itemCount; - Size = size; - } - } -} diff --git a/WinDirStat.Net.Base/Services/Structures/Implementation/Scanning.cs b/WinDirStat.Net.Base/Services/Structures/Implementation/Scanning.cs deleted file mode 100644 index 846ee0d..0000000 --- a/WinDirStat.Net.Base/Services/Structures/Implementation/Scanning.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Services.Structures { - /// The scan states for . - [Serializable] - public enum ScanState { - /// The scan has not started, or the last scan has been closed. - NotStarted, - /// A scan is currently in progress. - Scanning, - /// The current scan is suspended. - Suspended, - /// The last scan has finished and is still open. - Finished, - /// The scan is being canceled and has not ended yet. - Cancelling, - /// The last scan was cancelled. - Cancelled, - /// The last scan failed. - Failed, - } - - /// The scan progress states for . - [Serializable] - public enum ScanProgressState { - /// The scan has not started, or the last scan has been closed. - NotStarted, - /// The scan is preparing to start. - Starting, - /// The scan has fully started. - Started, - /// The scan is preparing to end. - Ending, - /// The scan has fully ended. - Ended, - } - - /// Event args for a event. - public class ScanEventArgs { - /// The current scan state. - public ScanState ScanState { get; } - /// The current scan progress state. - public ScanProgressState ProgressState { get; } - /// The exception that occurred during a failed scan. - public Exception Exception { get; } - - /// Constructs the without an exception. - public ScanEventArgs(ScanState state, ScanProgressState progress) { - ScanState = state; - ProgressState = progress; - Exception = null; - } - - /// Constructs the with an exception. - public ScanEventArgs(ScanState state, ScanProgressState progress, Exception exception) { - ScanState = state; - ProgressState = progress; - Exception = exception; - } - } - - /// Event handler for a event. - public delegate void ScanEventHander(object sender, ScanEventArgs e); -} diff --git a/WinDirStat.Net.Base/StringConstants.cs b/WinDirStat.Net.Base/StringConstants.cs deleted file mode 100644 index dcc641f..0000000 --- a/WinDirStat.Net.Base/StringConstants.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net { - public static class StringConstants { - - public const string FileName = "File"; - - public const string ComputerName = "Computer"; - public const string FileCollectionName = ""; - public const string FreeSpaceName = ""; - public const string UnknownName = ""; - } -} diff --git a/WinDirStat.Net.Base/Structures/Point2D.cs b/WinDirStat.Net.Base/Structures/Point2D.cs deleted file mode 100644 index 8e712a7..0000000 --- a/WinDirStat.Net.Base/Structures/Point2D.cs +++ /dev/null @@ -1,275 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Structures { - /// Point structure for double floating point 2D positions (X, Y). - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public struct Point2D { - - #region Constants - - /// Returns a point positioned at (0, 0). - public static readonly Point2D Zero = new Point2D(0, 0); - /// Returns a point positioned at (0.5, 0.5). - public static readonly Point2D Half = new Point2D(0.5d, 0.5d); - /// Returns a point positioned at (0.5, 0). - public static readonly Point2D HalfX = new Point2D(0.5d, 0); - /// Returns a point positioned at (0, 0.5). - public static readonly Point2D HalfY = new Point2D(0, 0.5d); - /// Returns a point positioned at (1, 1). - public static readonly Point2D One = new Point2D(1, 1); - /// Returns a point positioned at (1, 0). - public static readonly Point2D OneX = new Point2D(1, 0); - /// Returns a point positioned at (0, 1). - public static readonly Point2D OneY = new Point2D(0, 1); - - #endregion - - #region Fields - - /// X coordinate of this point. - public double X; - /// Y coordinate of this point. - public double Y; - - #endregion - - #region Constructors - - /// Constructs a from the X and Y coordinates. - /// The X coordinate to use. - /// The Y coordinate to use. - public Point2D(double x, double y) { - X = x; - Y = y; - } - - /// Constructs a from the same coordinates. - /// The X and Y coordinate to use. - public Point2D(double uniform) { - X = uniform; - Y = uniform; - } - - #endregion - - #region Static Constructors - - /// Constructs a from polar coordinates. - /// The length of the polar point. - /// The radians of the polar point. - /// The constructed . - public static Point2D FromPolarRad(double length, double radians) { - if (length == 0) - return Zero; - return new Point2D( - (double) (length * Math.Cos(radians)), - (double) (length * Math.Sin(radians))); - } - - /// Constructs a from polar coordinates. - /// The length of the polar point. - /// The degrees of the polar point. - /// The constructed . - public static Point2D FromPolarDeg(double length, double degrees) { - return FromPolarRad(length, MathUtils.DegToRad(degrees)); - } - - #endregion - - #region Object Overrides - - /// Convert to a human-readable string. - public override string ToString() => $"(X={X} Y={Y})"; - - /// Returns the hash code of this point. - public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode(); - - /// Checks if the point is equal to the other point. - public override bool Equals(object obj) { - switch (obj) { - case Point2I pt2i: return this == pt2i; - case Point2F pt2f: return this == pt2f; - case Point2D pt2d: return this == pt2d; - default: return false; - } - } - - #endregion - - #region Operators - - #region Unary Arithmetic Operators - - public static Point2D operator +(Point2D a) => a; - public static Point2D operator -(Point2D a) => new Point2D(-a.X, -a.Y); - - public static Point2D operator ++(Point2D a) => new Point2D(++a.X, ++a.Y); - public static Point2D operator --(Point2D a) => new Point2D(--a.X, --a.Y); - - #endregion - - #region Binary Arithmetic Operators - - public static Point2D operator +(Point2D a, Point2D b) => new Point2D(a.X + b.X, a.Y + b.Y); - public static Point2D operator +(Point2D a, double b) => new Point2D(a.X + b, a.Y + b ); - public static Point2D operator +(double a, Point2D b) => new Point2D(a + b.X, a + b.Y); - - public static Point2D operator -(Point2D a, Point2D b) => new Point2D(a.X - b.X, a.Y - b.Y); - public static Point2D operator -(Point2D a, double b) => new Point2D(a.X - b, a.Y - b ); - public static Point2D operator -(double a, Point2D b) => new Point2D(a - b.X, a - b.Y); - - public static Point2D operator *(Point2D a, Point2D b) => new Point2D(a.X * b.X, a.Y * b.Y); - public static Point2D operator *(Point2D a, double b) => new Point2D(a.X * b, a.Y * b ); - public static Point2D operator *(double a, Point2D b) => new Point2D(a * b.X, a * b.Y); - - public static Point2D operator /(Point2D a, Point2D b) => new Point2D(a.X / b.X, a.Y / b.Y); - public static Point2D operator /(Point2D a, double b) => new Point2D(a.X / b, a.Y / b ); - public static Point2D operator /(double a, Point2D b) => new Point2D(a / b.X, a / b.Y); - - public static Point2D operator %(Point2D a, Point2D b) => new Point2D(a.X % b.X, a.Y % b.Y); - public static Point2D operator %(Point2D a, double b) => new Point2D(a.X % b, a.Y % b ); - public static Point2D operator %(double a, Point2D b) => new Point2D(a % b.X, a % b.Y); - - #endregion - - #region Binary Logic Operators - - public static bool operator ==(Point2D a, Point2D b) => (a.X == b.X && a.Y == b.Y); - public static bool operator ==(Point2D a, double b) => (a.X == b && a.Y == b ); - public static bool operator ==(double a, Point2D b) => (a == b.X && a == b.Y); - - public static bool operator !=(Point2D a, Point2D b) => (a.X != b.X || a.Y != b.Y); - public static bool operator !=(Point2D a, double b) => (a.X != b || a.Y != b ); - public static bool operator !=(double a, Point2D b) => (a != b.X || a != b.Y); - - public static bool operator <(Point2D a, Point2D b) => (a.X < b.X && a.Y < b.Y); - public static bool operator <(Point2D a, double b) => (a.X < b && a.Y < b ); - public static bool operator <(double a, Point2D b) => (a < b.X && a < b.Y); - - public static bool operator >(Point2D a, Point2D b) => (a.X > b.X && a.Y > b.Y); - public static bool operator >(Point2D a, double b) => (a.X > b && a.Y > b ); - public static bool operator >(double a, Point2D b) => (a > b.X && a > b.Y); - - public static bool operator <=(Point2D a, Point2D b) => (a.X <= b.X && a.Y <= b.Y); - public static bool operator <=(Point2D a, double b) => (a.X <= b && a.Y <= b ); - public static bool operator <=(double a, Point2D b) => (a <= b.X && a <= b.Y); - - public static bool operator >=(Point2D a, Point2D b) => (a.X >= b.X && a.Y >= b.Y); - public static bool operator >=(Point2D a, double b) => (a.X >= b && a.Y >= b ); - public static bool operator >=(double a, Point2D b) => (a >= b.X && a >= b.Y); - - #endregion - - #endregion - - #region Casting - - /// Casts the to a . - public static implicit operator Point2D(Point2I point) { - return new Point2D(point.X, point.Y); - } - - /// Casts the to a . - public static implicit operator Point2D(Point2F point) { - return new Point2D(point.X, point.Y); - } - - /// Casts the to a . - public static explicit operator Point2I(Point2D point) { - return new Point2I((int) point.X, (int) point.Y); - } - - /// Casts the to a . - public static explicit operator Point2F(Point2D point) { - return new Point2F((float) point.X, (float) point.Y); - } - - #endregion - - #region Properties - - /// Gets or sets the direction of the point in degrees. - public double DirectionDeg { - get { - if (IsZero) - return 0; - return (double) MathUtils.RadToDeg(Math.Atan2(Y, X)); - } - set { - if (!IsZero) { - double length = Length; - X = (double) (length * Math.Cos(value)); - Y = (double) (length * Math.Sin(value)); - } - } - } - - /// Gets or sets the direction of the point in radians. - public double DirectionRad { - get { - if (IsZero) - return 0; - return (double) Math.Atan2(Y, X); - } - set { - if (!IsZero) { - double radians = MathUtils.DegToRad(value); - double length = Length; - X = (double) (length * Math.Cos(radians)); - Y = (double) (length * Math.Sin(radians)); - } - } - } - - /// Gets or sets the length of the point. - public double Length { - get => (double) Math.Sqrt((X * X) + (Y * Y)); - set { - if (!IsZero) { - double oldLength = Length; - X *= value / oldLength; - Y *= value / oldLength; - } - else { - X = value; - Y = 0; - } - } - } - - /// Gets the squared length of the point. - public double LengthSquared => ((X * X) + (Y * Y)); - - /// Gets the coordinate at the specified index. - public double this[int index] { - get { - switch (index) { - case 0: return X; - case 1: return Y; - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - set { - switch (index) { - case 0: X = value; return; - case 1: Y = value; return; - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - } - - /// Returns true if the point is positioned at (0, 0). - public bool IsZero => (X == 0 && Y == 0); - - /// Returns true if either X or Y is positioned at 0. - public bool IsAnyZero => (X == 0 || Y == 0); - - /// Returns the perpendicular point. - public Point2D Perpendicular => new Point2D(-Y, X); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Structures/Point2F.cs b/WinDirStat.Net.Base/Structures/Point2F.cs deleted file mode 100644 index 0b89c06..0000000 --- a/WinDirStat.Net.Base/Structures/Point2F.cs +++ /dev/null @@ -1,265 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Structures { - /// Point structure for floating point 2D positions (X, Y). - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public struct Point2F { - - #region Constants - - /// Returns a point positioned at (0, 0). - public static readonly Point2F Zero = new Point2F(0, 0); - /// Returns a point positioned at (0.5, 0.5). - public static readonly Point2F Half = new Point2F(0.5f, 0.5f); - /// Returns a point positioned at (0.5, 0). - public static readonly Point2F HalfX = new Point2F(0.5f, 0); - /// Returns a point positioned at (0, 0.5). - public static readonly Point2F HalfY = new Point2F(0, 0.5f); - /// Returns a point positioned at (1, 1). - public static readonly Point2F One = new Point2F(1, 1); - /// Returns a point positioned at (1, 0). - public static readonly Point2F OneX = new Point2F(1, 0); - /// Returns a point positioned at (0, 1). - public static readonly Point2F OneY = new Point2F(0, 1); - - #endregion - - #region Fields - - /// X coordinate of this point. - public float X; - /// Y coordinate of this point. - public float Y; - - #endregion - - #region Constructors - - /// Constructs a from the X and Y coordinates. - /// The X coordinate to use. - /// The Y coordinate to use. - public Point2F(float x, float y) { - X = x; - Y = y; - } - - /// Constructs a from the same coordinates. - /// The X and Y coordinate to use. - public Point2F(float uniform) { - X = uniform; - Y = uniform; - } - - #endregion - - #region Static Constructors - - /// Constructs a from polar coordinates. - /// The length of the polar point. - /// The radians of the polar point. - /// The constructed . - public static Point2F FromPolarRad(float length, float radians) { - if (length == 0) - return Zero; - return new Point2F( - (float) (length * Math.Cos(radians)), - (float) (length * Math.Sin(radians))); - } - - /// Constructs a from polar coordinates. - /// The length of the polar point. - /// The degrees of the polar point. - /// The constructed . - public static Point2F FromPolarDeg(float length, float degrees) { - return FromPolarRad(length, MathUtils.DegToRad(degrees)); - } - - #endregion - - #region Object Overrides - - /// Convert to a human-readable string. - public override string ToString() => $"(X={X} Y={Y})"; - - /// Returns the hash code of this point. - public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode(); - - /// Checks if the point is equal to the other point. - public override bool Equals(object obj) { - switch (obj) { - case Point2I pt2i: return this == pt2i; - case Point2F pt2f: return this == pt2f; - case Point2D pt2d: return this == pt2d; - default: return false; - } - } - - #endregion - - #region Operators - - #region Unary Arithmetic Operators - - public static Point2F operator +(Point2F a) => a; - public static Point2F operator -(Point2F a) => new Point2F(-a.X, -a.Y); - - public static Point2F operator ++(Point2F a) => new Point2F(++a.X, ++a.Y); - public static Point2F operator --(Point2F a) => new Point2F(--a.X, --a.Y); - - #endregion - - #region Binary Arithmetic Operators - - public static Point2F operator +(Point2F a, Point2F b) => new Point2F(a.X + b.X, a.Y + b.Y); - public static Point2F operator +(Point2F a, float b) => new Point2F(a.X + b, a.Y + b ); - public static Point2F operator +(float a, Point2F b) => new Point2F(a + b.X, a + b.Y); - - public static Point2F operator -(Point2F a, Point2F b) => new Point2F(a.X - b.X, a.Y - b.Y); - public static Point2F operator -(Point2F a, float b) => new Point2F(a.X - b, a.Y - b ); - public static Point2F operator -(float a, Point2F b) => new Point2F(a - b.X, a - b.Y); - - public static Point2F operator *(Point2F a, Point2F b) => new Point2F(a.X * b.X, a.Y * b.Y); - public static Point2F operator *(Point2F a, float b) => new Point2F(a.X * b, a.Y * b ); - public static Point2F operator *(float a, Point2F b) => new Point2F(a * b.X, a * b.Y); - - public static Point2F operator /(Point2F a, Point2F b) => new Point2F(a.X / b.X, a.Y / b.Y); - public static Point2F operator /(Point2F a, float b) => new Point2F(a.X / b, a.Y / b ); - public static Point2F operator /(float a, Point2F b) => new Point2F(a / b.X, a / b.Y); - - public static Point2F operator %(Point2F a, Point2F b) => new Point2F(a.X % b.X, a.Y % b.Y); - public static Point2F operator %(Point2F a, float b) => new Point2F(a.X % b, a.Y % b ); - public static Point2F operator %(float a, Point2F b) => new Point2F(a % b.X, a % b.Y); - - #endregion - - #region Binary Logic Operators - - public static bool operator ==(Point2F a, Point2F b) => (a.X == b.X && a.Y == b.Y); - public static bool operator ==(Point2F a, float b) => (a.X == b && a.Y == b ); - public static bool operator ==(float a, Point2F b) => (a == b.X && a == b.Y); - - public static bool operator !=(Point2F a, Point2F b) => (a.X != b.X || a.Y != b.Y); - public static bool operator !=(Point2F a, float b) => (a.X != b || a.Y != b ); - public static bool operator !=(float a, Point2F b) => (a != b.X || a != b.Y); - - public static bool operator <(Point2F a, Point2F b) => (a.X < b.X && a.Y < b.Y); - public static bool operator <(Point2F a, float b) => (a.X < b && a.Y < b ); - public static bool operator <(float a, Point2F b) => (a < b.X && a < b.Y); - - public static bool operator >(Point2F a, Point2F b) => (a.X > b.X && a.Y > b.Y); - public static bool operator >(Point2F a, float b) => (a.X > b && a.Y > b ); - public static bool operator >(float a, Point2F b) => (a > b.X && a > b.Y); - - public static bool operator <=(Point2F a, Point2F b) => (a.X <= b.X && a.Y <= b.Y); - public static bool operator <=(Point2F a, float b) => (a.X <= b && a.Y <= b ); - public static bool operator <=(float a, Point2F b) => (a <= b.X && a <= b.Y); - - public static bool operator >=(Point2F a, Point2F b) => (a.X >= b.X && a.Y >= b.Y); - public static bool operator >=(Point2F a, float b) => (a.X >= b && a.Y >= b ); - public static bool operator >=(float a, Point2F b) => (a >= b.X && a >= b.Y); - - #endregion - - #endregion - - #region Casting - - /// Casts the to a . - public static implicit operator Point2F(Point2I point) { - return new Point2F(point.X, point.Y); - } - - /// Casts the to a . - public static explicit operator Point2I(Point2F point) { - return new Point2I((int) point.X, (int) point.Y); - } - - #endregion - - #region Properties - - /// Gets or sets the direction of the point in degrees. - public float DirectionDeg { - get { - if (IsZero) - return 0; - return (float) MathUtils.RadToDeg(Math.Atan2(Y, X)); - } - set { - if (!IsZero) { - float length = Length; - X = (float) (length * Math.Cos(value)); - Y = (float) (length * Math.Sin(value)); - } - } - } - - /// Gets or sets the direction of the point in radians. - public float DirectionRad { - get { - if (IsZero) - return 0; - return (float) Math.Atan2(Y, X); - } - set { - if (!IsZero) { - double radians = MathUtils.DegToRad(value); - float length = Length; - X = (float) (length * Math.Cos(radians)); - Y = (float) (length * Math.Sin(radians)); - } - } - } - - /// Gets or sets the length of the point. - public float Length { - get => (float) Math.Sqrt((X * X) + (Y * Y)); - set { - if (!IsZero) { - float oldLength = Length; - X *= value / oldLength; - Y *= value / oldLength; - } - else { - X = value; - Y = 0; - } - } - } - - /// Gets the squared length of the point. - public float LengthSquared => ((X * X) + (Y * Y)); - - /// Gets the coordinate at the specified index. - public float this[int index] { - get { - switch (index) { - case 0: return X; - case 1: return Y; - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - set { - switch (index) { - case 0: X = value; return; - case 1: Y = value; return; - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - } - - /// Returns true if the point is positioned at (0, 0). - public bool IsZero => (X == 0 && Y == 0); - - /// Returns true if either X or Y is positioned at 0. - public bool IsAnyZero => (X == 0 || Y == 0); - - /// Returns the perpendicular point. - public Point2F Perpendicular => new Point2F(-Y, X); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Structures/Point2I.cs b/WinDirStat.Net.Base/Structures/Point2I.cs deleted file mode 100644 index 248bb1d..0000000 --- a/WinDirStat.Net.Base/Structures/Point2I.cs +++ /dev/null @@ -1,168 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace WinDirStat.Net.Structures { - /// Point structure for integer 2D positions (X, Y). - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public struct Point2I { - - #region Constants - - /// Returns a point positioned at (0, 0). - public static readonly Point2I Zero = new Point2I(0, 0); - /// Returns a point positioned at (1, 1). - public static readonly Point2I One = new Point2I(1, 1); - /// Returns a point positioned at (1, 0). - public static readonly Point2I OneX = new Point2I(1, 0); - /// Returns a point positioned at (0, 1). - public static readonly Point2I OneY = new Point2I(0, 1); - - #endregion - - #region Fields - - /// X coordinate of this point. - public int X; - /// Y coordinate of this point. - public int Y; - - #endregion - - #region Constructors - - /// Constructs a from the X and Y coordinates. - /// The X coordinate to use. - /// The Y coordinate to use. - public Point2I(int x, int y) { - X = x; - Y = y; - } - - /// Constructs a from the same coordinates. - /// The X and Y coordinate to use. - public Point2I(int uniform) { - X = uniform; - Y = uniform; - } - - #endregion - - #region Object Overrides - - /// Convert to a human-readable string. - public override string ToString() => $"(X={X} Y={Y})"; - - /// Returns the hash code of this point. - public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode(); - - /// Checks if the point is equal to the other point. - public override bool Equals(object obj) { - switch (obj) { - case Point2I pt2i: return this == pt2i; - case Point2F pt2f: return this == pt2f; - case Point2D pt2d: return this == pt2d; - default: return false; - } - } - - #endregion - - #region Operators - - #region Unary Arithmetic Operators - - public static Point2I operator +(Point2I a) => a; - public static Point2I operator -(Point2I a) => new Point2I(-a.X, -a.Y); - - public static Point2I operator ++(Point2I a) => new Point2I(++a.X, ++a.Y); - public static Point2I operator --(Point2I a) => new Point2I(--a.X, --a.Y); - - #endregion - - #region Binary Arithmetic Operators - - public static Point2I operator +(Point2I a, Point2I b) => new Point2I(a.X + b.X, a.Y + b.Y); - public static Point2I operator +(Point2I a, int b) => new Point2I(a.X + b, a.Y + b ); - public static Point2I operator +(int a, Point2I b) => new Point2I(a + b.X, a + b.Y); - - public static Point2I operator -(Point2I a, Point2I b) => new Point2I(a.X - b.X, a.Y - b.Y); - public static Point2I operator -(Point2I a, int b) => new Point2I(a.X - b, a.Y - b ); - public static Point2I operator -(int a, Point2I b) => new Point2I(a - b.X, a - b.Y); - - public static Point2I operator *(Point2I a, Point2I b) => new Point2I(a.X * b.X, a.Y * b.Y); - public static Point2I operator *(Point2I a, int b) => new Point2I(a.X * b, a.Y * b ); - public static Point2I operator *(int a, Point2I b) => new Point2I(a * b.X, a * b.Y); - - public static Point2I operator /(Point2I a, Point2I b) => new Point2I(a.X / b.X, a.Y / b.Y); - public static Point2I operator /(Point2I a, int b) => new Point2I(a.X / b, a.Y / b ); - public static Point2I operator /(int a, Point2I b) => new Point2I(a / b.X, a / b.Y); - - public static Point2I operator %(Point2I a, Point2I b) => new Point2I(a.X % b.X, a.Y % b.Y); - public static Point2I operator %(Point2I a, int b) => new Point2I(a.X % b, a.Y % b ); - public static Point2I operator %(int a, Point2I b) => new Point2I(a % b.X, a % b.Y); - - #endregion - - #region Binary Logic Operators - - public static bool operator ==(Point2I a, Point2I b) => (a.X == b.X && a.Y == b.Y); - public static bool operator ==(Point2I a, int b) => (a.X == b && a.Y == b ); - public static bool operator ==(int a, Point2I b) => (a == b.X && a == b.Y); - - public static bool operator !=(Point2I a, Point2I b) => (a.X != b.X || a.Y != b.Y); - public static bool operator !=(Point2I a, int b) => (a.X != b || a.Y != b ); - public static bool operator !=(int a, Point2I b) => (a != b.X || a != b.Y); - - public static bool operator <(Point2I a, Point2I b) => (a.X < b.X && a.Y < b.Y); - public static bool operator <(Point2I a, int b) => (a.X < b && a.Y < b ); - public static bool operator <(int a, Point2I b) => (a < b.X && a < b.Y); - - public static bool operator >(Point2I a, Point2I b) => (a.X > b.X && a.Y > b.Y); - public static bool operator >(Point2I a, int b) => (a.X > b && a.Y > b ); - public static bool operator >(int a, Point2I b) => (a > b.X && a > b.Y); - - public static bool operator <=(Point2I a, Point2I b) => (a.X <= b.X && a.Y <= b.Y); - public static bool operator <=(Point2I a, int b) => (a.X <= b && a.Y <= b ); - public static bool operator <=(int a, Point2I b) => (a <= b.X && a <= b.Y); - - public static bool operator >=(Point2I a, Point2I b) => (a.X >= b.X && a.Y >= b.Y); - public static bool operator >=(Point2I a, int b) => (a.X >= b && a.Y >= b ); - public static bool operator >=(int a, Point2I b) => (a >= b.X && a >= b.Y); - - #endregion - - #endregion - - #region Properties - - /// Gets the coordinate at the specified index. - public int this[int index] { - get { - switch (index) { - case 0: return X; - case 1: return Y; - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - set { - switch (index) { - case 0: X = value; return; - case 1: Y = value; return; - default: throw new ArgumentOutOfRangeException(nameof(index)); - } - } - } - - /// Returns true if the point is positioned at (0, 0). - public bool IsZero => (X == 0 && Y == 0); - - /// Returns true if either X or Y is positioned at 0. - public bool IsAnyZero => (X == 0 || Y == 0); - - /// Returns the perpendicular point. - public Point2I Perpendicular => new Point2I(-Y, X); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Structures/Rectangle2I.cs b/WinDirStat.Net.Base/Structures/Rectangle2I.cs deleted file mode 100644 index 14fc3d7..0000000 --- a/WinDirStat.Net.Base/Structures/Rectangle2I.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace WinDirStat.Net.Structures { - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public struct Rectangle2I { - - #region Constants - - /// Returns a rectangle positioned at (0, 0) with a size of (0, 0). - public static readonly Rectangle2I Empty = new Rectangle2I(0, 0, 0, 0); - /// Returns a rectangle positioned at (0, 0) with a size of (1, 1). - public static readonly Rectangle2I One = new Rectangle2I(0, 0, 1, 1); - /// Returns a rectangle positioned at (-1, -1) with a size of (0, 0). - public static readonly Rectangle2I Invalid = new Rectangle2I(-1, -1, 0, 0); - - #endregion - - #region Fields - - /// X coordinate of this rectangle. - public int X; - /// Y coordinate of this rectangle. - public int Y; - /// Width of this rectangle. - public int Width; - /// Height of this rectangle. - public int Height; - - #endregion - - #region Constructors - - public Rectangle2I(int width, int height) { - X = 0; - Y = 0; - Width = width; - Height = height; - } - - public Rectangle2I(int x, int y, int width, int height) { - X = x; - Y = y; - Width = width; - Height = height; - } - - public Rectangle2I(Point2I size) { - X = 0; - Y = 0; - Width = size.X; - Height = size.Y; - } - - public Rectangle2I(Point2I point, Point2I size) { - X = point.X; - Y = point.Y; - Width = size.X; - Height = size.Y; - } - - #endregion - - #region Static Constructors - - public static Rectangle2I FromLTRB(int left, int top, int right, int bottom) { - return new Rectangle2I(left, top, right - left, bottom - top); - } - - #endregion - - #region Properties - - public int Left { - get => X; - set { - // Keep the right position - Width += X - value; - X = value; - } - } - - public int Top { - get => Y; - set { - // Keep the right position - Height += Y - value; - Y = value; - } - } - - public int Right { - get => X + Width; - set => Width = value - X; - } - - public int Bottom { - get => Y + Height; - set => Height = value - Y; - } - - #endregion - - #region Casting - - public static implicit operator Rectangle2I(Rectangle2S rect) { - return new Rectangle2I( - (rect.X == ushort.MaxValue ? -1 : rect.X), - (rect.Y == ushort.MaxValue ? -1 : rect.Y), - rect.Width, - rect.Height); - } - - public static explicit operator Rectangle2S(Rectangle2I rect) { - return new Rectangle2S(rect.X, rect.Y, rect.Width, rect.Height); - } - - #endregion - - #region Accessors - - public bool Contains(int x, int y) { - return Contains(new Point2I(x, y)); - } - - public bool Contains(Point2I point) { - return (point.X >= Left && point.X <= Right && - point.Y >= Top && point.Y <= Bottom); - } - - #endregion - - #region Mutators - - public void Inflate(int x, int y) { - X -= x; - Y -= y; - Width += x * 2; - Height += y * 2; - } - - public void Deflate(int x, int y) { - X += x; - Y += y; - Width -= x * 2; - Height -= y * 2; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Structures/Rectangle2S.cs b/WinDirStat.Net.Base/Structures/Rectangle2S.cs deleted file mode 100644 index 843af83..0000000 --- a/WinDirStat.Net.Base/Structures/Rectangle2S.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace WinDirStat.Net.Structures { - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public struct Rectangle2S { - - #region Constants - - /// Returns a rectangle positioned at (0, 0) with a size of (0, 0). - public static readonly Rectangle2S Empty = new Rectangle2S(0, 0, 0, 0); - /// Returns a rectangle positioned at (0, 0) with a size of (1, 1). - public static readonly Rectangle2S One = new Rectangle2S(0, 0, 1, 1); - /// - /// Returns a rectangle positioned at (, ) - /// with a size of (0, 0). - /// - public static readonly Rectangle2S Invalid = new Rectangle2S(ushort.MaxValue, ushort.MaxValue, 0, 0); - - #endregion - - #region Fields - - /// X coordinate of this rectangle. - public ushort X; - /// Y coordinate of this rectangle. - public ushort Y; - /// Width of this rectangle. - public ushort Width; - /// Height of this rectangle. - public ushort Height; - - #endregion - - #region Constructors - - public Rectangle2S(int width, int height) { - X = 0; - Y = 0; - Width = (ushort) width; - Height = (ushort) height; - } - - public Rectangle2S(int x, int y, int width, int height) { - X = (ushort) (x == -1 ? ushort.MaxValue : x); - Y = (ushort) (y == -1 ? ushort.MaxValue : y); - Width = (ushort) width; - Height = (ushort) height; - } - - public Rectangle2S(Point2I size) { - X = 0; - Y = 0; - Width = (ushort) size.X; - Height = (ushort) size.Y; - } - - public Rectangle2S(Point2I point, Point2I size) { - X = (ushort) (point.X == -1 ? ushort.MaxValue : point.X); - Y = (ushort) (point.Y == -1 ? ushort.MaxValue : point.Y); - Width = (ushort) size.X; - Height = (ushort) size.Y; - } - - #endregion - - #region Static Constructors - - public static Rectangle2S FromLTRB(int left, int top, int right, int bottom) { - return new Rectangle2S(left, top, right - left, bottom - top); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Structures/Rgb24Color.cs b/WinDirStat.Net.Base/Structures/Rgb24Color.cs deleted file mode 100644 index caf84c1..0000000 --- a/WinDirStat.Net.Base/Structures/Rgb24Color.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace WinDirStat.Net.Structures { - /// An unmanaged 24-bit RGB color. - [Serializable] - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct Rgb24Color { - - #region Constants - - public static readonly Rgb24Color Black = new Rgb24Color(0, 0, 0); - public static readonly Rgb24Color White = new Rgb24Color(255, 255, 255); - - #endregion - - #region Fields - - /// The blue channel for the color. - public byte B; - /// The green channel for the color. - public byte G; - /// The red channel for the color. - public byte R; - - #endregion - - #region Constructors - - /// Constructs the . - /// The red channel. - /// The green channel. - /// The blue channel. - public Rgb24Color(int red, int green, int blue) { - R = (byte) red; - G = (byte) green; - B = (byte) blue; - } - - #endregion - - #region Properties - - public int PackedValue { - get => (B << 16) | (G << 8) | R; - set { - B = (byte) ((value >> 16) & 0xFF); - G = (byte) ((value >> 8) & 0xFF); - R = (byte) ((value) & 0xFF); - } - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Structures/Rgba32Color.cs b/WinDirStat.Net.Base/Structures/Rgba32Color.cs deleted file mode 100644 index 9f7fe5f..0000000 --- a/WinDirStat.Net.Base/Structures/Rgba32Color.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Structures { - /// An unmanaged 32-bit RGBA color. - [Serializable] - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct Rgba32Color { - - #region Constants - - public static readonly Rgba32Color Transparent = new Rgba32Color(0, 0, 0, 0); - public static readonly Rgba32Color Black = new Rgba32Color(0, 0, 0); - public static readonly Rgba32Color White = new Rgba32Color(255, 255, 255); - - #endregion - - #region Fields - - /// The blue channel for the color. - public byte B; - /// The green channel for the color. - public byte G; - /// The red channel for the color. - public byte R; - /// The alpha channel for the color. - public byte A; - - #endregion - - #region Constructors - - /// Constructs the with an alpha of 255. - /// The red channel. - /// The green channel. - /// The blue channel. - public Rgba32Color(int red, int green, int blue) { - R = (byte) red; - G = (byte) green; - B = (byte) blue; - A = byte.MaxValue; - } - - /// Constructs the .The red channel. - /// The green channel. - /// The blue channel. - /// The alpha channel. - public Rgba32Color(int red, int green, int blue, int alpha) { - R = (byte) red; - G = (byte) green; - B = (byte) blue; - A = (byte) alpha; - } - - /// Constructs the (0.0-1.0) with an alpha of 1.0. - /// The red channel. - /// The green channel. - /// The blue channel. - public Rgba32Color(float red, float green, float blue) { - R = (byte) MathUtils.Round(red * 255); - G = (byte) MathUtils.Round(green * 255); - B = (byte) MathUtils.Round(blue * 255); - A = byte.MaxValue; - } - - /// Constructs the (0.0-1.0) . - /// The red channel. - /// The green channel. - /// The blue channel. - /// The alpha channel. - public Rgba32Color(float red, float green, float blue, float alpha) { - R = (byte) MathUtils.Round(red * 255); - G = (byte) MathUtils.Round(green * 255); - B = (byte) MathUtils.Round(blue * 255); - A = (byte) MathUtils.Round(alpha * 255); - } - - /// Constructs the (0.0-1.0) with an alpha of 1.0. - /// The red channel. - /// The green channel. - /// The blue channel. - public Rgba32Color(double red, double green, double blue) { - R = (byte) MathUtils.Round(red * 255); - G = (byte) MathUtils.Round(green * 255); - B = (byte) MathUtils.Round(blue * 255); - A = byte.MaxValue; - } - - /// Constructs the (0.0-1.0) . - /// The red channel. - /// The green channel. - /// The blue channel. - /// The alpha channel. - public Rgba32Color(double red, double green, double blue, double alpha) { - R = (byte) MathUtils.Round(red * 255); - G = (byte) MathUtils.Round(green * 255); - B = (byte) MathUtils.Round(blue * 255); - A = (byte) MathUtils.Round(alpha * 255); - } - - /// Constructs the packed value . - /// The packed value. - public Rgba32Color(int rgba) { - B = (byte) ((rgba >> 24) & 0xFF); - G = (byte) ((rgba >> 16) & 0xFF); - R = (byte) ((rgba >> 8) & 0xFF); - A = (byte) ((rgba) & 0xFF); - } - - #endregion - - #region Properties - - public int PackedValue { - get => (B << 24) | (G << 16) | (R << 8) | A; - set { - B = (byte) ((value >> 24) & 0xFF); - G = (byte) ((value >> 16) & 0xFF); - R = (byte) ((value >> 8) & 0xFF); - A = (byte) ((value) & 0xFF); - } - } - - #endregion - - #region Casting - - /// Casts the to an . - public static explicit operator Rgb24Color(Rgba32Color color) { - return new Rgb24Color(color.R, color.G, color.B); - } - - /// Casts the to a . - public static implicit operator Rgba32Color(Rgb24Color color) { - return new Rgba32Color(color.R, color.G, color.B); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/ArrayExtensions.cs b/WinDirStat.Net.Base/Utils/ArrayExtensions.cs deleted file mode 100644 index c6296d6..0000000 --- a/WinDirStat.Net.Base/Utils/ArrayExtensions.cs +++ /dev/null @@ -1,598 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; - -namespace WinDirStat.Net.Utils { - /// How to handle BlockCast when the array byte sizes do not align. - public enum BlockCastAlign { - /// Throw an exception due to unalignment. - Error = 0, - /// Oversize the new array by one element. - Oversize, - /// Undersize the new array by one element. - Undersize, - } - - /// Extensions for 1-dimensional objects. - public static class ArrayExtensions { - - #region Memset (Single) - - /// Populates the entire array with the specified value. - /// The array to fill. - /// The value to populate the array with. - /// Returns the same array that was populated. - /// Created by TowerOfBricks: - /// - /// - /// Modified version of Memset created by TowerOfBricks: Source - /// - public static void Memset(this Array array, object value) { - Memset(array, value, 0, array.Length); - } - - /// - /// Populates the specified section of the array with the specified value. - /// - /// - /// The array to fill. - /// The value to populate the array with. - /// The index to start populating the array at. - /// The number of elements to populate the array with. - /// Returns the same array that was populated. - /// - /// - /// Modified version of Memset created by TowerOfBricks: Source - /// - /// - /// or is less than zero. - /// - public static void Memset(this Array array, object value, int startIndex, - int length) - { - if (length < 0) - throw new ArgumentOutOfRangeException(nameof(length), - $"{nameof(length)} '{length}' is less than zero!"); - - int block = Math.Min(32, length); - int index = startIndex; - int end = startIndex + block; - - while (index < end) - array.SetValue(value, index++); - - end = startIndex + length; - while (index < end) { - Array.Copy(array, startIndex, array, index, Math.Min(block, end - index)); - index += block; - block *= 2; - } - } - - /// Populates the entire array with the specified value. - /// The element type of the array. - /// The array to fill. - /// The value to populate the array with. - /// Returns the same array that was populated. - /// - /// - /// Modified version of Memset created by TowerOfBricks: Source - /// - public static void Memset(this T[] array, T value) { - Memset(array, value, 0, array.Length); - } - - /// - /// Populates the specified section of the array with the specified value. - /// - /// - /// The element type of the array. - /// The array to fill. - /// The value to populate the array with. - /// The index to start populating the array at. - /// The number of elements to populate the array with. - /// Returns the same array that was populated. - /// - /// - /// Modified version of Memset created by TowerOfBricks: Source - /// - /// - /// or is less than zero. - /// - public static void Memset(this T[] array, T value, int startIndex, - int length) - { - if (length < 0) - throw new ArgumentOutOfRangeException(nameof(length), - $"{nameof(length)} '{length}' is less than zero!"); - - int block = Math.Min(32, length); - int index = startIndex; - int end = startIndex + block; - - while (index < end) - array[index++] = value; - - end = startIndex + length; - while (index < end) { - Array.Copy(array, startIndex, array, index, Math.Min(block, end - index)); - index += block; - block *= 2; - } - } - - #endregion - - #region Memset (Multiple) - - /// Populates the entire array with the specified repeating values. - /// The array to fill. - /// The ordered values to repeatedly populate the array with. - /// Returns the same array that was populated. - /// - /// - /// Modified version of Memset created by TowerOfBricks: Source - /// - /// - /// has a length of zero. - /// - /// is null. - public static void Memset(this Array array, Array values) { - array.Memset(values, 0, array.Length); - } - - /// - /// Populates the specified section of the array with the specified repeating values. - /// - /// - /// The array to fill. - /// The ordered values to repeatedly populate the array with. - /// The index to start populating the array at. - /// The number of single elements to populate the array with. - /// Returns the same array that was populated. - /// - /// - /// Modified version of Memset created by TowerOfBricks: Source - /// - /// - /// or is less than zero. - /// - /// - /// has a length of zero. - /// - /// is null. - public static void Memset(this Array array, Array values, int startIndex, - int length) - { - if (length < 0) - throw new ArgumentOutOfRangeException(nameof(length), - $"{nameof(length)} '{length}' is less than zero!"); - else if (values == null) - throw new ArgumentNullException(nameof(values)); - else if (values.Length == 0) - throw new ArgumentException($"{nameof(values)} has a length of zero!", - nameof(values)); - - // Make sure the starting block is divisible by the number of values. - int block = Math.Max(values.Length, (32 / values.Length) * values.Length); - int index = startIndex; - int end = startIndex + block; - - for (int i = 0; i < block; i++) - array.SetValue(values.GetValue(i), index++); - - end = startIndex + length; - while (index < end) { - Array.Copy(array, 0, array, index, Math.Min(block, end - index)); - index += block; - block *= 2; - } - } - - /// Populates the entire array with the specified repeating values. - /// The element type of the array. - /// The array to fill. - /// The ordered values to repeatedly populate the array with. - /// Returns the same array that was populated. - /// - /// - /// Modified version of Memset created by TowerOfBricks: Source - /// - /// - /// has a length of zero. - /// - /// is null. - public static void Memset(this T[] array, params T[] values) { - array.Memset(values, 0, array.Length); - } - - /// - /// Populates the specified section of the array with the specified repeating values. - /// - /// - /// The element type of the array. - /// The array to fill. - /// The ordered values to repeatedly populate the array with. - /// The index to start populating the array at. - /// The number of single elements to populate the array with. - /// Returns the same array that was populated. - /// - /// - /// Modified version of Memset created by TowerOfBricks: Source - /// - /// - /// or is less than zero. - /// - /// has a length of zero. - /// - /// is null. - public static void Memset(this T[] array, T[] values, int startIndex, - int length) - { - if (length < 0) - throw new ArgumentOutOfRangeException(nameof(length), - $"{nameof(length)} '{length}' is less than zero!"); - else if (values == null) - throw new ArgumentNullException(nameof(values)); - else if (values.Length == 0) - throw new ArgumentException($"{nameof(values)} has a length of zero!", - nameof(values)); - - // Make sure the starting block is divisible by the number of values. - int block = Math.Max(values.Length, (32 / values.Length) * values.Length); - int index = startIndex; - int end = startIndex + block; - - for (int i = 0; i < block; i++) - array[index++] = values[i]; - - end = startIndex + length; - while (index < end) { - Array.Copy(array, 0, array, index, Math.Min(block, end - index)); - index += block; - block *= 2; - } - } - - #endregion - - #region Contains - - /// Returns true if the array contains the specified value. - /// The array to check for containment. - /// The value to check for. - /// Returns true if the array contains the specified value. - public static bool Contains(this Array array, object value) { - return Array.IndexOf(array, value) != -1; - } - - /// Returns true if the array contains the specified value. - /// The element type of the array. - /// The array to check for containment. - /// The value to check for. - /// Returns true if the array contains the specified value. - public static bool Contains(this T[] array, T value) { - return Array.IndexOf(array, value) != -1; - } - - #endregion - - #region BlockCast - - /// - /// Block copies the source array to a new array of primitive type . - /// - /// - /// The primitive type to cast to. - /// The array to block cast. - /// How alignment remainders are handled. - /// Return a new array with the casted type. - /// - /// - /// is not an array of primitives, - /// is not a primitive type, or is invalid. - /// - /// - /// The length of is greater than . - /// - public static TResult[] BlockCast(this Array source, - BlockCastAlign align = BlockCastAlign.Error) where TResult : struct - { - Type srcType = source.GetType().GetElementType(); - Type resultType = typeof(TResult); - if (!srcType.IsPrimitive) - throw new ArgumentException($"{nameof(source)} is not an array of " + - $"primitives!", nameof(source)); - else if (!resultType.IsPrimitive) - throw new ArgumentException($"{nameof(TResult)} '{resultType.Name}' " + - $"is not a primitive type!", nameof(TResult)); - - int srcSize = Marshal.SizeOf(srcType); - int srcByteLength = source.Length * srcSize; - - int resultSize = Marshal.SizeOf(); - int resultLength = Math.DivRem(srcByteLength, resultSize, out int rem); - int copyByteLength = srcByteLength; - if (rem != 0) { - switch (align) { - case BlockCastAlign.Oversize: - resultLength += resultSize; - break; - case BlockCastAlign.Undersize: - copyByteLength = resultLength * resultSize; - break; - case BlockCastAlign.Error: - throw new ArgumentException($"{srcType.Name}[] of length " + - $"'{source.Length}' cannot align with {resultType.Name}[] " + - $"of length '{resultLength}`!", nameof(source)); - default: - throw new ArgumentException($"{nameof(align)} is invalid!", - nameof(align)); - } - } - - TResult[] result = new TResult[resultLength]; - Buffer.BlockCopy(source, 0, result, 0, copyByteLength); - return result; - } - - #endregion - - #region Reverse - - /// Creates a reversed copy the array. - /// - /// The arrat to copy. - /// A reversed array. - /// - /// is multidimensional. - public static Array Reverse(this Array array) { - Array output = (Array) array.Clone(); - Array.Reverse(output); - return output; - } - - /// Creates a reversed copy the array. - /// - /// The element type of the array. - /// The arrat to copy. - /// A reversed array. - public static T[] Reverse(this T[] array) { - T[] output = (T[]) array.Clone(); - Array.Reverse(output); - return output; - } - - #endregion - - #region Swap - - /// Swaps two elements within an array. - /// - /// The array to swap elements in. - /// The index of the first element to swap. - /// The index of the second element to swap. - /// - /// - /// or is outside the bounds of the array. - /// - public static void Swap(this Array array, int indexA, int indexB) { - object swap = array.GetValue(indexA); - array.SetValue(array.GetValue(indexB), indexA); - array.SetValue(swap, indexB); - } - - /// Swaps two elements within an array. - /// - /// The element type of the array. - /// The array to swap elements in. - /// The index of the first element to swap. - /// The index of the second element to swap. - /// - /// - /// or is outside the bounds of the array. - /// - public static void Swap(this T[] array, int indexA, int indexB) { - T swap = array[indexA]; - array[indexA] = array[indexB]; - array[indexB] = swap; - } - - #endregion - - #region ToJagged - - /// Copies a 2D multidimension array to a 2D jagged array. - /// - /// The type of the array. - /// The array to create a jagged version of. - /// - /// True if the first dimension in the multidimension array should be the last dimension in the - /// jagged array. - /// - /// The new jagged array. - public static T[][] ToJagged(this T[,] array, bool reverse) { - T[][] output; - int lengthx, lengthy; - if (reverse) { - lengthx = array.GetLength(1); - lengthy = array.GetLength(0); - output = new T[lengthx][]; - for (int x = 0; x < lengthx; x++) { - output[x] = new T[lengthy]; - for (int y = 0; y < lengthy; y++) - output[x][y] = array[y, x]; - } - } - else { - lengthx = array.GetLength(0); - lengthy = array.GetLength(1); - output = new T[lengthx][]; - for (int x = 0; x < lengthx; x++) { - output[x] = new T[lengthy]; - for (int y = 0; y < lengthy; y++) - output[x][y] = array[x, y]; - } - } - return output; - } - - /// Copies a 3D multidimension array to a 3D jagged array. - /// - /// The type of the array. - /// The array to create a jagged version of. - /// - /// True if the first dimension in the multidimension array should be the last dimension in the - /// jagged array. - /// - /// The new jagged array. - public static T[][][] ToJagged(this T[,,] array, bool reverse) { - T[][][] output; - int lengthx, lengthy, lengthz; - if (reverse) { - lengthx = array.GetLength(2); - lengthy = array.GetLength(1); - lengthz = array.GetLength(0); - output = new T[lengthx][][]; - for (int x = 0; x < lengthx; x++) { - output[x] = new T[lengthy][]; - for (int y = 0; y < lengthy; y++) { - output[x][y] = new T[lengthz]; - for (int z = 0; z < lengthz; z++) - output[x][y][z] = array[z, y, x]; - } - } - } - else { - lengthx = array.GetLength(0); - lengthy = array.GetLength(1); - lengthz = array.GetLength(2); - output = new T[lengthx][][]; - for (int x = 0; x < lengthx; x++) { - output[x] = new T[lengthy][]; - for (int y = 0; y < lengthy; y++) { - output[x][y] = new T[lengthz]; - for (int z = 0; z < lengthz; z++) - output[x][y][z] = array[x, y, z]; - } - } - } - return output; - } - - #endregion - - #region ToMultidimension - - /// Copies a 2D jagged array to a 2D multidimension array. - /// - /// The type of the array. - /// The array to create a jagged version of. - /// - /// True if the first dimension in the jagged array should be the last dimension in the - /// multidimension array. - /// - /// The new multidimension array. - /// - /// - /// One of the dimensions in is null. - /// - public static T[,] ToMultidimension(this T[][] array, bool reverse) { - T[,] output; - int lengthx = array.Length; - int lengthy = array.FirstOrDefault()?.Length ?? 0; - if (reverse) { - output = new T[lengthy, lengthx]; - for (int x = 0; x < lengthx; x++) { - LengthCheck(array, x, lengthy, 1); - for (int y = 0; y < lengthy; y++) - output[y, x] = array[x][y]; - } - } - else { - output = new T[lengthx, lengthy]; - for (int x = 0; x < lengthx; x++) { - LengthCheck(array, x, lengthy, 1); - for (int y = 0; y < lengthy; y++) - output[x, y] = array[x][y]; - } - } - return output; - } - - /// Copies a 3D jagged array to a 3D multidimension array. - /// - /// The type of the array. - /// The array to create a jagged version of. - /// - /// True if the first dimension in the jagged array should be the last dimension in the - /// multidimension array. - /// - /// The new multidimension array. - /// - /// - /// One of the dimensions in is null. - /// - public static T[,,] ToMultidimension(this T[][][] array, bool reverse) { - T[,,] output; - int lengthx = array.Length; - int lengthy = array.FirstOrDefault()?.Length ?? 0; - int lengthz = array.FirstOrDefault()?.FirstOrDefault()?.Length ?? 0; - if (reverse) { - output = new T[lengthz, lengthy, lengthx]; - for (int x = 0; x < lengthx; x++) { - LengthCheck(array, x, lengthy, 1); - for (int y = 0; y < lengthy; y++) { - LengthCheck(array, y, lengthz, 1); - for (int z = 0; z < lengthz; y++) - output[z, y, x] = array[x][y][z]; - } - } - } - else { - output = new T[lengthx, lengthy, lengthz]; - for (int x = 0; x < lengthx; x++) { - LengthCheck(array, x, lengthy, 1); - for (int y = 0; y < lengthy; y++) { - LengthCheck(array, y, lengthz, 1); - for (int z = 0; z < lengthz; y++) - output[x, y, z] = array[x][y][z]; - } - } - } - return output; - } - - #endregion - - #region Private - - /// Ensures the jagged array conforms to the same length for every index. - /// - /// The element type of the array. - /// The array to check the length of. - /// The index of the array to check the length of. - /// The initial length of the array. - /// The current pdeth of teh array. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void LengthCheck(T[][] array, int index, int length, int depth) { - if (array[index].Length != length) { - throw new ArgumentException($"Jagged array of depth: {depth}, index: {index}, " + - $"length: {array[index].Length} does not match initial length of {length}!"); - } - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/CommandExtensions.cs b/WinDirStat.Net.Base/Utils/CommandExtensions.cs deleted file mode 100644 index 624e370..0000000 --- a/WinDirStat.Net.Base/Utils/CommandExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; - -namespace WinDirStat.Net.Utils { - /// Extensions for s. - public static class CommandExtensions { - - #region Execute - - /// Executes the method without a parameter. - /// - /// The command to execute. - public static void Execute(this ICommand command) { - command.Execute(null); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/Enumerator.cs b/WinDirStat.Net.Base/Utils/Enumerator.cs deleted file mode 100644 index d1ca616..0000000 --- a/WinDirStat.Net.Base/Utils/Enumerator.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace WinDirStat.Net.Utils { - /// A static class for creating basic s. - public static class Enumerator { - - #region EmptyEnumerator - - /// An empty non-generic enumerator. - private class EmptyEnumerator : IEnumerator { - - /// Constructs an empty enumerator. - public EmptyEnumerator() { } - - /// - /// Sets the enumerator to its initial position, which is before the first element in the - /// collection. - /// - public void Reset() { } - - /// Advances the enumerator to the next element of the collection. - /// - /// - /// true if the enumerator was successfully advanced to the next element; false if the enumerator - /// has passed the end of the collection. - /// - public bool MoveNext() { - return false; - } - - /// Gets the current element in the collection. - public object Current { - get => throw new InvalidOperationException(); - } - } - - #endregion - - #region EmptyEnumerator - - /// An empty generic enumerator. - private class EmptyEnumerator : IEnumerator, IEnumerator { - - /// Constructs an empty generic enumerator. - public EmptyEnumerator() { } - - /// Disposes of the enumerator. - public void Dispose() { } - - /// - /// Sets the enumerator to its initial position, which is before the first element in the - /// collection. - /// - public void Reset() { } - - /// Advances the enumerator to the next element of the collection. - /// - /// - /// true if the enumerator was successfully advanced to the next element; false if the enumerator - /// has passed the end of the collection. - /// - public bool MoveNext() { - return false; - } - - /// Gets the current element in the collection. - public T Current { - get => throw new InvalidOperationException(); - } - - /// Gets the current element in the collection. - object IEnumerator.Current { - get => throw new InvalidOperationException(); - } - } - - #endregion - - #region EmptyEnumerator Static Constructors - - /// Construct an empty . - /// - /// The new non-generic enumerator. - public static IEnumerator Empty() { - return new EmptyEnumerator(); - } - - /// Construct an empty . - /// - /// The generic type of the enumerator. - /// The new generic enumerator. - public static IEnumerator Empty() { - return new EmptyEnumerator(); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/FormatBytes.cs b/WinDirStat.Net.Base/Utils/FormatBytes.cs deleted file mode 100644 index 65afa51..0000000 --- a/WinDirStat.Net.Base/Utils/FormatBytes.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Utils { - /// A formatter for displaying bytes with their abbreviations. - public static class FormatBytes { - - #region Constants - - /// All supported byte abbrevations. - public static readonly ReadOnlyCollection Abbreviations = - Array.AsReadOnly(new[] { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }); - - /// The default format for abbreviations of just bytes. - public const string SingleFormat = "N0"; - /// The default format for abbreviations greater than just bytes. - public const string MultiFormat = "N1"; - - #endregion - - #region Default Format - - /// Formats the bytes using the default formats. - public static string Format(int bytes) { - return Format(Convert.ToDouble(bytes)); - } - /// Formats the bytes using the default formats. - public static string Format(uint bytes) { - return Format(Convert.ToDouble(bytes)); - } - /// Formats the bytes using the default formats. - public static string Format(long bytes) { - return Format(Convert.ToDouble(bytes)); - } - /// Formats the bytes using the default formats. - public static string Format(ulong bytes) { - return Format(Convert.ToDouble(bytes)); - } - /// Formats the bytes using the default formats. - public static string Format(float bytes) { - return Format(bytes, SingleFormat, MultiFormat); - } - /// Formats the bytes using the default formats. - public static string Format(decimal bytes) { - return Format(Convert.ToDouble(bytes)); - } - /// Formats the bytes using the default formats. - public static string Format(double bytes) { - return Format(bytes, SingleFormat, MultiFormat); - } - - #endregion - - #region Custom Format - - /// Formats the bytes using the specified formats. - public static string Format(int bytes, string singleFormat, string multiFormat) { - return Format(Convert.ToDouble(bytes), singleFormat, multiFormat); - } - /// Formats the bytes using the specified formats. - public static string Format(uint bytes, string singleFormat, string multiFormat) { - return Format(Convert.ToDouble(bytes), singleFormat, multiFormat); - } - /// Formats the bytes using the specified formats. - public static string Format(long bytes, string singleFormat, string multiFormat) { - return Format(Convert.ToDouble(bytes), singleFormat, multiFormat); - } - /// Formats the bytes using the specified formats. - public static string Format(ulong bytes, string singleFormat, string multiFormat) { - return Format(Convert.ToDouble(bytes), singleFormat, multiFormat); - } - /// Formats the bytes using the specified formats. - public static string Format(float bytes, string singleFormat, string multiFormat) { - return Format(Convert.ToDouble(bytes), singleFormat, multiFormat); - } - /// Formats the bytes using the specified formats. - public static string Format(decimal bytes, string singleFormat, string multiFormat) { - return Format(Convert.ToDouble(bytes), singleFormat, multiFormat); - } - /// Formats the bytes using the specified formats. - public static string Format(double bytes, string singleFormat, string multiFormat) { - int order; - int sign = Math.Sign(bytes); - bytes = Math.Abs(bytes); - for (order = 0; order < Abbreviations.Count && bytes >= 1024; order++) { - bytes /= 1024; - } - - // Don't show decimal places for Bytes - string format = (order == 0 ? singleFormat : multiFormat); - - return string.Format("{0:" + format + "} {1}", sign * bytes, Abbreviations[order]); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/ListExtensions.cs b/WinDirStat.Net.Base/Utils/ListExtensions.cs deleted file mode 100644 index 8a78b6d..0000000 --- a/WinDirStat.Net.Base/Utils/ListExtensions.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Utils { - /// Extensions for the list class. - public static class ListExtensions { - /// - /// Minimizes the memory usage of teh list by reducing the to the - /// current . - /// - /// - /// The element type of the list. - /// The list to minimize. - public static void Minimize(this List source) { - source.Capacity = source.Count; - } - - /// Moves a single item in the list. - /// - /// The element type of the list. - /// The list to move an item in. - /// The new index of the item. - /// The old index of the item. - public static void Move(this List source, int index, int oldIndex) { - T item = source[oldIndex]; - source.RemoveAt(index); - source.Insert(index, item); - } - - /// Movess a range of items in the list. - /// - /// The element type of the list. - /// The list to move items in. - /// The new index of the items. - /// The old index of the items. - /// The number of items to move. - public static void MoveRange(this List source, int index, int oldIndex, int count) { - List items = source.GetRange(oldIndex, count); - source.RemoveRange(oldIndex, count); - source.InsertRange(index, items); - } - - /// - /// Creates a copy of the list using a more efficient method than with . - /// - /// - /// The element type of the list. - /// The list to create a copy of. - public static List GetFullRange(this List source) { - return source.GetRange(0, source.Count); - } - } -} diff --git a/WinDirStat.Net.Base/Utils/MathUtils.cs b/WinDirStat.Net.Base/Utils/MathUtils.cs deleted file mode 100644 index ac97f93..0000000 --- a/WinDirStat.Net.Base/Utils/MathUtils.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Utils { - /// Simple additional math functions. - public static class MathUtils { - - /// Converts degrees to radians. - /// - /// The degress to convert. - /// The as radians. - public static float DegToRad(float degrees) { - return degrees * (float) Math.PI / 180f; - } - - /// Converts degrees to radians. - /// - /// The degress to convert. - /// The as radians. - public static double DegToRad(double degrees) { - return degrees * Math.PI / 180d; - } - - /// Converts radians to degrees. - /// - /// The radians to convert. - /// The as degrees. - public static float RadToDeg(float radians) { - return radians / (float) Math.PI * 180f; - } - - /// Converts radians to degrees. - /// - /// The radians to convert. - /// The as degrees. - public static double RadToDeg(double radians) { - return radians / Math.PI * 180d; - } - - /// Rounds the value and returns it as an integer. - /// - /// The value to round. - /// The rounded value as an integer. - public static int Round(float x) { - return Math.Sign(x) * (int) (Math.Abs(x) + 0.5f); - } - - /// Rounds the value and returns it as an integer. - /// - /// The value to round. - /// The rounded value as an integer. - public static int Round(double x) { - return Math.Sign(x) * (int) (Math.Abs(x) + 0.5); - } - - /// Clamps the values. - /// - /// The type to compare. - /// The value to clamp. - /// The minimum value (has priority over ). - /// The maximum value. - /// The value between and . - public static T Clamp(T value, T min, T max) where T : IComparable { - if (value.CompareTo(min) < 0) - return min; - else if (value.CompareTo(max) > 0) - return max; - else - return value; - } - } -} diff --git a/WinDirStat.Net.Base/Utils/PathUtils.cs b/WinDirStat.Net.Base/Utils/PathUtils.cs deleted file mode 100644 index 125bbee..0000000 --- a/WinDirStat.Net.Base/Utils/PathUtils.cs +++ /dev/null @@ -1,549 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace WinDirStat.Net.Utils { - /// A helper with extra methods for paths, files, and directories. - public static class PathUtils { - - //----------------------------------------------------------------------------- - // Constants - //----------------------------------------------------------------------------- - - /// The stored executable path for the entry assembly. - public static readonly string EntryPath = - Assembly.GetEntryAssembly().Location; - - /// The directory of the entry executable. - public static readonly string EntryDirectory = - Path.GetDirectoryName(EntryPath); - - /// Gets the file name of the entry executable. - public static readonly string EntryFile = - Path.GetFileName(EntryPath); - - /// Gets the file name of the entry executable without its extension. - public static readonly string EntryName = - Path.GetFileNameWithoutExtension(EntryPath); - - /// - /// Provides a platform-specific character used to separate directory levels in a path - /// string that reflects a hierarchical file system organization. - /// - public static readonly char[] DirectorySeparators = { - Path.DirectorySeparatorChar, - Path.AltDirectorySeparatorChar, - }; - - public static readonly string DirectorySeparatorString = - new string(Path.DirectorySeparatorChar, 1); - public static readonly string AltDirectorySeparatorString = - new string(Path.AltDirectorySeparatorChar, 1); - public static readonly string VolumeSeparatorString = - new string(Path.VolumeSeparatorChar, 1); - - /// - /// Provides a platform-specific character used to separate directory levels in a path - /// string that reflects a hierarchical file system organization. - /// - public static readonly string[] DotDirectorySeparators = { - Path.DirectorySeparatorChar + ".", - Path.AltDirectorySeparatorChar + ".", - }; - - /// Gets the path to System32 whether this is an x86 or x64 process. - /// - /// - /// The operating system is not running Windows. - /// - public static string System32 { - get { - return Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.Windows), - Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess - ? "Sysnative" : "System32"); - } - } - - //----------------------------------------------------------------------------- - // File Validity - //----------------------------------------------------------------------------- - - /// Returns true if the file name has valid characters. - public static bool IsValidName(string name) { - return name.IndexOfAny(Path.GetInvalidFileNameChars()) == -1; - } - - /// - /// Returns true if the file name has valid characters for a search pattern. - /// - public static bool IsValidNamePattern(string name) { - name = name.Replace("*", "").Replace("?", ""); - return IsValidName(name); - } - - /// Returns true if the file path has valid characters. - public static bool IsValidPath(string path) { - try { - Path.GetFullPath(path); - return true; - } - catch { - return false; - } - //return name.IndexOfAny(Path.GetInvalidPathChars()) == -1; - } - - /// - /// Returns true if the file path has valid characters and is not rooted. - /// - public static bool IsValidRelativePath(string path) { - if (Path.IsPathRooted(path)) - return false; - return IsValidPath(path); - } - - /// - /// Returns true if the file path has valid characters for a search pattern. - /// - public static bool IsValidPathPattern(string path) { - path = path.Replace("*", "").Replace("?", ""); - return IsValidPath(path); - //return path.IndexOfAny(Path.GetInvalidPathChars()) == -1; - } - - /// - /// Returns true if the file path has valid characters and does not lead to a directory. - /// - public static bool IsValidFile(string path) { - return IsValidPath(path) && !Directory.Exists(path); - } - - /// - /// Returns true if the file path has valid characters, is not rooted. and does not lead to - /// a directory. - /// - public static bool IsValidRelativeFile(string path) { - if (Path.IsPathRooted(path)) - return false; - return IsValidFile(path); - } - - /// - /// Returns true if the file path has valid characters and does not lead to a file. - /// - public static bool IsValidDirectory(string path) { - return IsValidPath(path) && !File.Exists(path); - } - - /// - /// Returns true if the file path has valid characters, is not rooted. and does not lead to - /// a file. - /// - public static bool IsValidRelativeDirectory(string path) { - if (Path.IsPathRooted(path)) - return false; - return IsValidDirectory(path); - } - - - //----------------------------------------------------------------------------- - // File or Directory - //----------------------------------------------------------------------------- - - /// Copies a file or directory. - public static void CopyFileOrDirectory(string sourcePath, string destPath, bool overwrite) { - if (Directory.Exists(sourcePath)) - CopyDirectory(sourcePath, destPath, overwrite); - else - File.Copy(sourcePath, destPath, overwrite); - } - - /// Moves a file or directory. - public static void MoveFileOrDirectory(string sourcePath, string destPath) { - if (Directory.Exists(sourcePath)) - Directory.Move(sourcePath, destPath); - else - File.Move(sourcePath, destPath); - } - - /// Deletes a file or directory. - public static void DeleteFileOrDirectory(string path) { - if (Directory.Exists(path)) - Directory.Delete(path, true); - else - File.Delete(path); - } - - /// Returns true if a file or directory exists at the path. - public static bool Exists(string path) { - return (File.Exists(path) || Directory.Exists(path)); - } - - /// Copies the directory and all subfolders and files. - public static void CopyDirectory(string sourceDir, string destDir, bool merge) { - // Get the subdirectories for the specified directory. - DirectoryInfo dir = new DirectoryInfo(sourceDir); - - if (!dir.Exists) - throw new DirectoryNotFoundException($"Source directory does not exist or could " + - $"not be found: {sourceDir}"); - - DirectoryInfo[] dirs = dir.GetDirectories(); - // If the destination directory doesn't exist, create it. - if (File.Exists(destDir)) - throw new IOException("File already exists at location!"); - else if (!Directory.Exists(destDir)) - Directory.CreateDirectory(destDir); - else if (!merge) - throw new IOException("Directory already exists at location!"); - - // Get the files in the directory and copy them to the new location. - FileInfo[] files = dir.GetFiles(); - foreach (FileInfo file in files) { - string temppath = Path.Combine(destDir, file.Name); - file.CopyTo(temppath, true); - } - - // Copy subdirectories and their contents to new location. - foreach (DirectoryInfo subdir in dirs) { - string temppath = Path.Combine(destDir, subdir.Name); - CopyDirectory(subdir.FullName, temppath, true); - } - } - - - //----------------------------------------------------------------------------- - // File Paths - //----------------------------------------------------------------------------- - - /// Returns a path that can be compared with another normalized path. - public static string NormalizePath(string path) { - return TrimSeparatorDotEnd( - Path.GetFullPath(path) - .TrimEnd(DirectorySeparators) - .ToUpperInvariant()); - } - - /// Returns true if the two paths lead to the same location. - public static bool IsSamePath(string path1, string path2) { - return string.Compare(NormalizePath(path1), NormalizePath(path2), true) == 0; - } - - /// Removes the ending directory separator from the path. - public static string TrimSeparatorEnd(string path) { - return path.TrimEnd(DirectorySeparators); - } - - /// Removes the ending directory separator from the path. - public static string TrimSeparatorDotEnd(string path) { - for (int i = 0; i < DotDirectorySeparators.Length; i++) { - if (path.EndsWith(DotDirectorySeparators[i])) - return path.Substring(0, path.Length - DotDirectorySeparators[i].Length); - } - return TrimSeparatorEnd(path); - } - - private static readonly string DirectorySeparatorCharAsString = new string(Path.DirectorySeparatorChar, 1); - - public static string CombineNoChecks(string path1, string path2) { - if (path2.Length == 0) - return path1; - - if (path1.Length == 0) - return path2; - - if (Path.IsPathRooted(path2)) - return path2; - - char ch = path1[path1.Length - 1]; - if (!IsDirectorySeparator(ch)) - return path1 + DirectorySeparatorString + path2; - return path1 + path2; - } - - public static string AddLongPathPrefix(string path) { - if (!path.StartsWith(@"\\?\")) - return @"\\?\" + path; - return path; - } - - /// - /// A version of that doesn't access the file system. - /// - /// - /// The path to expand. - /// True if environment variables should be expanded. - /*public static string GetFullPath(string path) { - bool notRooted = !Path.IsPathRooted(path); - string currentDirectory = ""; - if (notRooted) - currentDirectory = Directory.GetDirectories() - string root = () - - string dirs = path; - //string name = Path.GetFileName(path); - string outPath = ""; - while (dirs.Length != 0) { - string name = Path.GetFileName(dirs); - if (name == ".") { - - } - - dirs = Path.GetDirectoryName(dirs); - } - - if (expandEnvVars && path.Contains("%")) - path = Environment.ExpandEnvironmentVariables(path); - }*/ - - /*public static IEnumerable EnumerateDirectoryNames(string path) { - while (path.Contains(DirectorySeparators[0]) || path.Contains(DirectorySeparators[1])) { - - } - }*/ - - public static bool IsPathRoot(string path) { - return IsSamePath(Path.GetPathRoot(path), path); - } - - public static string GetRootOrFileName(string path) { - if (IsPathRoot(path)) - return path; - else - return Path.GetFileName(path); - } - - /// Returns a file path with " - Copy" appended to the filename. - public static string GetCopyName(string path) { - string newPath = Path.GetFileNameWithoutExtension(path) + " - Copy"; - string ext = Path.GetExtension(path); - - int index = 1; - string finalPath = newPath + ext; - while (Exists(finalPath)) { - index++; - finalPath = $"{newPath} ({index}){ext}"; - } - return finalPath; - } - - /// Combines the specified paths with the executable directory. - public static string CombineExe(string path1) { - return Path.Combine(EntryDirectory, path1); - } - - /// Combines the specified paths with the executable directory. - public static string CombineExe(string path1, string path2) { - return Path.Combine(EntryDirectory, path1, path2); - } - - /// Combines the specified paths with the executable directory. - public static string CombineExe(string path1, string path2, - string path3) { - return Path.Combine(EntryDirectory, path1, path2, path3); - } - - /// Combines the specified paths with the executable directory. - public static string CombineExe(params string[] paths) { - return Path.Combine(EntryDirectory, Path.Combine(paths)); - } - - public static string GetTempDirectory(params string[] paths) { - return Path.Combine(Path.GetTempPath(), Path.Combine(paths)); - } - - public static string CreateTempDirectory(params string[] paths) { - string path = GetTempDirectory(paths); - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); - return path; - } - - public static void CleanupTempDirectory(bool deleteRoot, params string[] paths) { - string path = GetTempDirectory(paths); - - if (Directory.Exists(path)) { - - if (deleteRoot) - Directory.Delete(path); - } - } - - /// - /// Gets the exact case used on the file system for an existing file or directory name. - /// - /// - /// A relative or absolute path. - /// The name using the correct case if the path exists. - /// - /// - /// This supports drive-lettered paths and UNC paths, but a UNC root will be returned in - /// title case (e.g., \\Server\Share). - /// Source - /// - public static string GetExactName(string path) { - // DirectoryInfo accepts either a file path or a directory path, and most - // of its properties work for either. However, its Exists property only - // works for a directory path. - DirectoryInfo directory = new DirectoryInfo(path); - if (File.Exists(path) || directory.Exists) { - DirectoryInfo parentDirectory = directory.Parent; - FileSystemInfo child = parentDirectory.EnumerateFileSystemInfos( - directory.Name).First(); - return child.Name; - } - else { - throw new FileNotFoundException(path); - } - } - - /// - /// Gets the exact case used on the file system for an existing file or directory path. - /// - /// - /// A relative or absolute path. - /// The full path using the correct case if the path exists. - /// - /// - /// This supports drive-lettered paths and UNC paths, but a UNC root will be returned in - /// title case (e.g., \\Server\Share). - /// Source - /// - public static string GetExactPath(string path) { - // DirectoryInfo accepts either a file path or a directory path, and most - // of its properties work for either. However, its Exists property only - // works for a directory path. - DirectoryInfo directory = new DirectoryInfo(path); - if (File.Exists(path) || directory.Exists) { - List parts = new List(); - - DirectoryInfo parentDirectory = directory.Parent; - while (parentDirectory != null) { - FileSystemInfo entry = parentDirectory.EnumerateFileSystemInfos( - directory.Name).First(); - parts.Add(entry.Name); - - directory = parentDirectory; - parentDirectory = directory.Parent; - } - - // Handle the root part (i.e., drive letter or UNC \\server\share). - string root = directory.FullName; - if (root.Contains(':')) { - // Drive Letter - root = root.ToUpper(); - } - else { - // UNC - string[] rootParts = root.Split(Path.DirectorySeparatorChar); - root = string.Join(DirectorySeparatorString, rootParts.Select(part => - CultureInfo.CurrentCulture.TextInfo.ToTitleCase(part))); - } - - parts.Add(root); - parts.Reverse(); - return Path.Combine(parts.ToArray()); - } - else { - throw new FileNotFoundException(path); - } - } - - public static bool EndsWithSeparator(string path) { - return path.Length > 0 && IsSeparator(path[path.Length - 1]); - } - public static bool EndsWithDirectorySeparator(string path) { - return path.Length > 0 && IsDirectorySeparator(path[path.Length - 1]); - } - public static bool EndsWithVolumeSeparator(string path) { - return path.Length > 0 && IsVolumeSeparator(path[path.Length - 1]); - } - public static string AddVolumeSeparator(string path) { - if (!EndsWithVolumeSeparator(path)) - return path + Path.VolumeSeparatorChar; - return path; - } - public static string AddDirectorySeparator(string path) { - if (!EndsWithDirectorySeparator(path)) - return path + Path.DirectorySeparatorChar; - return path; - } - - public static bool IsSeparator(char c) { - return c == Path.DirectorySeparatorChar || - c == Path.AltDirectorySeparatorChar || - c == Path.VolumeSeparatorChar; - } - public static bool IsDirectorySeparator(char c) { - return c == Path.DirectorySeparatorChar || - c == Path.AltDirectorySeparatorChar; - } - public static bool IsVolumeSeparator(char c) { - return c == Path.VolumeSeparatorChar; - } - - - //----------------------------------------------------------------------------- - // Get Files - //----------------------------------------------------------------------------- - - #region Get/EnumerateAllFiles - - /// Returns an array of all files and subfiles in the directory. - public static string[] GetAllFiles(string path) { - return Directory.GetFiles(path, "*", SearchOption.AllDirectories); - } - - /// - /// Returns an array of all files and subfiles in the directory that match the search - /// pattern. - /// - public static string[] GetAllFiles(string path, string pattern) { - return Directory.GetFiles(path, pattern, SearchOption.AllDirectories); - } - - /// Enumerates all files and subfiles in the directory. - public static IEnumerable EnumerateAllFiles(string path) { - return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories); - } - - /// - /// Enumerates all files and subfiles in the directory that match the search pattern. - /// - public static IEnumerable EnumerateAllFiles(string path, string pattern) { - return Directory.EnumerateFiles(path, pattern, SearchOption.AllDirectories); - } - - #endregion - - //----------------------------------------------------------------------------- - // Directory - //----------------------------------------------------------------------------- - - /// Returns true if the directory has no files in it. - public static bool IsDirectoryEmpty(string directory) { - return !Directory.EnumerateFileSystemEntries(directory).Any(); - } - - /// - /// Deletes all empty directories and subdirectories within this directory. - /// - public static void DeleteAllEmptyDirectories(string directory) { - foreach (string dir in Directory.EnumerateDirectories(directory)) { - if (IsDirectoryEmpty(dir)) { - Directory.Delete(dir); - } - else { - DeleteAllEmptyDirectories(dir); - if (IsDirectoryEmpty(dir)) - Directory.Delete(dir); - } - } - } - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/IVolatile.cs b/WinDirStat.Net.Base/Utils/Volatiles/IVolatile.cs deleted file mode 100644 index 295aa00..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/IVolatile.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Utils { - /// An interface for a volatile container type. - public interface IVolatile { - - #region Properties - - /// Gets the value. - object Value { get; } - /// Gets the lock context. - object LockObj { get; } - - #endregion - - #region Locking - - /// Locks the value. - void Lock(); - /// Unlocks the value. - void Unlock(); - - #endregion - - #region Volatile Operators - - /// Sets the value. - object Set(object o); - - #endregion - - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/Volatile.cs b/WinDirStat.Net.Base/Utils/Volatiles/Volatile.cs deleted file mode 100644 index 6d81e72..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/Volatile.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Utils { - /// A mutable volatile . - public class Volatile : IVolatile { - - #region Fields - - /// The value. - protected T value; - /// The lock context. - protected readonly object lockObj; - - #endregion - - #region Constructors - - /// Constructs the default . - public Volatile() { - lockObj = new object(); - } - /// Constructs the with the specified value. - /// - /// The value to use. - public Volatile(T value) : this() { - this.value = value; - } - /// Constructs the with the specified lock. - /// - /// The lock context to use. - public Volatile(object lockObj) { - if (lockObj == null) - throw new ArgumentNullException(nameof(lockObj)); - if (lockObj.GetType().IsValueType) - throw new ArgumentException("Cannot use a boxed a value type as a lock context!"); - this.lockObj = lockObj; - } - /// Constructs the with the specified value and lock. - /// - /// The value to use. - /// The lock context to use. - public Volatile(T value, object lockObj) : this(lockObj) { - this.value = value; - } - - #endregion - - #region Locking - - /// Locks the value. - public void Lock() { - Monitor.Enter(lockObj); - } - /// Unlocks the value. - public void Unlock() { - Monitor.Exit(lockObj); - } - - #endregion - - #region Properties - - /// Gets the value. - public T Value { - get { lock (lockObj) return value; } - //set { lock (lockObj) this.value = value; } - } - /// Gets the value. - object IVolatile.Value => Value; - /// Gets the lock context. - public object LockObj => lockObj; - - #endregion - - #region Volatile Operators - - /// Sets the value. - public T Set(T newValue) { - lock (lockObj) - return value = newValue; - } - /// Sets the value. - object IVolatile.Set(object newValue) { - lock (lockObj) - return value = (T) newValue; - } - - #endregion - - #region Conversion Operators - - /// Gets the of the . - public static implicit operator T(Volatile value) { - return value.Value; - } - - #endregion - - #region Overrides - - /// Determines whether the specified object is equal to the current object. - public override bool Equals(object obj) { - if (obj is IVolatile vol) - return value.Equals(vol.Value); - return value.Equals(obj); - } - /// Returns the hash code for this instance. - public override int GetHashCode() => value.GetHashCode(); - /// Converts the value of this instance to its equivalent string representation. - public override string ToString() => value.ToString(); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/VolatileBoolean.cs b/WinDirStat.Net.Base/Utils/Volatiles/VolatileBoolean.cs deleted file mode 100644 index 22d7877..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/VolatileBoolean.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Utils { - /// A mutable volatile that supports compound assignments. - public class VolatileBoolean : Volatile { - - #region Constructors - - /// Constructs the default . - public VolatileBoolean() { } - /// Constructs the with the specified value. - /// - /// The value to use. - public VolatileBoolean(bool value) : base(value) { } - /// Constructs the with the specified lock. - /// - /// The lock context to use. - public VolatileBoolean(object lockObj) : base(lockObj) { } - /// Constructs the with the specified value and lock. - /// - /// The value to use. - /// The lock context to use. - public VolatileBoolean(bool value, object lockObj) : base(value, lockObj) { } - - #endregion - - #region Volatile Operators - - /// Toggles the value. - public bool Toggle() { - lock (lockObj) - return value = !value; - } - - #endregion - - #region Volatile Bitwise Operators - - /// Bitwise AND's the value. - public bool BitwiseAnd(bool b) { - lock (lockObj) - return value &= b; - } - /// Bitwise OR's the value. - public bool BitwiseOr(bool b) { - lock (lockObj) - return value |= b; - } - /// Bitwise XOR's the value. - public bool BitwiseXor(bool b) { - lock (lockObj) - return value ^= b; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/VolatileCompound.cs b/WinDirStat.Net.Base/Utils/Volatiles/VolatileCompound.cs deleted file mode 100644 index a6b7492..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/VolatileCompound.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Utils { - /// A mutable volatile . - public class VolatileCompound : IVolatile { - - #region Fields - - /// The value. - protected T value; - /// The lock context. - protected readonly object lockObj; - - #endregion - - #region Constructors - - /// Constructs the default . - public VolatileCompound() { - lockObj = new object(); - } - /// Constructs the with the specified value. - /// - /// The value to use. - public VolatileCompound(T value) : this() { - this.value = value; - } - /// Constructs the with the specified lock. - /// - /// The lock context to use. - public VolatileCompound(object lockObj) { - if (lockObj == null) - throw new ArgumentNullException(nameof(lockObj)); - if (lockObj.GetType().IsValueType) - throw new ArgumentException("Cannot use a boxed a value type as a lock context!"); - this.lockObj = lockObj; - } - /// Constructs the with the specified value and lock. - /// - /// The value to use. - /// The lock context to use. - public VolatileCompound(T value, object lockObj) : this(lockObj) { - this.value = value; - } - - #endregion - - #region Locking - - /// Locks the value. - public void Lock() { - Monitor.Enter(lockObj); - } - /// Unlocks the value. - public void Unlock() { - Monitor.Exit(lockObj); - } - - #endregion - - #region Properties - - /// Gets the value. - public T Value { get { lock (lockObj) return value; } } - /// Gets the value. - object IVolatile.Value => Value; - /// Gets the lock context. - public object LockObj => lockObj; - - #endregion - - #region VolatileCompound Operators - - /// Sets the value. - public T Set(T newValue) { - lock (lockObj) - return value = newValue; - } - /// Sets the value. - object IVolatile.Set(object newValue) { - lock (lockObj) - return value = (T) newValue; - } - - #endregion - - #region Conversion Operators - - /// Gets the of the . - public static implicit operator T(VolatileCompound value) { - return value.Value; - } - - #endregion - - #region Overrides - - /// Determines whether the specified object is equal to the current object. - public override bool Equals(object obj) { - if (obj is IVolatile vol) - return value.Equals(vol.Value); - return value.Equals(obj); - } - /// Returns the hash code for this instance. - public override int GetHashCode() => value.GetHashCode(); - /// Converts the value of this instance to its equivalent string representation. - public override string ToString() => value.ToString(); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/VolatileDouble.cs b/WinDirStat.Net.Base/Utils/Volatiles/VolatileDouble.cs deleted file mode 100644 index d7abc79..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/VolatileDouble.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; - -namespace WinDirStat.Net.Utils { - /// A mutable volatile that supports compound assignments. - public class VolatileDouble : Volatile { - - #region Constructors - - /// Constructs the default . - public VolatileDouble() { } - /// Constructs the with the specified value. - /// - /// The value to use. - public VolatileDouble(double value) : base(value) { } - /// Constructs the with the specified lock. - /// - /// The lock context to use. - public VolatileDouble(object lockObj) : base(lockObj) { } - /// Constructs the with the specified value and lock. - /// - /// The value to use. - /// The lock context to use. - public VolatileDouble(double value, object lockObj) : base(value, lockObj) { } - - #endregion - - #region Volatile Operators - - /// Adds to the value. - public double Add(double x) { - lock (lockObj) - return value += x; - } - /// Subtracts from the value. - public double Sub(double x) { - lock (lockObj) - return value -= x; - } - /// Multiplies the value. - public double Mul(double x) { - lock (lockObj) - return value *= x; - } - /// Divides the value. - public double Div(double x) { - lock (lockObj) - return value /= x; - } - /// Negates the value. - public double Negate() { - lock (lockObj) - return value = -value; - } - - #endregion - - #region Volatile Floating Operators - - /// Floors the value. - public double Floor() { - lock (lockObj) - return value = (double) Math.Floor(value); - } - /// Ceilings the value. - public double Ceiling() { - lock (lockObj) - return value = (double) Math.Ceiling(value); - } - /// Rounds the value. - public double Round() { - lock (lockObj) - return value = (double) Math.Round(value); - } - /// Truncates the value. - public double Truncate() { - lock (lockObj) - return value = (double) Math.Truncate(value); - } - /// Squares the value. - public double Sqr() { - lock (lockObj) - return value *= value; - } - /// Square roots the value. - public double Sqrt() { - lock (lockObj) - return value = (double) Math.Sqrt(value); - } - /// Powers the value. - public double Pow(double y) { - lock (lockObj) - return value = (double) Math.Pow(value, y); - } - /// Logs the value. - public double Log(double newBase) { - lock (lockObj) - return value = (double) Math.Log(value, newBase); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt16.cs b/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt16.cs deleted file mode 100644 index ff2ac8a..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt16.cs +++ /dev/null @@ -1,81 +0,0 @@ - -namespace WinDirStat.Net.Utils { - /// A mutable volatile that supports compound assignments. - public class VolatileInt16 : Volatile { - - #region Constructors - - /// Constructs the default . - public VolatileInt16() { } - /// Constructs the with the specified value. - /// - /// The value to use. - public VolatileInt16(short value) : base(value) { } - /// Constructs the with the specified lock. - /// - /// The lock context to use. - public VolatileInt16(object lockObj) : base(lockObj) { } - /// Constructs the with the specified value and lock. - /// - /// The value to use. - /// The lock context to use. - public VolatileInt16(short value, object lockObj) : base(value, lockObj) { } - - #endregion - - #region Volatile Operators - - /// Adds to the value. - public short Add(short i) { - lock (lockObj) - return value += i; - } - /// Subtracts from the value. - public short Sub(short i) { - lock (lockObj) - return value -= i; - } - /// Multiplies the value. - public short Mul(short i) { - lock (lockObj) - return value *= i; - } - /// Divides the value. - public short Div(short i) { - lock (lockObj) - return value /= i; - } - /// Negates the value. - public short Negate() { - lock (lockObj) - return value = (short) -value; - } - - #endregion - - #region Volatile Bitwise Operators - - /// Bitwise AND's the value. - public short BitwiseAnd(short i) { - lock (lockObj) - return value &= i; - } - /// Bitwise OR's the value. - public short BitwiseOr(short i) { - lock (lockObj) - return value |= i; - } - /// Bitwise XOR's the value. - public short BitwiseXor(short i) { - lock (lockObj) - return value ^= i; - } - /// Bitwise negates the value. - public short BitwiseNegate() { - lock (lockObj) - return value = unchecked((short) ~value); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt32.cs b/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt32.cs deleted file mode 100644 index 45c9b0f..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt32.cs +++ /dev/null @@ -1,81 +0,0 @@ - -namespace WinDirStat.Net.Utils { - /// A mutable volatile that supports compound assignments. - public class VolatileInt32 : Volatile { - - #region Constructors - - /// Constructs the default . - public VolatileInt32() { } - /// Constructs the with the specified value. - /// - /// The value to use. - public VolatileInt32(int value) : base(value) { } - /// Constructs the with the specified lock. - /// - /// The lock context to use. - public VolatileInt32(object lockObj) : base(lockObj) { } - /// Constructs the with the specified value and lock. - /// - /// The value to use. - /// The lock context to use. - public VolatileInt32(int value, object lockObj) : base(value, lockObj) { } - - #endregion - - #region Volatile Operators - - /// Adds to the value. - public int Add(int i) { - lock (lockObj) - return value += i; - } - /// Subtracts from the value. - public int Sub(int i) { - lock (lockObj) - return value -= i; - } - /// Multiplies the value. - public int Mul(int i) { - lock (lockObj) - return value *= i; - } - /// Divides the value. - public int Div(int i) { - lock (lockObj) - return value /= i; - } - /// Negates the value. - public int Negate() { - lock (lockObj) - return value = -value; - } - - #endregion - - #region Volatile Bitwise Operators - - /// Bitwise AND's the value. - public int BitwiseAnd(int i) { - lock (lockObj) - return value &= i; - } - /// Bitwise OR's the value. - public int BitwiseOr(int i) { - lock (lockObj) - return value |= i; - } - /// Bitwise XOR's the value. - public int BitwiseXor(int i) { - lock (lockObj) - return value ^= i; - } - /// Bitwise negates the value. - public int BitwiseNegate() { - lock (lockObj) - return value = ~value; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt64.cs b/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt64.cs deleted file mode 100644 index 5d2f894..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/VolatileInt64.cs +++ /dev/null @@ -1,81 +0,0 @@ - -namespace WinDirStat.Net.Utils { - /// A mutable volatile that supports compound assignments. - public class VolatileInt64 : Volatile { - - #region Constructors - - /// Constructs the default . - public VolatileInt64() { } - /// Constructs the with the specified value. - /// - /// The value to use. - public VolatileInt64(long value) : base(value) { } - /// Constructs the with the specified lock. - /// - /// The lock context to use. - public VolatileInt64(object lockObj) : base(lockObj) { } - /// Constructs the with the specified value and lock. - /// - /// The value to use. - /// The lock context to use. - public VolatileInt64(long value, object lockObj) : base(value, lockObj) { } - - #endregion - - #region Volatile Operators - - /// Adds to the value. - public long Add(long i) { - lock (lockObj) - return value += i; - } - /// Subtracts from the value. - public long Sub(long i) { - lock (lockObj) - return value -= i; - } - /// Multiplies the value. - public long Mul(long i) { - lock (lockObj) - return value *= i; - } - /// Divides the value. - public long Div(long i) { - lock (lockObj) - return value /= i; - } - /// Negates the value. - public long Negate() { - lock (lockObj) - return value = -value; - } - - #endregion - - #region Volatile Bitwise Operators - - /// Bitwise AND's the value. - public long BitwiseAnd(long i) { - lock (lockObj) - return value &= i; - } - /// Bitwise OR's the value. - public long BitwiseOr(long i) { - lock (lockObj) - return value |= i; - } - /// Bitwise XOR's the value. - public long BitwiseXor(long i) { - lock (lockObj) - return value ^= i; - } - /// Bitwise negates the value. - public long BitwiseNegate() { - lock (lockObj) - return value = ~value; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/Utils/Volatiles/VolatileSingle.cs b/WinDirStat.Net.Base/Utils/Volatiles/VolatileSingle.cs deleted file mode 100644 index 8273b5a..0000000 --- a/WinDirStat.Net.Base/Utils/Volatiles/VolatileSingle.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; - -namespace WinDirStat.Net.Utils { - /// A mutable volatile that supports compound assignments. - public class VolatileSingle : Volatile { - - #region Constructors - - /// Constructs the default . - public VolatileSingle() { } - /// Constructs the with the specified value. - /// - /// The value to use. - public VolatileSingle(float value) : base(value) { } - /// Constructs the with the specified lock. - /// - /// The lock context to use. - public VolatileSingle(object lockObj) : base(lockObj) { } - /// Constructs the with the specified value and lock. - /// - /// The value to use. - /// The lock context to use. - public VolatileSingle(float value, object lockObj) : base(value, lockObj) { } - - #endregion - - #region Volatile Operators - - /// Adds to the value. - public float Add(float x) { - lock (lockObj) - return value += x; - } - /// Subtracts from the value. - public float Sub(float x) { - lock (lockObj) - return value -= x; - } - /// Multiplies the value. - public float Mul(float x) { - lock (lockObj) - return value *= x; - } - /// Divides the value. - public float Div(float x) { - lock (lockObj) - return value /= x; - } - /// Negates the value. - public float Negate() { - lock (lockObj) - return value = -value; - } - - #endregion - - #region Volatile Floating Operators - - /// Floors the value. - public float Floor() { - lock (lockObj) - return value = (float) Math.Floor(value); - } - /// Ceilings the value. - public float Ceiling() { - lock (lockObj) - return value = (float) Math.Ceiling(value); - } - /// Rounds the value. - public float Round() { - lock (lockObj) - return value = (float) Math.Round(value); - } - /// Truncates the value. - public float Truncate() { - lock (lockObj) - return value = (float) Math.Truncate(value); - } - /// Squares the value. - public float Sqr() { - lock (lockObj) - return value *= value; - } - /// Square roots the value. - public float Sqrt() { - lock (lockObj) - return value = (float) Math.Sqrt(value); - } - /// Powers the value. - public float Pow(float y) { - lock (lockObj) - return value = (float) Math.Pow(value, y); - } - /// Logs the value. - public float Log(float newBase) { - lock (lockObj) - return value = (float) Math.Log(value, newBase); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Commands/IRelayCommand.cs b/WinDirStat.Net.Base/ViewModel/Commands/IRelayCommand.cs deleted file mode 100644 index 6a49972..0000000 --- a/WinDirStat.Net.Base/ViewModel/Commands/IRelayCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.ComponentModel; -using System.Windows.Input; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.ViewModel { - /// An interface for working with any type of RelayCommand. - public interface IRelayCommand : ICommand { - - #region CanExecuteChanged - - /// Raises the event. - void RaiseCanExecuteChanged(); - - #endregion - - #region Execute (No Parameter) - - /// Executes the method without a parameter. - void Execute(); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Commands/IRelayUICommand.cs b/WinDirStat.Net.Base/ViewModel/Commands/IRelayUICommand.cs deleted file mode 100644 index cdc4523..0000000 --- a/WinDirStat.Net.Base/ViewModel/Commands/IRelayUICommand.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.ComponentModel; -using System.Windows.Input; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.ViewModel { - /// An interface for working with generic and non-generic RelayUICommands. - public interface IRelayUICommand : IRelayCommand { - string Text { get; } - IImage Icon { get; } - IShortcut Shortcut { get; } - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Commands/RelayUICommand.Generic.cs b/WinDirStat.Net.Base/ViewModel/Commands/RelayUICommand.Generic.cs deleted file mode 100644 index d3da8f9..0000000 --- a/WinDirStat.Net.Base/ViewModel/Commands/RelayUICommand.Generic.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -#if WPF -using GalaSoft.MvvmLight.CommandWpf; -#else -using GalaSoft.MvvmLight.Command; -#endif - -namespace WinDirStat.Net.ViewModel { - public class RelayUICommand : RelayCommand, IRelayUICommand { - - #region Fields - - private string text; - private IImage icon; - private readonly IShortcut keyGesture; - - #endregion - - #region Constructors - - public RelayUICommand(string text, IImage icon, Action execute) - : this(text, icon, null, execute, null) - { - } - - public RelayUICommand(string text, IImage icon, Action execute, - Func canExecute) - : this(text, icon, null, execute, canExecute) - { - } - - public RelayUICommand(string text, IImage icon, IShortcut keyGesture, - Action execute) - : this(text, icon, keyGesture, execute, null) - { - } - - public RelayUICommand(string text, IImage icon, IShortcut keyGesture, - Action execute, Func canExecute) - : base(execute, canExecute) - { - this.text = text; - this.icon = icon; - this.keyGesture = keyGesture; - } - - #endregion - - #region Properties - - public string Text { - get => text; - set { - if (text != value) { - text = value; - RaisePropertyChanged(); - } - } - } - - public IImage Icon { - get => icon; - set { - if (icon != value) { - icon = value; - RaisePropertyChanged(); - } - } - } - - public IShortcut Shortcut { - get => keyGesture; - } - - #endregion - - #region Events - - /// Called when the or property has changed. - public event PropertyChangedEventHandler PropertyChanged; - - #endregion - - #region RaisePropertyChanged - - /// Raises the event. - protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Commands/RelayUICommand.cs b/WinDirStat.Net.Base/ViewModel/Commands/RelayUICommand.cs deleted file mode 100644 index 094bdfa..0000000 --- a/WinDirStat.Net.Base/ViewModel/Commands/RelayUICommand.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -#if WPF -using GalaSoft.MvvmLight.CommandWpf; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -#else -using GalaSoft.MvvmLight.Command; -#endif - -namespace WinDirStat.Net.ViewModel { - public class RelayUICommand : RelayCommand, IRelayUICommand { - - #region Fields - - private string text; - private IImage icon; - private readonly IShortcut keyGesture; - - #endregion - - #region Constructors - - public RelayUICommand(string text, IImage icon, Action execute) - : this(text, icon, null, execute, null) - { - } - - public RelayUICommand(string text, IImage icon, Action execute, - Func canExecute) - : this(text, icon, null, execute, canExecute) - { - } - - public RelayUICommand(string text, IImage icon, IShortcut keyGesture, - Action execute) - : this(text, icon, keyGesture, execute, null) - { - } - - public RelayUICommand(string text, IImage icon, IShortcut keyGesture, - Action execute, Func canExecute) - : base(execute, canExecute) - { - this.text = text; - this.icon = icon; - this.keyGesture = keyGesture; - } - - #endregion - - #region Properties - - public string Text { - get => text; - set { - if (text != value) { - text = value; - RaisePropertyChanged(); - } - } - } - - public IImage Icon { - get => icon; - set { - if (icon != value) { - icon = value; - RaisePropertyChanged(); - } - } - } - - public IShortcut Shortcut { - get => keyGesture; - } - - #endregion - - #region Events - - /// Called when the or property has changed. - public event PropertyChangedEventHandler PropertyChanged; - - #endregion - - #region RaisePropertyChanged - - /// Raises the event. - protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Comparers/DriveComparer.cs b/WinDirStat.Net.Base/ViewModel/Comparers/DriveComparer.cs deleted file mode 100644 index 95ca664..0000000 --- a/WinDirStat.Net.Base/ViewModel/Comparers/DriveComparer.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.ViewModel.Drives; - -namespace WinDirStat.Net.ViewModel.Comparers { - /// The sort mode for use in the drive select list. - [Serializable] - public enum DriveSortMode { - None, - Name, - Total, - Free, - UsedTotalBar, - UsedTotalPercent, - [Browsable(false)] - Count, - } - - /// The comparer for s. - public class DriveComparer : SortComparer { - - #region Constructors - - /// Constructs the default . - public DriveComparer() - : base(DriveSortMode.Name, ListSortDirection.Ascending) - { - } - - #endregion - - #region SortComparer Overrides - - /// A secondary comparison that's called when the sort mode comparison returns 0. - /// - /// The first item to compare. - /// The second item to compare. - /// The comparison result. - protected override Comparison GetSortComparison(DriveSortMode mode) { - switch (mode) { - case DriveSortMode.None: - case DriveSortMode.Name: - return SortByNameAndDriveType; - case DriveSortMode.Total: - return SortByTotal; - case DriveSortMode.Free: - return SortByFree; - case DriveSortMode.UsedTotalBar: - case DriveSortMode.UsedTotalPercent: - return SortByPercent; - default: - throw new ArgumentException($"Invalid {typeof(DriveSortMode).Name} ({mode})!", nameof(mode)); - } - } - - /// Gets the comparison method for the specified sort mode. - /// - /// The mode to get the comparison of. - /// The comparison to use. - protected override int SecondaryCompare(DriveItemViewModel a, DriveItemViewModel b) { - return string.Compare(a.Model.Name, b.Model.Name, true); - } - - #endregion - - #region Comparisons - - /// Scores the drives by type so that some are ordered before others. - private static int GetDriveTypeScore(DriveType type) { - switch (type) { - case DriveType.Fixed: return 0; - case DriveType.Removable: return 1; - case DriveType.CDRom: return 2; - case DriveType.Network: return 3; - case DriveType.NoRootDirectory: return 4; - case DriveType.Ram: return 5; - default: return 6; - } - } - - private static int SortByNameAndDriveType(DriveItemViewModel a, DriveItemViewModel b) { - int diff = GetDriveTypeScore(a.Model.DriveType) - GetDriveTypeScore(b.Model.DriveType); - if (diff == 0) - return SortByName(a, b); - return diff; - } - private static int SortByName(DriveItemViewModel a, DriveItemViewModel b) { - return string.Compare(a.Model.Name, b.Model.Name, true); - } - private static int SortByTotal(DriveItemViewModel a, DriveItemViewModel b) { - return a.Model.TotalSize.CompareTo(b.Model.TotalSize); - } - private static int SortByFree(DriveItemViewModel a, DriveItemViewModel b) { - return a.Model.FreeSpace.CompareTo(b.Model.FreeSpace); - } - private static int SortByPercent(DriveItemViewModel a, DriveItemViewModel b) { - return a.Model.Percent.CompareTo(b.Model.Percent); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Comparers/ExtensionComparer.cs b/WinDirStat.Net.Base/ViewModel/Comparers/ExtensionComparer.cs deleted file mode 100644 index ed6534f..0000000 --- a/WinDirStat.Net.Base/ViewModel/Comparers/ExtensionComparer.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.ViewModel.Extensions; - -namespace WinDirStat.Net.ViewModel.Comparers { - /// The sort mode for use in the file types list. - [Serializable] - public enum ExtensionSortMode { - None, - Extension, - Color, - Description, - Bytes, - Percent, - Files, - [Browsable(false)] - Count, - } - - /// The comparer for s. - public class ExtensionComparer : SortComparer { - - #region Constructors - - /// Constructs the default . - public ExtensionComparer() - : base(ExtensionSortMode.Bytes, ListSortDirection.Descending) - { - } - - #endregion - - #region SortComparer Overrides - - /// A secondary comparison that's called when the sort mode comparison returns 0. - /// - /// The first item to compare. - /// The second item to compare. - /// The comparison result. - protected override Comparison GetSortComparison(ExtensionSortMode mode) { - switch (mode) { - case ExtensionSortMode.None: - case ExtensionSortMode.Bytes: - case ExtensionSortMode.Percent: - case ExtensionSortMode.Color: return SortBySize; - case ExtensionSortMode.Extension: return SortByExtension; - case ExtensionSortMode.Description: return SortByDescription; - case ExtensionSortMode.Files: return SortByFiles; - default: - throw new ArgumentException($"Invalid {typeof(ExtensionSortMode).Name} ({mode})!", nameof(mode)); - } - } - - /// Gets the comparison method for the specified sort mode. - /// - /// The mode to get the comparison of. - /// The comparison to use. - protected override int SecondaryCompare(ExtensionItemViewModel a, ExtensionItemViewModel b) { - return string.Compare(a.Model.Extension, b.Model.Extension, true); - } - - #endregion - - #region Comparisons - - private static int SortByExtension(ExtensionItemViewModel a, ExtensionItemViewModel b) { - return string.Compare(a.Model.Extension, b.Model.Extension, true); - } - private static int SortByDescription(ExtensionItemViewModel a, ExtensionItemViewModel b) { - return string.Compare(a.TypeName, b.TypeName, true); - } - private static int SortBySize(ExtensionItemViewModel a, ExtensionItemViewModel b) { - return a.Model.Size.CompareTo(b.Model.Size); - } - private static int SortByFiles(ExtensionItemViewModel a, ExtensionItemViewModel b) { - return a.Model.FileCount - b.Model.FileCount; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Comparers/FileComparer.cs b/WinDirStat.Net.Base/ViewModel/Comparers/FileComparer.cs deleted file mode 100644 index e1d1e30..0000000 --- a/WinDirStat.Net.Base/ViewModel/Comparers/FileComparer.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.ViewModel.Files; - -namespace WinDirStat.Net.ViewModel.Comparers { - /// The sort mode for use in the file tree. - [Serializable] - public enum FileSortMode { - None, - Name, - Subtree, - Percent, - Size, - Items, - Files, - Subdirs, - LastWrite, - LastAccess, - Creation, - Attributes, - [Browsable(false)] - Count, - } - - /// The comparer for s. - public class FileComparer : SortComparer { - - #region Constructors - - /// Constructs the default . - public FileComparer() - : base(FileSortMode.Size, ListSortDirection.Descending) - { - } - - #endregion - - #region SortComparer Overrides - - /// A secondary comparison that's called when the sort mode comparison returns 0. - /// - /// The first item to compare. - /// The second item to compare. - /// The comparison result. - protected override Comparison GetSortComparison(FileSortMode mode) { - switch (mode) { - case FileSortMode.None: - case FileSortMode.Size: - case FileSortMode.Percent: - case FileSortMode.Subtree: return SortBySize; - case FileSortMode.Name: return SortByName; - case FileSortMode.Items: return SortByItems; - case FileSortMode.Files: return SortByFiles; - case FileSortMode.Subdirs: return SortBySubdirs; - case FileSortMode.LastWrite: return SortByLastWrite; - //case FileSortMode.LastAccess: return SortByLastAccess; - //case FileSortMode.Creation: return SortByCreation; - case FileSortMode.Attributes: return SortByAttributes; - default: - throw new ArgumentException($"Invalid {typeof(FileSortMode).Name} ({mode})!", nameof(mode)); - } - } - - /// Gets the comparison method for the specified sort mode. - /// - /// The mode to get the comparison of. - /// The comparison to use. - protected override int SecondaryCompare(FileItemViewModel a, FileItemViewModel b) { - return string.Compare(a.Model.Name, b.Model.Name, true); - } - - #endregion - - #region Comparisons - - private static int SortByName(FileItemViewModel a, FileItemViewModel b) { - return string.Compare(a.Model.Name, b.Model.Name, true); - } - private static int SortBySize(FileItemViewModel a, FileItemViewModel b) { - return a.Model.Size.CompareTo(b.Model.Size); - } - private static int SortByItems(FileItemViewModel a, FileItemViewModel b) { - return a.Model.ItemCount - b.Model.ItemCount; - } - private static int SortByFiles(FileItemViewModel a, FileItemViewModel b) { - return a.Model.FileCount - b.Model.FileCount; - } - private static int SortBySubdirs(FileItemViewModel a, FileItemViewModel b) { - return a.Model.SubdirCount - b.Model.SubdirCount; - } - private static int SortByAttributes(FileItemViewModel a, FileItemViewModel b) { - return a.Model.SortAttributes.CompareTo(b.Model.SortAttributes); - } - private static int SortByLastWrite(FileItemViewModel a, FileItemViewModel b) { - return a.Model.LastWriteTimeUtc.CompareTo(b.Model.LastWriteTimeUtc); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Comparers/SortComparer.cs b/WinDirStat.Net.Base/ViewModel/Comparers/SortComparer.cs deleted file mode 100644 index bd6f19d..0000000 --- a/WinDirStat.Net.Base/ViewModel/Comparers/SortComparer.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using GalaSoft.MvvmLight; - -namespace WinDirStat.Net.ViewModel.Comparers { - /// A helper class for view model comparers. - /// The type of the view model. - /// The type that representings the sort mode. - public abstract class SortComparer : ObservableObject, IComparer, IComparer { - - #region Fields - - /// The current sort direction. - private ListSortDirection direction; - /// The current sort mode. - private TSortMode mode; - /// The current sort comparison. - private Comparison comparison; - - #endregion - - #region Constructor - - /// - /// Constructs the with the specified sort mode in ascending order. - /// - /// - /// The sort mode to start with. - protected SortComparer(TSortMode mode) { - Mode = mode; - } - - /// - /// Constructs the with the specified sort mode and direction. - /// - /// - /// The sort mode to start with. - /// The sort direction to start with. - protected SortComparer(TSortMode mode, ListSortDirection direction) { - Mode = mode; - Direction = direction; - } - - #endregion - - #region IComparer - - /// Compares the two items based on the sort mode and direction. - /// - /// The first item to compare. - /// The second item to compare. - /// The comparison result. - public int Compare(T a, T b) { - int diff = comparison(a, b); - // Always sort alphabetically after initial sort - if (diff == 0) - return SecondaryCompare(a, b); - if (direction == ListSortDirection.Ascending) - return diff; - else - return -diff; - } - /// Compares the two items based on the sort mode and direction. - /// - /// The first item to compare. - /// The second item to compare. - /// The comparison result. - int IComparer.Compare(object a, object b) { - return Compare((T) a, (T) b); - } - - #endregion - - #region Sort Settings - - /// Gets the mode that determines the primary comparison method. - public TSortMode Mode { - get => mode; - set { - if (!mode.Equals(value)) { - mode = value; - comparison = GetSortComparison(mode); - RaisePropertyChanged(); - } - } - } - /// Gets the direction of the sorting. - public ListSortDirection Direction { - get => direction; - set { - if (direction != value) { - direction = value; - RaisePropertyChanged(); - RaisePropertyChanged(nameof(IsDescending)); - } - } - } - /// Gets if the sort direction is in descending order. - public bool IsDescending { - get => direction == ListSortDirection.Descending; - set { - if (IsDescending != value) { - if (value) - direction = ListSortDirection.Descending; - else - direction = ListSortDirection.Ascending; - RaisePropertyChanged(nameof(Direction)); - RaisePropertyChanged(); - } - } - } - - #endregion - - #region Abstract Methods - - /// A secondary comparison that's called when the sort mode comparison returns 0. - /// - /// The first item to compare. - /// The second item to compare. - /// The comparison result. - protected abstract int SecondaryCompare(T a, T b); - - /// Gets the comparison method for the specified sort mode. - /// - /// The mode to get the comparison of. - /// The comparison to use. - protected abstract Comparison GetSortComparison(TSortMode mode); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/ConfigureViewModel.cs b/WinDirStat.Net.Base/ViewModel/ConfigureViewModel.cs deleted file mode 100644 index cff5950..0000000 --- a/WinDirStat.Net.Base/ViewModel/ConfigureViewModel.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services; - -namespace WinDirStat.Net.ViewModel { - /// The view model for the configure dialog. - public partial class ConfigureViewModel : ViewModelWindowBase { - - #region Fields - - // Services - /// Gets the program settings service. - public SettingsService Settings { get; } - /// Gets the UI service. - public IUIService UI { get; } - /// Gets the dialog service. - public IWindowDialogService Dialogs { get; } - - #endregion - - #region Constructors - - /// Constructrs the . - public ConfigureViewModel(SettingsService settings, - IUIService ui, - IWindowDialogService dialog) - { - Settings = settings; - UI = ui; - Dialogs = dialog; - } - - #endregion - - #region Override Properties - - /// Gets the title to display for the window. - public override string Title => "WinDirStat.Net - Settings"; - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.Commands.cs b/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.Commands.cs deleted file mode 100644 index 6da8e36..0000000 --- a/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.Commands.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Drives; - -#if WPF -using GalaSoft.MvvmLight.CommandWpf; -#else -using GalaSoft.MvvmLight.Command; -#endif - -namespace WinDirStat.Net.ViewModel { - partial class DriveSelectViewModel { - - public RelayCommand OK { - get => GetCommand(OnOK); - } - - public RelayCommand SelectFolder { - get => GetCommand(OnSelectFolder); - } - - private void OnOK() { - // Apply the settings for future use - Settings.DriveSelectMode = mode; - Settings.SelectedDrives = SelectedDrives.Select(d => d.Name).ToArray(); - Settings.SelectedFolderPath = folderPath; - Result = new DriveSelectResult(Scanning, - Settings.DriveSelectMode, - Settings.SelectedDrives, - Settings.SelectedFolderPath); - } - - private void OnSelectFolder() { - string newFolder = Dialogs.ShowFolderBrowser(WindowOwner, "WinDirStat.Net - Select Folder", false); - if (newFolder != null) { - FolderPath = newFolder; - } - } - - } -} diff --git a/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.Methods.cs b/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.Methods.cs deleted file mode 100644 index 45f4979..0000000 --- a/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.Methods.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.ViewModel.Drives; - -namespace WinDirStat.Net.ViewModel { - partial class DriveSelectViewModel { - - public void Loaded() { - SelectedDrives.Clear(); - Drives.Model.Refresh(); - Mode = Settings.DriveSelectMode; - FolderPath = Settings.SelectedFolderPath; - var drivesToSelect = Drives.Where(d => Settings.SelectedDrives.Any(n => d.Name == n)); - foreach (DriveItemViewModel drive in drivesToSelect) - SelectedDrives.Add(drive); - } - - public void SortDrives() { - Drives.Sort(DriveComparer.Compare); - } - - public void ListGotFocus() { - Mode = DriveSelectMode.Individual; - } - - } -} diff --git a/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.cs b/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.cs deleted file mode 100644 index dcd634f..0000000 --- a/WinDirStat.Net.Base/ViewModel/DriveSelectViewModel.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Services; -using WinDirStat.Net.ViewModel; -using WinDirStat.Net.ViewModel.Comparers; -using WinDirStat.Net.ViewModel.Drives; - -namespace WinDirStat.Net.ViewModel { - /// The view model for the drive select dialog. - public partial class DriveSelectViewModel : ViewModelWindowBase { - - #region Fields - - // Services - /// Gets the program settings service. - public SettingsService Settings { get; } - /// Gets the UI service. - public IUIService UI { get; } - /// Gets the dialog service. - public IWindowDialogService Dialogs { get; } - /// Gets the icon cache service. - public IIconCacheService IconCache { get; } - /// Gets the scanning service. - public ScanningService Scanning { get; } - - // Collections - /// Gets the drive collection. - public DriveItemViewModelCollection Drives { get; } - /// Gets the comparer for the drives. - public DriveComparer DriveComparer { get; } - - // Settings - /// The root path selection mode. - private DriveSelectMode mode; - /// Gets the selected individual drives. - public ObservableCollection SelectedDrives { get; } - /// The current folder path. - private string folderPath; - - // State - /// The result of the drive selection. - private DriveSelectResult result; - /// True if the current mode's selection is valid. - private bool validSelection; - - #endregion - - #region Constructors - - /// Constructrs the . - public DriveSelectViewModel(SettingsService settings, - IUIService ui, - IWindowDialogService dialog, - IIconCacheService iconCache, - ScanningService scanning) - { - Settings = settings; - UI = ui; - Dialogs = dialog; - IconCache = iconCache; - Scanning = scanning; - - Drives = new DriveItemViewModelCollection(this); - DriveComparer = new DriveComparer(); - - SelectedDrives = new ObservableCollection(); - SelectedDrives.CollectionChanged += OnSelectedDrivesChanged; - } - - #endregion - - #region Override Properties - - /// Gets the title to display for the window. - public override string Title => "WinDirStat.Net - Drive Select"; - - #endregion - - #region Properties - - /// Gets or sets the root path selection mode. - public DriveSelectMode Mode { - get => mode; - set { - if (mode != value) { - mode = value; - ValidateSelection(); - RaisePropertyChanged(); - } - } - } - - /// Gets or sets the current folder path. - public string FolderPath { - get => folderPath; - set { - if (folderPath != value) { - folderPath = value; - if (mode == DriveSelectMode.Folder) - ValidateSelection(); - RaisePropertyChanged(); - } - } - } - - /// Gets or sets if the current selection is valid. - public bool IsValidSelection { - get => validSelection; - private set { - if (validSelection != value) { - validSelection = value; - RaisePropertyChanged(); - } - } - } - - /// Gets the result root paths. - public DriveSelectResult Result { - get => result; - private set => Set(ref result, value); - } - - #endregion - - #region Validation - - /// Validates the current mode's selection. - private void ValidateSelection() { - switch (mode) { - case DriveSelectMode.All: - IsValidSelection = true; - break; - case DriveSelectMode.Individual: - IsValidSelection = SelectedDrives.Count > 0; - break; - case DriveSelectMode.Folder: - try { - IsValidSelection = Directory.Exists(Path.GetFullPath(folderPath)); - } - catch { - IsValidSelection = false; - } - break; - } - } - - #endregion - - #region Event Handlers - - /// Validates the selection when the drive selection changes. - private void OnSelectedDrivesChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (mode == DriveSelectMode.Individual) - ValidateSelection(); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Drives/DriveItemViewModel.cs b/WinDirStat.Net.Base/ViewModel/Drives/DriveItemViewModel.cs deleted file mode 100644 index c04a7f7..0000000 --- a/WinDirStat.Net.Base/ViewModel/Drives/DriveItemViewModel.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.ViewModel.Drives { - /// The view model that represents a drive item. - public class DriveItemViewModel : ObservableObject { - - #region Fields - - /// The collection containing this drive item view model. - private readonly DriveItemViewModelCollection drives; - /// The model that this view model represents. - public DriveItem Model { get; } - - /// The display icon for the drive. - private IImage icon; - /// The display name for the drive. - private string displayName; - - #endregion - - #region Constructors - - /// Constructs the see . - /// - /// The collection containing this drive item view model. - /// The model that this view model represents. - public DriveItemViewModel(DriveItemViewModelCollection drives, DriveItem model) { - this.drives = drives; - Model = model; - - IIconAndName iconName = IconCache.CacheIconAndDisplayName(Name); - if (iconName != null) { - Icon = iconName.Icon; - DisplayName = iconName.Name; - } - else { - Icon = IconCache.VolumeIcon; - DisplayName = $"({PathUtils.TrimSeparatorEnd(Name)})"; - } - } - - #endregion - - #region Properties - - /// Gets the display icon for the drive. - public IImage Icon { - get => icon; - private set => Set(ref icon, value); - } - - /// Gets the display name for the drive. - public string DisplayName { - get => displayName; - private set => Set(ref displayName, value); - } - - /// Gets the name/path of the drive. - public string Name => Model.Name; - /// Gets the total size of the drive. - public long TotalSize => Model.TotalSize; - /// Gets the freespace on the drive in bytes. - public long FreeSpace => Model.FreeSpace; - /// Gets the type of the drive. - public DriveType DriveType => Model.DriveType; - /// Gets the partition format of the drive. - public string DriveFormat => Model.DriveFormat; - /// Gets the used space on the drive in bytes. - public long UsedSpace => Model.UsedSpace; - /// Gets the used percentage of the drive. - public double Percent => Model.Percent; - - /// Gets the icon cache service. - private IIconCacheService IconCache => drives.IconCache; - - /// Gets the program settings service. - private SettingsService Settings => drives.Settings; - - /// Gets the icon cache mode setting. - private IconCacheMode CacheMode => drives.Settings.IconCacheMode; - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Drives/DriveItemViewModelCollection.cs b/WinDirStat.Net.Base/ViewModel/Drives/DriveItemViewModelCollection.cs deleted file mode 100644 index c2d329b..0000000 --- a/WinDirStat.Net.Base/ViewModel/Drives/DriveItemViewModelCollection.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Services; - -namespace WinDirStat.Net.ViewModel.Drives { - /// A collection manager for s. - public class DriveItemViewModelCollection - : ObservablePropertyCollectionObject, IReadOnlyList - { - #region Fields - - /// Gets the drive select view model that contains this collection. - public DriveSelectViewModel ViewModel { get; } - /// Gets the model collection that this view model represents. - public DriveItems Model { get; } - - // Services - /// Gets the scanning service. - public ScanningService Scanning { get; } - /// Gets the icon cache service. - public IIconCacheService IconCache { get; } - /// Gets the program settings service. - public SettingsService Settings { get; } - /// Gets the UI service. - public IUIService UI { get; } - - /// The list of sorted drive items. - private readonly List drives; - - #endregion - - #region Constructors - - /// Constructs the . - /// - /// The main view model containing this collection. - public DriveItemViewModelCollection(DriveSelectViewModel viewModel) { - ViewModel = viewModel; - Scanning = ViewModel.Scanning; - Model = Scanning.Drives; - IconCache = ViewModel.IconCache; - Settings = ViewModel.Settings; - UI = ViewModel.UI; - - drives = new List(); - - Model.CollectionChanged += OnModelCollectionChanged; - } - - #endregion - - #region Event Handlers - - private void OnModelCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - UI.Invoke(() => { - switch (e.Action) { - case NotifyCollectionChangedAction.Reset: - drives.Clear(); - for (int i = 0; i < Model.Count; i++) { - DriveItem newItem = Model[i]; - DriveItemViewModel newItemViewModel = new DriveItemViewModel(this, newItem); - drives.Add(newItemViewModel); - } - Sort(ViewModel.DriveComparer.Compare); - //RaiseCollectionChanged(NotifyCollectionChangedAction.Reset); - break; - case NotifyCollectionChangedAction.Add: - //List newItemViewModels = new List(); - for (int i = 0; i < e.NewItems.Count; i++) { - DriveItem newItem = (DriveItem) e.NewItems[i]; - DriveItemViewModel newItemViewModel = new DriveItemViewModel(this, newItem); - drives.Add(newItemViewModel); - //newItemViewModels.Add(newItemViewModel); - } - Sort(ViewModel.DriveComparer.Compare); - //RaiseCollectionChanged(NotifyCollectionChangedAction.Add, newItemViewModels, e.NewStartingIndex); - break; - case NotifyCollectionChangedAction.Remove: - //List oldItemViewModels = new List(); - for (int i = 0; i < e.OldItems.Count; i++) { - DriveItem oldItem = (DriveItem) e.OldItems[i]; - DriveItemViewModel oldItemViewModel = drives.Find(d => d.Model == oldItem); - //oldItemViewModel.Dispose(); - drives.Remove(oldItemViewModel); - //oldItemViewModels.Add(oldItemViewModel); - } - Sort(ViewModel.DriveComparer.Compare); - //RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, oldItemViewModels, e.OldStartingIndex); - break; - } - }); - } - - #endregion - - #region Properties - - /// Gets the number of drives. - public int Count => drives.Count; - - /// Gets the drive item at the specified index in the collection. - public DriveItemViewModel this[int index] => drives[index]; - - #endregion - - #region Sort - - /// Sorts the collection based on the comparison. - /// - /// The comparison to sort with. - public void Sort(Comparison comparison) { - drives.Sort(comparison); - RaiseCollectionChanged(NotifyCollectionChangedAction.Reset); - } - - #endregion - - #region IEnumerator Implementation - - /// Gets the enumerator for the drive items. - IEnumerator IEnumerable.GetEnumerator() { - return drives.GetEnumerator(); - } - /// Gets the enumerator for the drive items. - IEnumerator IEnumerable.GetEnumerator() { - return drives.GetEnumerator(); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Extensions/ExtensionItemViewModel.cs b/WinDirStat.Net.Base/ViewModel/Extensions/ExtensionItemViewModel.cs deleted file mode 100644 index 1c52a2e..0000000 --- a/WinDirStat.Net.Base/ViewModel/Extensions/ExtensionItemViewModel.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.ViewModel.Extensions { - /// The view model that represents an . - public class ExtensionItemViewModel : ObservableObject, IDisposable { - - #region Constants - - /// The used to represent a non-file. - public static readonly ExtensionItemViewModel NotAFile = new ExtensionItemViewModel(); - - #endregion - - #region Fields - - /// The collection containing this item. - private readonly ExtensionItemViewModelCollection extensions; - /// Gets the model that this view model represents. - public ExtensionItem Model { get; } - - /// The icon of the associated file type. - private IImage icon; - /// The type name of the associated file type. - private string typeName; - /// The cache state for the icon. - private IconCacheState cacheState; - /// True if events have been hooked to the model. - private bool eventsHooked; - /// The preview image for the file palette color. - private IImage preview; - - #endregion - - #region Constructors - - /// - /// Constructs an used to represent a non-file. - /// - private ExtensionItemViewModel() { - Model = ExtensionItem.NotAFile; - } - - /// Constructs an . - /// - /// The collection containing this item. - /// The model that this view model item represents. - public ExtensionItemViewModel(ExtensionItemViewModelCollection extensions, ExtensionItem model) { - this.extensions = extensions; - Model = model; - icon = IconCache.FileIcon; - if (IsEmptyExtension || Extension.Contains(" ")) { - // Extensions with spaces have no rights, so says Windows - typeName = "File"; - cacheState = IconCacheState.Cached; - } - else { - typeName = model.Extension.TrimStart('.').ToUpper() + " File"; - if (CacheMode >= IconCacheMode.FileType) - LoadIcon(); - } - HookEvents(); - } - - /// Disposes of the . - /*~ExtensionItemViewModel() { - Dispose(); - }*/ - - #endregion - - #region Event Handlers - - private void OnModelChanged(ExtensionItem sender, ExtensionItemEventArgs e) { - switch (e.Action) { - case ExtensionItemAction.ColorChanged: - Preview = Settings.GetFilePalettePreview(e.Index); - break; - case ExtensionItemAction.GetViewModel: - e.ViewModel = this; - break; - } - } - - #endregion - - #region CacheIcon - - /// Attempts to load the icon if it has not already been loaded. - public void LoadIcon() { - if (cacheState == IconCacheState.NotCached) { - cacheState = IconCacheState.Caching; - IconCache.CacheFileTypeAsync(Extension, OnCacheIconAndTypeName); - } - } - - /// The callback for asynchronously caching the file type icon and type name. - /// - /// The resulting icon and type name. - private void OnCacheIconAndTypeName(IIconAndName iconName) { - if (iconName != null) { - Icon = iconName.Icon; - TypeName = iconName.Name; - } - // Even if "I failed, I failed, I failed", we're not gonna reattempt this - cacheState = IconCacheState.Cached; - } - - #endregion - - #region Properties - - /// Gets the name of the extension with the dot. - public string Extension => Model.Extension; - /// Gets the total size of all the files that use this extension. - public long Size => Model.Size; - /// Gets the number of files that use this extension. - public int FileCount => Model.FileCount; - /// Gets this extension's size relative to the total used space. - public double Percent => Model.Percent; - /// Gets if this extension is the empty extension with nothing after the dot. - public bool IsEmptyExtension => Model.IsEmptyExtension; - - /// Gets the icon of the associated file type. - public IImage Icon { - get => icon; - private set => Set(ref icon, value); - } - - /// Gets the type name of the associated file type. - public string TypeName { - get => typeName; - private set => Set(ref typeName, value); - } - - /// Gets the preview image for the file palette color. - public IImage Preview { - get => preview; - internal set => Set(ref preview, value); - } - - /// Gets the cache state for the icon. - public IconCacheState CacheState { - get => cacheState; - private set => Set(ref cacheState, value); - } - - /// Gets the icon cache service. - private IIconCacheService IconCache => extensions.IconCache; - - /// Gets the program settings service. - private SettingsService Settings => extensions.Settings; - - /// Gets the icon cache mode setting. - private IconCacheMode CacheMode => extensions.Settings.IconCacheMode; - - #endregion - - #region IDisposable Implementation - - /// Disposes of the . - public void Dispose() { - UnhookEvents(); - } - - /// Hooks up events to the model changed event. - private void HookEvents() { - if (!eventsHooked) { - eventsHooked = true; - Model.Changed += OnModelChanged; - } - } - - /// Unhooks events from the model changed event. - private void UnhookEvents() { - if (eventsHooked) { - eventsHooked = false; - Model.Changed -= OnModelChanged; - } - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Extensions/ExtensionItemViewModelCollection.cs b/WinDirStat.Net.Base/ViewModel/Extensions/ExtensionItemViewModelCollection.cs deleted file mode 100644 index 8d87939..0000000 --- a/WinDirStat.Net.Base/ViewModel/Extensions/ExtensionItemViewModelCollection.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Services; -using WinDirStat.Net.Utils; -using static WinDirStat.Net.Model.Extensions.ExtensionItem; - -namespace WinDirStat.Net.ViewModel.Extensions { - /// A collection manager for s. - public class ExtensionItemViewModelCollection - : ObservablePropertyCollectionObject, IReadOnlyList - { - #region Fields - - /// Gets the main view model that contains this collection. - public MainViewModel ViewModel { get; } - public ScanningService Scanning { get; } - public ExtensionItems Model { get; } - public IIconCacheService IconCache { get; } - /// Gets the images service. - public ImagesServiceBase Images { get; } - public SettingsService Settings { get; } - public IUIService UI { get; } - - /// The collection of mapped extension items. - private readonly Dictionary extensions; - /// The list of sorted extension items. - private readonly List sortedExtensions; - /// - /// True if the file tree scanner is not open, and the collection should hide all extensions. - /// - private bool isNotOpen; - - #endregion - - #region Constructors - - /// Constructs the . - /// - /// The main view model containing this collection. - public ExtensionItemViewModelCollection(MainViewModel viewModel) { - ViewModel = viewModel; - Scanning = ViewModel.Scanning; - Model = ViewModel.Scanning.Extensions; - IconCache = ViewModel.IconCache; - Images = ViewModel.Images; - Settings = ViewModel.Settings; - UI = ViewModel.UI; - - isNotOpen = false; - extensions = new Dictionary(); - sortedExtensions = new List(); - - ViewModel.Scanning.PropertyChanged += OnScanningPropertyChanged; - Model.CollectionChanged += OnModelCollectionChanged; - } - - #endregion - - #region Properties - - /// Gets the number of extensions. This value is always zero while scanning/refreshing. - public int Count => (isNotOpen ? 0 : extensions.Count); - - /// Gets if the scanner is not open and this collection should hide its items. - private bool IsNotOpen { - get => isNotOpen; - set { - if (isNotOpen != value) { - isNotOpen = value; - if (extensions.Count > 0) { - UI.Invoke(() => { - RaisePropertyChanged(nameof(Count)); - RaiseCollectionChanged(NotifyCollectionChangedAction.Reset); - }); - } - } - } - } - - #endregion - - #region Event Handlers - - private void OnScanningPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { - switch (e.PropertyName) { - case nameof(ScanningService.IsOpen): - IsNotOpen = !Scanning.IsOpen; - break; - } - } - - private void OnModelCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - // We must be sorting, nothing to do here - if (!IsNotOpen && e.Action == NotifyCollectionChangedAction.Reset) - return; - - Debug.Assert(IsNotOpen, "Cannot change collection while not scanning!"); - - switch (e.Action) { - case NotifyCollectionChangedAction.Reset: - sortedExtensions.Clear(); - for (int i = 0; i < sortedExtensions.Count; i++) { - ExtensionItemViewModel oldItemViewModel = sortedExtensions[i]; - oldItemViewModel.Dispose(); - } - extensions.Clear(); - for (int i = 0; i < Model.Count; i++) { - ExtensionItem newItem = Model[i]; - ExtensionItemViewModel newItemViewModel = new ExtensionItemViewModel(this, newItem); - sortedExtensions.Add(newItemViewModel); - extensions.Add(newItem.Extension, newItemViewModel); - } - break; - case NotifyCollectionChangedAction.Add: - for (int i = 0; i < e.NewItems.Count; i++) { - ExtensionItem newItem = (ExtensionItem) e.NewItems[i]; - ExtensionItemViewModel newItemViewModel = new ExtensionItemViewModel(this, newItem); - sortedExtensions.Add(newItemViewModel); - extensions.Add(newItem.Extension, newItemViewModel); - } - break; - case NotifyCollectionChangedAction.Remove: - for (int i = 0; i < e.OldItems.Count; i++) { - ExtensionItem oldItem = (ExtensionItem) e.OldItems[i]; - ExtensionItemViewModel oldItemViewModel = extensions[oldItem.Extension]; - oldItemViewModel.Dispose(); - sortedExtensions.Remove(oldItemViewModel); - extensions.Remove(oldItem.Extension); - } - break; - } - } - - #endregion - - #region Sort - - /// Sorts the collection based on the comparison. - /// - /// The comparison to sort with. - public void Sort(Comparison comparison) { - sortedExtensions.Sort(comparison); - RaiseCollectionChanged(NotifyCollectionChangedAction.Reset); - } - - #endregion - - #region Accessors - - /// Gets the extension item at the specified index in the collection. - public ExtensionItemViewModel this[int index] { - get { - if (IsNotOpen) - throw new IndexOutOfRangeException(nameof(index)); - return sortedExtensions[index]; - } - } - - /// Gets the extension item in the collection with the specified extension. - public ExtensionItemViewModel this[string extension] { - get => extensions[NormalizeExtension(extension)]; - } - - /// Gets if the collection contains the extension. - /// - /// The extension to check for. - /// True if the collection contains the extension. - public bool ContainsExtension(string extension) { - return extensions.ContainsKey(NormalizeExtension(extension)); - } - - /// Tries to get the extension item associated with the extension. - /// - /// The extension of the item to look for. - /// The output item result. - /// True if the extension was found. - public bool TryGetItem(string extension, out ExtensionItemViewModel item) { - return extensions.TryGetValue(NormalizeExtension(extension), out item); - } - - #endregion - - #region IEnumeratable Implementation - - /// Gets the enumerator for the sorted extension list. - public IEnumerator GetEnumerator() { - if (IsNotOpen) - return Enumerator.Empty(); - return sortedExtensions.GetEnumerator(); - } - - /// Gets the enumerator for the sorted extension list. - IEnumerator IEnumerable.GetEnumerator() { - if (IsNotOpen) - return Enumerator.Empty(); - return sortedExtensions.GetEnumerator(); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/Collection/FileItemViewModelCollection.cs b/WinDirStat.Net.Base/ViewModel/Files/Collection/FileItemViewModelCollection.cs deleted file mode 100644 index d1e21d2..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/Collection/FileItemViewModelCollection.cs +++ /dev/null @@ -1,394 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Diagnostics; -using System.Linq; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.ViewModel.Files { - /// The internal modifiable collection. - internal class FileItemViewModelCollection - : ObservableCollectionObject, IList, IReadOnlyFileItemViewModelCollection - { - #region Fields - - /// The owner of this collection. - private readonly FileItemViewModel parent; - /// The collection of file item view models. - private readonly List list = new List(); - - #endregion - - #region Constructors - - /// Constructs a for empty use. - public FileItemViewModelCollection() { - // Empty collection for readonly use only - } - - /// Constructs a for normal use. - /// - /// The owner of this collection. - public FileItemViewModelCollection(FileItemViewModel parent) { - this.parent = parent; - } - - #endregion - - #region RaiseCollectionReset - - /// - /// Raises a special collection reset event, which allows the to - /// properly make changes to the list. - /// - /// - /// The new current list of the collection. - /// The old list of the collection. - private void RaiseCollectionReset(List list, List oldList) { - Debug.Assert(!IsRaisingEvent); - IsRaisingEvent = true; - try { - parent.OnChildrenReset(list, oldList); - InvokeCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - } - finally { - IsRaisingEvent = false; - } - } - - /// Raises a new event. - /// - /// The arguments for the event. - protected override void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) { - //Debug.Assert(!isRaisingEvent); - ThrowOnReentrancy(); - IsRaisingEvent = true; - try { - parent.OnChildrenChanged(e); - InvokeCollectionChanged(e); - } - finally { - IsRaisingEvent = false; - } - } - - #endregion - - #region Throw Helpers - - /// Throws an exception if the item is not valid for adding to the collection. - /// - /// The item to check. - private void ThrowIfValueIsNullOrHasParent(FileItemViewModel item) { - if (item == null) - throw new ArgumentNullException(nameof(item)); - if (item.Parent != null) - throw new ArgumentException("The item already has a parent", nameof(item)); - } - - #endregion - - #region Properties - - /// Gets or sets the item at the specified index in the collection. - public FileItemViewModel this[int index] { - get => list[index]; - set { - ThrowOnReentrancy(); - var oldItem = list[index]; - if (oldItem == value) - return; - ThrowIfValueIsNullOrHasParent(value); - list[index] = value; - RaiseCollectionChanged(NotifyCollectionChangedAction.Replace, value, oldItem, index); - } - } - - /// Gets the number of items in the collection. - public int Count => list.Count; - - #endregion - - #region Sorting - - /// Sorts the collection based on the comparison. - /// - /// The comparison to sort with. - public void Sort(Comparison comparison) { - if (list.Count > 0) { - List oldList = list.GetFullRange(); - list.Sort(comparison); - RaiseCollectionReset(list, oldList); - } - } - - #endregion - - #region Accessors - - /// Checks if the collection contains the specified view model item. - /// - /// The view model item to check for. - /// True if the collection contains the item. - public bool Contains(FileItemViewModel item) { - return IndexOf(item) >= 0; - } - - /// Checks if the collection contains the specified model item. - /// - /// The model item to check for. - /// True if the collection contains the item. - public bool Contains(FileItem item) { - return IndexOf(item) >= 0; - } - - /// Gets the index of the specified view model item in the collection. - /// - /// The item to get the index of. - /// The index of the item if it exists in the collection, otherwise -1. - public int IndexOf(FileItemViewModel item) { - if (item == null || item.Parent != parent) - return -1; - else - return list.IndexOf(item); - } - - /// Gets the index of the specified model item in the collection. - /// - /// The item to get the index of. - /// The index of the item if it exists in the collection, otherwise -1. - public int IndexOf(FileItemBase item) { - if (item == null) - return -1; - else - return list.FindIndex(n => n.Model == item); - } - - /// Finds the view model item that contains this model item. - /// - /// The model item to look for. - /// The view model item that contains this model item, null if none was found. - public FileItemViewModel Find(FileItemBase item) { - return list.Find(v => v.Model == item); - } - - /// Converts the collection to an array. - /// - /// The new array of the elements. - public FileItemViewModel[] ToArray() { - return list.ToArray(); - } - - /// Copies the collection to the specified array. - /// - /// The array to copy the items to. - /// The index to start copying items to in the array. - public void CopyTo(FileItemViewModel[] array, int arrayIndex) { - list.CopyTo(array, arrayIndex); - } - - #endregion - - #region Add - - /// Adds the item to the end of collection. - /// - /// The item to add. - public void Add(FileItemViewModel item) { - ThrowOnReentrancy(); - ThrowIfValueIsNullOrHasParent(item); - //item.Parent = parent; - list.Add(item); - RaiseCollectionChanged(NotifyCollectionChangedAction.Add, item, list.Count - 1); - } - - /*public void AddSilent(FileItemViewModel item) { - ThrowOnReentrancy(); - ThrowIfValueIsNullOrHasParent(item); - list.Add(item); - }*/ - - /// Adds the items to the end of collection. - /// - /// The items to add. - public void AddRange(IEnumerable items) { - InsertRange(list.Count, items); - } - - #endregion - - #region Insert - - /// Inserts the item at the specified index in the collection. - /// - /// The index to insert at. - /// The item to insert. - public void Insert(int index, FileItemViewModel item) { - ThrowOnReentrancy(); - ThrowIfValueIsNullOrHasParent(item); - //item.Parent = parent; - list.Insert(index, item); - RaiseCollectionChanged(NotifyCollectionChangedAction.Add, item, index); - } - - /// Inserts the items at the specified index in the collection. - /// - /// The index to insert at. - /// The items to insert. - public void InsertRange(int index, IEnumerable items) { - if (items == null) - throw new ArgumentNullException(nameof(items)); - ThrowOnReentrancy(); - List newItems = items.ToList(); - if (newItems.Count == 0) - return; - foreach (FileItemViewModel item in newItems) { - ThrowIfValueIsNullOrHasParent(item); - //item.Parent = parent; - } - list.InsertRange(index, newItems); - RaiseCollectionChanged(NotifyCollectionChangedAction.Add, newItems, index); - } - - #endregion - - #region Remove - - /// Removes the items at the specified index in the collection. - /// - /// The index to remove the item at. - public void RemoveAt(int index) { - ThrowOnReentrancy(); - var oldItem = list[index]; - //oldItem.Parent = null; - list.RemoveAt(index); - RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, oldItem, index); - } - - /// Removes the itemss at the specified index in the collection. - /// - /// The index to remove the items at. - /// The number of items to remove. - public void RemoveRange(int index, int count) { - ThrowOnReentrancy(); - if (count == 0) - return; - var oldItems = list.GetRange(index, count); - //for (int i = 0; i < oldItems.Count; i++) - // oldItems[i].Parent = null; - list.RemoveRange(index, count); - RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, oldItems, index); - } - - /// Removes the specified view model item from the collection. - /// - /// The view model item to remove. - /// True if the item was found and removed. - public bool Remove(FileItemViewModel item) { - int pos = IndexOf(item); - if (pos >= 0) { - RemoveAt(pos); - return true; - } - else { - return false; - } - } - - /// Removes the specified model item from the collection. - /// - /// The model item to remove. - /// True if the item was found and removed. - public bool Remove(FileItemBase item) { - int pos = list.FindIndex(n => n.Model == item); - if (pos >= 0) { - RemoveAt(pos); - return true; - } - else { - return false; - } - } - - /*public void RemoveAll(Predicate match) { - if (match == null) - throw new ArgumentNullException(nameof(match)); - ThrowOnReentrancy(); - int firstToRemove = 0; - for (int i = 0; i < list.Count; i++) { - bool removeItem; - IsRaisingEvent = true; - try { - removeItem = match(list[i]); - } - finally { - IsRaisingEvent = false; - } - if (!removeItem) { - if (firstToRemove < i) { - RemoveRange(firstToRemove, i - firstToRemove); - i = firstToRemove - 1; - } - else { - firstToRemove = i + 1; - } - Debug.Assert(firstToRemove == i + 1); - } - } - if (firstToRemove < list.Count) { - RemoveRange(firstToRemove, list.Count - firstToRemove); - } - }*/ - - #endregion - - #region Move - - /*public void Move(int index, int oldIndex) { - ThrowOnReentrancy(); - FileItemViewModel item = list[oldIndex]; - list.RemoveAt(oldIndex); - list.Insert(index, item); - RaiseCollectionChanged(NotifyCollectionChangedAction.Move, item, index, oldIndex); - }*/ - - #endregion - - #region Clear - - /// Clears the collection. - public void Clear() { - ThrowOnReentrancy(); - if (list.Count > 0) { - //var oldList = new List(list); - //list.Clear(); - var oldList = list.GetFullRange(); - //for (int i = 0; i < oldList.Count; i++) - // oldList[i].Parent = null; - list.Clear(); - RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, oldList, 0); - } - } - - #endregion - - #region Explicit Interface Implementation - - /// Gets if the collection is readonly - it is not. - bool ICollection.IsReadOnly => false; - - /// Gets the enumerator for the collection. - IEnumerator IEnumerable.GetEnumerator() { - return list.GetEnumerator(); - } - - /// Gets the enumerator for the collection. - IEnumerator IEnumerable.GetEnumerator() { - return list.GetEnumerator(); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/Collection/IReadOnlyFileItemViewModelCollection.cs b/WinDirStat.Net.Base/ViewModel/Files/Collection/IReadOnlyFileItemViewModelCollection.cs deleted file mode 100644 index 45a4cc3..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/Collection/IReadOnlyFileItemViewModelCollection.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.ViewModel.Files { - /// - /// The public interface for the readonly part of the collection. - /// - public interface IReadOnlyFileItemViewModelCollection - : INotifyCollectionChanged, IReadOnlyList - { - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.Flags.cs b/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.Flags.cs deleted file mode 100644 index 81109ce..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.Flags.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.ViewModel.Files { - partial class FileItemViewModel { - - private FileItemViewModelFlags flags = FileItemViewModelFlags.None; - -#pragma warning disable 0649, IDE1006 - /*private bool isVisible { - get => flags.HasFlag(FileNodeViewFlags.Visible); - set => flags.SetFlag(FileNodeViewFlags.Visible, value); - }*/ - private bool isHidden { - get => flags.HasFlag(FileItemViewModelFlags.Hidden); - set => flags = flags.SetFlag(FileItemViewModelFlags.Hidden, value); - } - private bool isSelected { - get => flags.HasFlag(FileItemViewModelFlags.Selected); - set => flags = flags.SetFlag(FileItemViewModelFlags.Selected, value); - } - private bool isExpanded { - get => flags.HasFlag(FileItemViewModelFlags.Expanded); - set => flags = flags.SetFlag(FileItemViewModelFlags.Expanded, value); - } - private bool isEditing { - get => flags.HasFlag(FileItemViewModelFlags.Editing); - set => flags = flags.SetFlag(FileItemViewModelFlags.Editing, value); - } - private bool isEventsHooked { - get => flags.HasFlag(FileItemViewModelFlags.EventsHooked); - set => flags = flags.SetFlag(FileItemViewModelFlags.EventsHooked, value); - } - private bool isWaitingForExtensionIcon { - get => flags.HasFlag(FileItemViewModelFlags.WaitingForExtensionIcon); - set => flags = flags.SetFlag(FileItemViewModelFlags.WaitingForExtensionIcon, value); - } - private bool exists { - get => flags.HasFlag(FileItemViewModelFlags.Exists); - set => flags = flags.SetFlag(FileItemViewModelFlags.Exists, value); - } -#pragma warning restore 0649, IDE1006 - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.FlatList.cs b/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.FlatList.cs deleted file mode 100644 index b6d9c85..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.FlatList.cs +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Diagnostics; - -namespace WinDirStat.Net.ViewModel.Files { - // This part of SharpTreeNode controls the 'flat list' data structure, which emulates - // a big flat list containing the whole tree; allowing access by visible index. - partial class FileItemViewModel { - /// The parent in the flat list - internal FileItemViewModel listParent; - /// Left/right nodes in the flat list - private FileItemViewModel left, right; - - internal FileTreeFlattener treeFlattener; - - /// Subtree height in the flat list tree - private byte height = 1; - - /// Length in the flat list, including children (children within the flat list). -1 = invalidated - private int totalListLength = -1; - - private int Balance { - get { return Height(right) - Height(left); } - } - - static int Height(FileItemViewModel node) { - return node != null ? node.height : 0; - } - - internal FileItemViewModel GetListRoot() { - FileItemViewModel node = this; - while (node.listParent != null) - node = node.listParent; - return node; - } - - #region Debugging - [Conditional("DEBUG")] - void CheckRootInvariants() { - GetListRoot().CheckInvariants(); - } - - [Conditional("DATACONSISTENCYCHECK")] - void CheckInvariants() { - Debug.Assert(left == null || left.listParent == this); - Debug.Assert(right == null || right.listParent == this); - Debug.Assert(height == 1 + Math.Max(Height(left), Height(right))); - Debug.Assert(Math.Abs(this.Balance) <= 1); - Debug.Assert(totalListLength == -1 || totalListLength == (left != null ? left.totalListLength : 0) + (isVisible ? 1 : 0) + (right != null ? right.totalListLength : 0)); - if (left != null) left.CheckInvariants(); - if (right != null) right.CheckInvariants(); - } - - [Conditional("DEBUG")] - static void DumpTree(FileItemViewModel node) { - node.GetListRoot().DumpTree(); - } - - [Conditional("DEBUG")] - void DumpTree() { - Debug.Indent(); - if (left != null) - left.DumpTree(); - Debug.Unindent(); - Debug.WriteLine("{0}, totalListLength={1}, height={2}, Balance={3}, isVisible={4}", ToString(), totalListLength, height, Balance, isVisible); - Debug.Indent(); - if (right != null) - right.DumpTree(); - Debug.Unindent(); - } - #endregion - - #region GetNodeByVisibleIndex / GetVisibleIndexForNode - internal static FileItemViewModel GetNodeByVisibleIndex(FileItemViewModel root, int index) { - root.GetTotalListLength(); // ensure all list lengths are calculated - Debug.Assert(index >= 0); - Debug.Assert(index < root.totalListLength); - FileItemViewModel node = root; - while (true) { - if (node.left != null && index < node.left.totalListLength) { - node = node.left; - } - else { - if (node.left != null) { - index -= node.left.totalListLength; - } - if (node.isVisible) { - if (index == 0) - return node; - index--; - } - node = node.right; - } - } - } - - internal static int GetVisibleIndexForNode(FileItemViewModel node) { - int index = node.left != null ? node.left.GetTotalListLength() : 0; - while (node.listParent != null) { - if (node == node.listParent.right) { - if (node.listParent.left != null) - index += node.listParent.left.GetTotalListLength(); - if (node.listParent.isVisible) - index++; - } - node = node.listParent; - } - return index; - } - #endregion - - #region Balancing - /// - /// Balances the subtree rooted in and recomputes the 'height' field. - /// This method assumes that the children of this node are already balanced and have an up-to-date 'height' value. - /// - /// The new root node - static FileItemViewModel Rebalance(FileItemViewModel node) { - Debug.Assert(node.left == null || Math.Abs(node.left.Balance) <= 1); - Debug.Assert(node.right == null || Math.Abs(node.right.Balance) <= 1); - // Keep looping until it's balanced. Not sure if this is stricly required; this is based on - // the Rope code where node merging made this necessary. - while (Math.Abs(node.Balance) > 1) { - // AVL balancing - // note: because we don't care about the identity of concat nodes, this works a little different than usual - // tree rotations: in our implementation, the "this" node will stay at the top, only its children are rearranged - if (node.Balance > 1) { - if (node.right.Balance < 0) { - node.right = node.right.RotateRight(); - } - node = node.RotateLeft(); - // If 'node' was unbalanced by more than 2, we've shifted some of the inbalance to the left node; so rebalance that. - node.left = Rebalance(node.left); - } - else if (node.Balance < -1) { - if (node.left.Balance > 0) { - node.left = node.left.RotateLeft(); - } - node = node.RotateRight(); - // If 'node' was unbalanced by more than 2, we've shifted some of the inbalance to the right node; so rebalance that. - node.right = Rebalance(node.right); - } - } - Debug.Assert(Math.Abs(node.Balance) <= 1); - node.height = (byte) (1 + Math.Max(Height(node.left), Height(node.right))); - node.totalListLength = -1; // mark for recalculation - // since balancing checks the whole tree up to the root, the whole path will get marked as invalid - return node; - } - - internal int GetTotalListLength() { - if (totalListLength >= 0) - return totalListLength; - int length = (isVisible ? 1 : 0); - if (left != null) { - length += left.GetTotalListLength(); - } - if (right != null) { - length += right.GetTotalListLength(); - } - return totalListLength = length; - } - - FileItemViewModel RotateLeft() { - /* Rotate tree to the left - * - * this right - * / \ / \ - * A right ===> this C - * / \ / \ - * B C A B - */ - FileItemViewModel b = right.left; - FileItemViewModel newTop = right; - - if (b != null) b.listParent = this; - this.right = b; - newTop.left = this; - newTop.listParent = this.listParent; - this.listParent = newTop; - // rebalance the 'this' node - this is necessary in some bulk insertion cases: - newTop.left = Rebalance(this); - return newTop; - } - - FileItemViewModel RotateRight() { - /* Rotate tree to the right - * - * this left - * / \ / \ - * left C ===> A this - * / \ / \ - * A B B C - */ - FileItemViewModel b = left.right; - FileItemViewModel newTop = left; - - if (b != null) b.listParent = this; - this.left = b; - newTop.right = this; - newTop.listParent = this.listParent; - this.listParent = newTop; - newTop.right = Rebalance(this); - return newTop; - } - - static void RebalanceUntilRoot(FileItemViewModel pos) { - while (pos.listParent != null) { - if (pos == pos.listParent.left) { - pos = pos.listParent.left = Rebalance(pos); - } - else { - Debug.Assert(pos == pos.listParent.right); - pos = pos.listParent.right = Rebalance(pos); - } - pos = pos.listParent; - } - FileItemViewModel newRoot = Rebalance(pos); - if (newRoot != pos && pos.treeFlattener != null) { - Debug.Assert(newRoot.treeFlattener == null); - newRoot.treeFlattener = pos.treeFlattener; - pos.treeFlattener = null; - newRoot.treeFlattener.root = newRoot; - } - Debug.Assert(newRoot.listParent == null); - newRoot.CheckInvariants(); - } - #endregion - - #region Insertion - static void InsertNodeAfter(FileItemViewModel pos, FileItemViewModel newNode) { - // newNode might be the model root of a whole subtree, so go to the list root of that subtree: - newNode = newNode.GetListRoot(); - if (pos.right == null) { - pos.right = newNode; - newNode.listParent = pos; - } - else { - // insert before pos.right's leftmost: - pos = pos.right; - while (pos.left != null) - pos = pos.left; - Debug.Assert(pos.left == null); - pos.left = newNode; - newNode.listParent = pos; - } - RebalanceUntilRoot(pos); - } - #endregion - - #region Removal - void RemoveNodes(FileItemViewModel start, FileItemViewModel end) { - // Removes all nodes from start to end (inclusive) - // All removed nodes will be reorganized in a separate tree, do not delete - // regions that don't belong together in the tree model! - - List removedSubtrees = new List(); - FileItemViewModel oldPos; - FileItemViewModel pos = start; - do { - // recalculate the endAncestors every time, because the tree might have been rebalanced - HashSet endAncestors = new HashSet(); - for (FileItemViewModel tmp = end; tmp != null; tmp = tmp.listParent) - endAncestors.Add(tmp); - - removedSubtrees.Add(pos); - if (!endAncestors.Contains(pos)) { - // we can remove pos' right subtree in a single step: - if (pos.right != null) { - removedSubtrees.Add(pos.right); - pos.right.listParent = null; - pos.right = null; - } - } - FileItemViewModel succ = pos.Successor(); - DeleteNode(pos); // this will also rebalance out the deletion of the right subtree - - oldPos = pos; - pos = succ; - } while (oldPos != end); - - // merge back together the removed subtrees: - FileItemViewModel removed = removedSubtrees[0]; - for (int i = 1; i < removedSubtrees.Count; i++) { - removed = ConcatTrees(removed, removedSubtrees[i]); - } - } - - static FileItemViewModel ConcatTrees(FileItemViewModel first, FileItemViewModel second) { - FileItemViewModel tmp = first; - while (tmp.right != null) - tmp = tmp.right; - InsertNodeAfter(tmp, second); - return tmp.GetListRoot(); - } - - FileItemViewModel Successor() { - if (right != null) { - FileItemViewModel node = right; - while (node.left != null) - node = node.left; - return node; - } - else { - FileItemViewModel node = this; - FileItemViewModel oldNode; - do { - oldNode = node; - node = node.listParent; - // loop while we are on the way up from the right part - } while (node != null && node.right == oldNode); - return node; - } - } - - static void DeleteNode(FileItemViewModel node) { - FileItemViewModel balancingNode; - if (node.left == null) { - balancingNode = node.listParent; - node.ReplaceWith(node.right); - node.right = null; - } - else if (node.right == null) { - balancingNode = node.listParent; - node.ReplaceWith(node.left); - node.left = null; - } - else { - FileItemViewModel tmp = node.right; - while (tmp.left != null) - tmp = tmp.left; - // First replace tmp with tmp.right - balancingNode = tmp.listParent; - tmp.ReplaceWith(tmp.right); - tmp.right = null; - Debug.Assert(tmp.left == null); - Debug.Assert(tmp.listParent == null); - // Now move node's children to tmp: - tmp.left = node.left; node.left = null; - tmp.right = node.right; node.right = null; - if (tmp.left != null) tmp.left.listParent = tmp; - if (tmp.right != null) tmp.right.listParent = tmp; - // Then replace node with tmp - node.ReplaceWith(tmp); - if (balancingNode == node) - balancingNode = tmp; - } - Debug.Assert(node.listParent == null); - Debug.Assert(node.left == null); - Debug.Assert(node.right == null); - node.height = 1; - node.totalListLength = -1; - if (balancingNode != null) - RebalanceUntilRoot(balancingNode); - } - - void ReplaceWith(FileItemViewModel node) { - if (listParent != null) { - if (listParent.left == this) { - listParent.left = node; - } - else { - Debug.Assert(listParent.right == this); - listParent.right = node; - } - if (node != null) - node.listParent = listParent; - listParent = null; - } - else { - // this was a root node - Debug.Assert(node != null); // cannot delete the only node in the tree - node.listParent = null; - if (treeFlattener != null) { - Debug.Assert(node.treeFlattener == null); - node.treeFlattener = this.treeFlattener; - this.treeFlattener = null; - node.treeFlattener.root = node; - } - } - } - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.TreeNode.cs b/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.TreeNode.cs deleted file mode 100644 index 6fe0575..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.TreeNode.cs +++ /dev/null @@ -1,771 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using WinDirStat.Net.Services; - -namespace WinDirStat.Net.ViewModel.Files { - partial class FileItemViewModel { - - private bool isVisible = true; - /*private bool isHidden; - private bool isSelected; - private bool isExpanded; - private bool isEditing;*/ - - /*private BitField16 flags = new BitField16 { - //[0] = true, - }; - -#pragma warning disable 0649, IDE1006 - private bool isVisible { - get => flags[0]; - set => flags[0] = value; - } - private bool isHidden { - get => flags[1]; - set => flags[1] = value; - } - private bool isSelected { - get => flags[2]; - set => flags[2] = value; - } - private bool isExpanded { - get => flags[3]; - set => flags[3] = value; - } - private bool isEditing { - get => flags[4]; - set => flags[4] = value; - } - private bool isEventsHooked { - get => flags[5]; - set => flags[5] = value; - } -#pragma warning restore 0649, IDE1006*/ - - //private bool canExpandRecursively = true; - //private bool lazyLoading; - //private bool? isChecked; - - private void UpdateIsVisible(bool parentIsVisible, bool updateFlattener) { - bool newIsVisible = parentIsVisible && !isHidden; - if (isVisible != newIsVisible) { - isVisible = newIsVisible; - - // invalidate the augmented data - FileItemViewModel node = this; - while (node != null && node.totalListLength >= 0) { - node.totalListLength = -1; - node = node.listParent; - } - // Remember the removed nodes: - List removedNodes = null; - if (updateFlattener && !newIsVisible) { - removedNodes = VisibleDescendantsAndSelf().ToList(); - } - // also update the model children: - UpdateChildIsVisible(false); - - // Validate our invariants: - if (updateFlattener) - CheckRootInvariants(); - - // Tell the flattener about the removed nodes: - if (removedNodes != null) { - var flattener = GetListRoot().treeFlattener; - if (flattener != null) { - if (!SuppressRefresh) - flattener.NodesRemoved(GetVisibleIndexForNode(this), removedNodes); - foreach (var n in removedNodes) - n.OnIsVisibleChanged(); - } - } - // Tell the flattener about the new nodes: - if (updateFlattener && newIsVisible) { - var flattener = GetListRoot().treeFlattener; - if (flattener != null) { - if (!SuppressRefresh) - flattener.NodesInserted(GetVisibleIndexForNode(this), VisibleDescendantsAndSelf()); - foreach (var n in VisibleDescendantsAndSelf()) - n.OnIsVisibleChanged(); - } - } - } - } - - protected void OnIsVisibleChanged() { } - - private void UpdateChildIsVisible(bool updateFlattener) { - if (children != null && children.Count > 0) { - bool showChildren = isVisible && isExpanded; - foreach (FileItemViewModel child in children) { - child.UpdateIsVisible(showChildren, updateFlattener); - } - } - } - - #region Main - - public IReadOnlyFileItemViewModelCollection Children { - get { - if (Model.IsContainerType) { - if (children == null) - children = new FileItemViewModelCollection(this); - return children; - } - return EmptyChildren; - } - } - - //public IBrush Foreground => IBrush.Black; - - public int Level => Parent != null ? Parent.Level + 1 : 0; - - public bool IsRoot => Parent == null; - - public bool IsHidden { - get => isHidden; - set { - if (isHidden != value) { - isHidden = value; - if (parent != null) - UpdateIsVisible(parent.isVisible && parent.isExpanded, true); - RaisePropertyChanged(); - if (Parent != null) - Parent.RaisePropertyChanged(nameof(ShowExpander)); - } - } - } - - /// - /// Return true when this node is not hidden and when all parent nodes are expanded and not hidden. - /// - public bool IsVisible => isVisible; - - public bool IsSelected { - get => isSelected; - set { - if (isSelected != value) { - isSelected = value; - RaisePropertyChanged(); - } - } - } - - #endregion - - #region OnChildrenChanged - - internal protected void RaiseChildrenReset() { - Stopwatch watch = Stopwatch.StartNew(); - GetListRoot().treeFlattener.NodesReset(); - Console.WriteLine($"Took {watch.ElapsedMilliseconds}ms to reset"); - } - - internal protected void OnChildrenReset(List newList, List oldList) { - foreach (FileItemViewModel node in oldList) { - Debug.Assert(node.parent == this); - - //if (node.isHidden) - // continue; - - node.Parent = null; - //Debug.WriteLine("Removing {0} from {1}", node, this); - FileItemViewModel removeEnd = node; - while (removeEnd.children != null && removeEnd.children.Count > 0) - removeEnd = removeEnd.children.Last(); - - List removedNodes = null; - int visibleIndexOfRemoval = 0; - if (node.isVisible) { - visibleIndexOfRemoval = GetVisibleIndexForNode(node); - removedNodes = node.VisibleDescendantsAndSelf().ToList(); - } - - RemoveNodes(node, removeEnd); - } - - FileItemViewModel insertionPos = null; - - foreach (FileItemViewModel node in newList) { - Debug.Assert(node.Model.Parent != null); - Debug.Assert(node.parent == null); - node.Parent = this; - node.UpdateIsVisible(isVisible && isExpanded, false); - //Debug.WriteLine("Inserting {0} after {1}", node, insertionPos); - - while (insertionPos != null && insertionPos.children != null && insertionPos.children.Count > 0) { - insertionPos = insertionPos.children.Last(); - } - InsertNodeAfter(insertionPos ?? this, node); - - insertionPos = node; - } - - if (!SuppressRefresh) { - var flattener = GetListRoot().treeFlattener; - if (flattener != null) { - flattener.NodesReset(); - } - } - - RaisePropertyChanged(nameof(ShowExpander)); - if (newList.Count > 0) { - if (oldList.Count > 0) { - if (newList[newList.Count - 1] != oldList[oldList.Count - 1]) { - oldList[oldList.Count - 1].RaisePropertyChanged(nameof(IsLast)); - newList[newList.Count - 1].RaisePropertyChanged(nameof(IsLast)); - } - } - else { - newList[newList.Count - 1].RaisePropertyChanged(nameof(IsLast)); - } - } - else if (oldList.Count > 0) { - oldList[oldList.Count - 1].RaisePropertyChanged(nameof(IsLast)); - } - //RaiseIsLastChangedIfNeeded(e); - } - internal protected void OnChildrenChanged(NotifyCollectionChangedEventArgs e) { - Debug.WriteLine(e.Action); - if (e.OldItems != null) { - foreach (FileItemViewModel node in e.OldItems) { - Debug.Assert(node.parent == this); - - //if (node.isHidden) - // continue; - - node.Parent = null; - //Debug.WriteLine("Removing {0} from {1}", node, this); - FileItemViewModel removeEnd = node; - while (removeEnd.children != null && removeEnd.children.Count > 0) - removeEnd = removeEnd.children.Last(); - - List removedNodes = null; - int visibleIndexOfRemoval = 0; - if (node.isVisible) { - visibleIndexOfRemoval = GetVisibleIndexForNode(node); - removedNodes = node.VisibleDescendantsAndSelf().ToList(); - } - - RemoveNodes(node, removeEnd); - - if (removedNodes != null && !SuppressRefresh) { - var flattener = GetListRoot().treeFlattener; - if (flattener != null) { - flattener.NodesRemoved(visibleIndexOfRemoval, removedNodes); - } - } - } - } - if (e.NewItems != null) { - FileItemViewModel insertionPos; - if (e.NewStartingIndex == 0) - insertionPos = null; - else - insertionPos = children[e.NewStartingIndex - 1]; - - foreach (FileItemViewModel node in e.NewItems) { - Debug.Assert(node.Model.Parent != null); - Debug.Assert(node.parent == null); - node.Parent = this; - node.UpdateIsVisible(isVisible && isExpanded, false); - //Debug.WriteLine("Inserting {0} after {1}", node, insertionPos); - - while (insertionPos != null && insertionPos.children != null && insertionPos.children.Count > 0) { - insertionPos = insertionPos.children.Last(); - } - InsertNodeAfter(insertionPos ?? this, node); - - insertionPos = node; - if (node.isVisible && !SuppressRefresh) { - var flattener = GetListRoot().treeFlattener; - if (flattener != null) { - flattener.NodesInserted(GetVisibleIndexForNode(node), node.VisibleDescendantsAndSelf()); - } - } - } - } - - RaisePropertyChanged(nameof(ShowExpander)); - RaiseIsLastChangedIfNeeded(e); - } - #endregion - - #region Expanding / LazyLoading - - public bool ShowExpander { - get => Model.HasChildren; - } - - public bool IsExpanded { - get => isExpanded; - set { - if (isExpanded != value) { - isExpanded = value; - if (isExpanded) { - OnExpanding(); - } - else { - OnCollapsing(); - } - UpdateChildIsVisible(true); - RaisePropertyChanged(); - } - } - } - - //protected virtual void OnExpanding() { } - //protected virtual void OnCollapsing() { } - - /*public bool LazyLoading { - get => lazyLoading; - set { - lazyLoading = value; - if (lazyLoading) { - IsExpanded = false; - if (canExpandRecursively) { - canExpandRecursively = false; - RaisePropertyChanged("CanExpandRecursively"); - } - } - RaisePropertyChanged("LazyLoading"); - RaisePropertyChanged("ShowExpander"); - } - }*/ - - /// - /// Gets whether this node can be expanded recursively. - /// If not overridden, this property returns false if the node is using lazy-loading, and true otherwise. - /// - public bool CanExpandRecursively { - get => false;// ItemCount <= 500; - } - - /*public bool ShowIcon { - get { return Icon != null; } - } - - protected void LoadChildren() { - throw new NotSupportedException(GetType().Name + " does not support lazy loading"); - } - - /// - /// Ensures the children were initialized (loads children if lazy loading is enabled) - /// - public void EnsureLazyChildren() { - if (LazyLoading) { - LazyLoading = false; - LoadChildren(); - } - }*/ - - #endregion - - #region Ancestors / Descendants - - public IEnumerable Descendants() { - return FileTreeTraversal.PreOrder(this.Children, n => n.Children); - } - - public IEnumerable VirtualDescendants() { - return FileTreeTraversal.PreOrder(this.Children, n => n.Children); - } - - public IEnumerable DescendantsAndSelf() { - return FileTreeTraversal.PreOrder(this, n => n.Children); - } - - public IEnumerable VisibleDescendants() { - return FileTreeTraversal.PreOrder(this.Children.Where(c => c.isVisible), n => n.Children.Where(c => c.isVisible)); - } - - public IEnumerable VisibleDescendantsAndSelf() { - return FileTreeTraversal.PreOrder(this, n => n.Children.Where(c => c.isVisible)); - } - - public IEnumerable Ancestors() { - for (FileItemViewModel n = this.Parent; n != null; n = n.Parent) - yield return n; - } - - public IEnumerable AncestorsAndSelf() { - for (FileItemViewModel n = this; n != null; n = n.Parent) - yield return n; - } - - #endregion - - #region Editing - - public bool IsEditable { - get => false; - } - - public bool IsEditing { - get => isEditing; - set { - if (isEditing != value) { - isEditing = value; - RaisePropertyChanged(); - } - } - } - - public string LoadEditText() { - return null; - } - - public bool SaveEditText(string value) { - return true; - } - - #endregion - - #region Checkboxes (Disabled) - - /*public bool IsCheckable { - get => false; - } - - public bool? IsChecked { - get => isChecked; - set { - SetIsChecked(value, true); - } - } - - void SetIsChecked(bool? value, bool update) { - if (isChecked != value) { - isChecked = value; - - if (update) { - if (IsChecked != null) { - foreach (var child in Descendants()) { - if (child.IsCheckable) { - child.SetIsChecked(IsChecked, false); - } - } - } - - foreach (var parent in Ancestors()) { - if (parent.IsCheckable) { - if (!parent.TryValueForIsChecked(true)) { - if (!parent.TryValueForIsChecked(false)) { - parent.SetIsChecked(null, false); - } - } - } - } - } - - RaisePropertyChanged("IsChecked"); - } - } - - bool TryValueForIsChecked(bool? value) { - if (Children.Where(n => n.IsCheckable).All(n => n.IsChecked == value)) { - SetIsChecked(value, false); - return true; - } - return false; - }*/ - - #endregion - - #region Cut / Copy / Paste / Delete (Disabled) - - /// - /// Gets whether the node should render transparently because it is 'cut' (but not actually removed yet). - /// - /*public bool IsCut { - get => false; - }*/ - /* - static List cuttedNodes = new List(); - static IDataObject cuttedData; - static EventHandler requerySuggestedHandler; // for weak event - - static void StartCuttedDataWatcher() - { - requerySuggestedHandler = new EventHandler(CommandManager_RequerySuggested); - CommandManager.RequerySuggested += requerySuggestedHandler; - } - - static void CommandManager_RequerySuggested(object sender, EventArgs e) - { - if (cuttedData != null && !Clipboard.IsCurrent(cuttedData)) { - ClearCuttedData(); - } - } - - static void ClearCuttedData() - { - foreach (var node in cuttedNodes) { - node.IsCut = false; - } - cuttedNodes.Clear(); - cuttedData = null; - } - - //static public IEnumerable PurifyNodes(IEnumerable nodes) - //{ - // var list = nodes.ToList(); - // var array = list.ToArray(); - // foreach (var node1 in array) { - // foreach (var node2 in array) { - // if (node1.Descendants().Contains(node2)) { - // list.Remove(node2); - // } - // } - // } - // return list; - //} - - bool isCut; - - public bool IsCut - { - get { return isCut; } - private set - { - isCut = value; - RaisePropertyChanged("IsCut"); - } - } - - internal bool InternalCanCut() - { - return InternalCanCopy() && InternalCanDelete(); - } - - internal void InternalCut() - { - ClearCuttedData(); - cuttedData = Copy(ActiveNodesArray); - Clipboard.SetDataObject(cuttedData); - - foreach (var node in ActiveNodes) { - node.IsCut = true; - cuttedNodes.Add(node); - } - } - - internal bool InternalCanCopy() - { - return CanCopy(ActiveNodesArray); - } - - internal void InternalCopy() - { - Clipboard.SetDataObject(Copy(ActiveNodesArray)); - } - - internal bool InternalCanPaste() - { - return CanPaste(Clipboard.GetDataObject()); - } - - internal void InternalPaste() - { - Paste(Clipboard.GetDataObject()); - - if (cuttedData != null) { - DeleteCore(cuttedNodes.ToArray()); - ClearCuttedData(); - } - } - */ - - /*public bool CanDelete(WinDirNode[] nodes) { - return false; - } - - public void Delete(WinDirNode[] nodes) { - throw new NotSupportedException(GetType().Name + " does not support deletion"); - } - - public void DeleteWithoutConfirmation(WinDirNode[] nodes) { - throw new NotSupportedException(GetType().Name + " does not support deletion"); - } - - public bool CanCut(WinDirNode[] nodes) { - return CanCopy(nodes) && CanDelete(nodes); - } - - public void Cut(WinDirNode[] nodes) { - var data = GetDataObject(nodes); - if (data != null) { - // TODO: default cut implementation should not immediately perform deletion, but use 'IsCut' - Clipboard.SetDataObject(data, copy: true); - DeleteWithoutConfirmation(nodes); - } - } - - public bool CanCopy(WinDirNode[] nodes) { - return false; - } - - public void Copy(WinDirNode[] nodes) { - var data = GetDataObject(nodes); - if (data != null) - Clipboard.SetDataObject(data, copy: true); - } - - protected IDataObject GetDataObject(WinDirNode[] nodes) { - return null; - } - - public bool CanPaste(IDataObject data) { - return false; - } - - public void Paste(IDataObject data) { - throw new NotSupportedException(GetType().Name + " does not support copy/paste"); - }*/ - #endregion - - #region Drag and Drop (Disabled) - /*public void StartDrag(DependencyObject dragSource, WinDirNode[] nodes) { - // The default drag implementation works by reusing the copy infrastructure. - // Derived classes should override this method - var data = GetDataObject(nodes); - if (data == null) - return; - DragDropEffects effects = DragDropEffects.Copy; - if (CanDelete(nodes)) - effects |= DragDropEffects.Move; - DragDropEffects result = DragDrop.DoDragDrop(dragSource, data, effects); - if (result == DragDropEffects.Move) { - DeleteWithoutConfirmation(nodes); - } - } - - /// - /// Gets the possible drop effects. - /// If the method returns more than one of (Copy|Move|Link), the tree view will choose one effect based - /// on the allowed effects and keyboard status. - /// - public DragDropEffects GetDropEffect(DragEventArgs e, int index) { - // Since the default drag implementation uses Copy(), - // we'll use Paste() in our default drop implementation. - if (CanPaste(e.Data)) { - // If Ctrl is pressed -> copy - // If moving is not allowed -> copy - // Otherwise: move - if ((e.KeyStates & DragDropKeyStates.ControlKey) != 0 || (e.AllowedEffects & DragDropEffects.Move) == 0) - return DragDropEffects.Copy; - return DragDropEffects.Move; - } - return DragDropEffects.None; - } - - internal void InternalDrop(DragEventArgs e, int index) { - if (LazyLoading) { - EnsureLazyChildren(); - index = Children.Count; - } - - Drop(e, index); - } - - public void Drop(DragEventArgs e, int index) { - // Since the default drag implementation uses Copy(), - // we'll use Paste() in our default drop implementation. - Paste(e.Data); - }*/ - #endregion - - #region IsLast (for TreeView lines) - - public bool IsLast { - get => Parent == null || Parent.Children[Parent.Children.Count - 1] == this; - } - - void RaiseIsLastChangedIfNeeded(NotifyCollectionChangedEventArgs e) { - switch (e.Action) { - case NotifyCollectionChangedAction.Add: - if (e.NewStartingIndex == Children.Count - 1) { - if (Children.Count > 1) { - Children[Children.Count - 2].RaisePropertyChanged("IsLast"); - } - Children[Children.Count - 1].RaisePropertyChanged("IsLast"); - } - break; - case NotifyCollectionChangedAction.Remove: - if (e.OldStartingIndex == Children.Count) { - if (Children.Count > 0) { - Children[Children.Count - 1].RaisePropertyChanged("IsLast"); - } - } - break; - } - } - - #endregion - - #region INotifyPropertyChanged Members (Disabled) - - /*public event PropertyChangedEventHandler PropertyChanged { - add { } - remove { } - //add => PropertyChanged += value; - //remove => PropertyChanged -= value; - }*/ - /*public event PropertyChangedEventHandler PropertyChanged; - - protected internal void RaisePropertyChanged(string name) { - //visualInfo?.RaisePropertyChanged(this, new PropertyChangedEventArgs(name)); - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); - } - - protected internal void RaisePropertiesChanged(params string[] names) { - for (int i = 0; i < names.Length; i++) - RaisePropertyChanged(names[i]); - } - - protected internal void AutoRaisePropertyChanged([CallerMemberName] string name = null) { - //visualInfo?.RaisePropertyChanged(this, new PropertyChangedEventArgs(name)); - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); - }*/ - - #endregion - - #region Model (Disabled) - /// - /// Gets the underlying model object. - /// - /// - /// This property calls the virtual helper method. - /// I didn't make the property itself virtual because deriving classes - /// may wish to replace it with a more specific return type, - /// but C# doesn't support variance in override declarations. - /// - /*public object Model { - get => GetModel(); - } - - protected virtual object GetModel() { - return null; - }*/ - #endregion - - /// - /// Gets called when the item is double-clicked. - /// - public void ActivateItem() { - } - - public override string ToString() { - // used for keyboard navigation - return Name ?? string.Empty; - } - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.cs b/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.cs deleted file mode 100644 index cfdbf93..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModel.cs +++ /dev/null @@ -1,657 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Utils; -using WinDirStat.Net.ViewModel.Extensions; - -namespace WinDirStat.Net.ViewModel.Files { - /// A view model for displaying models. - public partial class FileItemViewModel : ObservableObject, IDisposable { - - #region Constants - - /// The collection used for empty children to avoid wasting memory. - private static readonly FileItemViewModelCollection EmptyChildren = new FileItemViewModelCollection(); - - #endregion - - #region Fields - - /// The loaded, visible children of the view model item. - private FileItemViewModelCollection children; - /// The parent of the view model item. - private FileItemViewModel parent; - /// The loaded icon of the view model item. - private IImage icon; - /// The loaded display name of the view model item. Only used with certain types. - private string displayName; - - /// The main view model containing this item. - public MainViewModel ViewModel { get; } - /// The model this item represents. - public FileItemBase Model { get; } - /// The extension item view model associated with this item. - public ExtensionItemViewModel ExtensionItem { get; } - - #endregion - - #region Constructors - - /// Constructs the . - /// - /// The main view model containing this item. - /// The model this item represents. - public FileItemViewModel(MainViewModel viewModel, FileItemBase model) { - ViewModel = viewModel; - Model = model; - if (model.Type == FileItemType.File) - ExtensionItem = model.ExtensionItem.GetViewModel(); - else - ExtensionItem = ExtensionItemViewModel.NotAFile; - Debug.Assert(ExtensionItem != null); - - exists = model.Exists; - HookEvents(); - LoadIcon(); - } - - /// Disposes of the . - /*~FileItemViewModel() { - Dispose(); - }*/ - - #endregion - - #region Properties - - /// Gets the parent of the item. - public FileItemViewModel Parent { - get => parent; - private set => Set(ref parent, value); - } - /// Gets the icon of the item. - public IImage Icon { - get => icon; - private set => Set(ref icon, value); - } - - /// Gets the overlay icon if there is one. - public IImage OverlayIcon { - get { - if (!Exists) - return Images.Missing; - else if (IsShortcut) - return IconCache.ShortcutIcon; - return null; - } - } - - /// Gets the display name of the item. (This may be null) - public string DisplayName { - get => displayName; - private set { - if (Set(ref displayName, value)) - RaisePropertyChanged(nameof(Header)); - } - } - - /// Gets the extension of the item. - public string Extension => Model.Extension; - - /// Gets the name of the file. - public string Name => Model.Name; - - /// Gets the path of the file. - public string FullName { - get { - if (Model.Parent != null || Model.IsAbsoluteRootType) - return Model.FullName; - return ""; - } - } - - /// Gets the type of this file item. - public FileItemType Type => Model.Type; - - /// Gets the total size of the file and all of its children. - public long Size => Model.Size; - - /// Gets this file's size relative to the parent's size. - public double Percent { - get { - if (Model.Parent != null || Model.IsAbsoluteRootType) - return Model.Percent; - return 0d; - } - } - - /// - /// Gets the local time of when the file was last written to. - /// If this is a container, it returns the most recent time of all children. - /// - public DateTime LastWriteTime => Model.LastWriteTime; - - /// - /// Gets the number of files and directories this folder contains. Returns -1 if this is not a - /// container. - /// - public int ItemCount => Model.ItemCount; - /// - /// Gets the number of files this folder contains. Returns -1 if this is not a container. - /// - public int FileCount => Model.FileCount; - /// - /// Gets the number of directories this folder contains. Returns -1 if this is not a container. - /// - public int SubdirCount => Model.SubdirCount; - - /// Gets the attributes for this file. - public FileAttributes Attributes => Model.Attributes; - - /// Gets the attributes for this file. - public string AttributesString => Model.AttributesString; - - /// Gets if the item should display a shortcut overlay. - public bool IsShortcut => Model.IsShortcut; - - /// Gets the root view model item containing this view model item. - public FileItemViewModel Root { - get { - if (parent == null) - return this; - return parent.Root; - } - } - - /// Gets the display tooltip for the view model item. - public string ToolTip { - get { - if (Model.Type == FileItemType.Computer) - return StringConstants.ComputerName; - if (Model.Parent != null || Model.IsAbsoluteRootType) - return Model.FullName; - return ""; - } - } - - /// Gets the display header for the view model item. - public string Header { - get { - if (Type == FileItemType.Volume || Type == FileItemType.Computer) - return displayName ?? $"({PathUtils.TrimSeparatorEnd(Name)})"; - else - return Model.Name; - } - } - - /// Gets if file still exists in the system. - public bool Exists { - get => exists; - private set { - if (exists != value) { - exists = value; - RaisePropertyChanged(); - RaisePropertyChanged(nameof(OverlayIcon)); - } - } - } - - /// Gets the method for how icons are cached and displayed. - private IconCacheMode CacheMode => ViewModel.Settings.IconCacheMode; - - /// Gets the UI service. - private IUIService UI => ViewModel.UI; - - /// Gets the images service. - private ImagesServiceBase Images => ViewModel.Images; - - /// Gets the icon cache service. - private IIconCacheService IconCache => ViewModel.IconCache; - - /// Gets if the UI refreshing should be supressed due to validation. - private bool SuppressRefresh => ViewModel.SuppressFileTreeRefresh; - - #endregion - - #region CacheIcon - - /// Caches the file's icon. - private void LoadIcon(bool basicLoad = false) { - IconCacheMode cacheMode = CacheMode; - if (cacheMode == IconCacheMode.None) - return; - IIconAndName iconName; - switch (Type) { - case FileItemType.File: - if (cacheMode >= IconCacheMode.FileType) { - SetIcon(ExtensionItem.Icon); - if (cacheMode >= IconCacheMode.Individual) { - IconCache.CacheIconAsync(FullName, OnCacheFileIcon); - } - else if (ExtensionItem.CacheState != IconCacheState.Cached) { - // Hook an event to wait for the cache state to change - isWaitingForExtensionIcon = true; - ExtensionItem.PropertyChanged += OnExtensionItemPropertyChanged; - } - } - else { - SetIcon(IconCache.FileIcon); - } - break; - case FileItemType.Directory: - SetIcon(IconCache.FolderIcon); - if (cacheMode >= IconCacheMode.Individual) - IconCache.CacheIconAsync(FullName, OnCacheFolderIcon); - break; - case FileItemType.Volume: - if (cacheMode >= IconCacheMode.Individual) { - iconName = IconCache.CacheIconAndDisplayName(FullName); - SetIconAndDisplayName(iconName, IconCache.VolumeIcon, Name); - } - else { - SetIcon(IconCache.VolumeIcon); - } - break; - case FileItemType.Computer: - if (CacheMode != IconCacheMode.None) { - iconName = IconCache.CacheSpecialFolder(Environment.SpecialFolder.MyComputer); - SetIconAndDisplayName(iconName, null, Name); - } - break; - case FileItemType.FileCollection: - SetIcon(Images.FileCollection); - break; - case FileItemType.FreeSpace: - SetIcon(Images.FreeSpace); - break; - case FileItemType.Unknown: - SetIcon(Images.UnknownSpace); - break; - } - } - - /// - /// The callback for when a property of the extension item has changed. - /// This is only used to wait for the file type icon to be cached. - /// - private void OnExtensionItemPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(ExtensionItem.CacheState)) { - if (ExtensionItem.CacheState == IconCacheState.Cached) { - SetIcon(ExtensionItem.Icon); - // Unhook event - isWaitingForExtensionIcon = false; - ExtensionItem.PropertyChanged -= OnExtensionItemPropertyChanged; - } - } - } - - /// Sets the icon and raises the associated property change. - /// - /// The icon to use. - /// True if the was non-null and was assigned. - private bool SetIcon(IImage icon) { - if (icon != null) { - this.icon = icon; - RaisePropertyChanged(nameof(Icon)); - return true; - } - return false; - } - - /// Sets the icon and raises the associated property change. - /// - /// The icon to use. - /// The default icon to use if the result is null. - /// True if the was non-null and was assigned. - private bool SetIcon(IImage icon, IImage defaultIcon) { - if (icon != null) { - this.icon = icon; - RaisePropertyChanged(nameof(Icon)); - return true; - } - else if (defaultIcon != null) { - icon = defaultIcon; - RaisePropertyChanged(nameof(Icon)); - } - return false; - } - - /// Sets the icon and display name and raises the associated property changes. - /// - /// The icon and name to use. - /// The default icon to use if the result is null. - /// The default name to use if the result is null. - /// True if the was non-null and was assigned. - private bool SetIconAndDisplayName(IIconAndName iconName, IImage defaultIcon, string defaultName) { - if (iconName != null) { - icon = iconName.Icon; - displayName = iconName.Name; - RaisePropertyChanged(nameof(Icon)); - RaisePropertyChanged(nameof(DisplayName)); - RaisePropertyChanged(nameof(Header)); - return true; - } - else { - if (defaultIcon != null) { - icon = defaultIcon; - RaisePropertyChanged(nameof(Icon)); - } - if (defaultName != null) { - displayName = defaultName; - RaisePropertyChanged(nameof(DisplayName)); - RaisePropertyChanged(nameof(Header)); - } - } - return false; - } - - /// The callback for caching a an individual file icon. - /// - /// The newly cached icon. - private void OnCacheFileIcon(IImage icon) { - SetIcon(icon, ExtensionItem.Icon); - } - - /// The callback for caching a an individual folder icon. - /// - /// The newly cached icon. - private void OnCacheFolderIcon(IImage icon) { - SetIcon(icon, IconCache.FolderIcon); - } - - /*private void OnCacheIconAndDisplayName(IconAndName iconName) { - this.icon = icon ?? IconCache.FileIcon; - if (icon == null) { - if (Type == FileItemType.Volume) - icon = IconCache.VolumeIcon; - } - else { - displayName = Name; - } - RaisePropertyChanged(nameof(Icon)); - RaisePropertyChanged(nameof(Header)); - }*/ - - #endregion - - #region Sort - - /// Sorts the children and all subchildren based on the comparison. - /// - /// The comparison to sort with. - public void Sort(Comparison comparison) { - Sort(comparison, true); - } - - /// Sorts the children based on the comparison. - /// - /// The comparison to sort with. - /// True if all subchildren should be recursively sorted. - private void Sort(Comparison comparison, bool recursive) { - // We don't wanna go locking empty children. - if (Model is FolderItem folder && !folder.IsEmpty) { - List modelChildren = folder.Children; - lock (modelChildren) { - children.Sort(comparison); - if (recursive) { - int count = children.Count; - for (int i = 0; i < count; i++) { - FileItemViewModel child = children[i]; - if (child.Model.IsContainerType) { - child.Sort(comparison, true); - } - } - } - } - } - } - - #endregion - - #region Children - - /// Ensures that the chidren collection is created and ready for population. - private void EnsureChildren() { - if (children == null) - children = new FileItemViewModelCollection(this); - } - - /// The callback for when the model has changed in some way. - private void OnModelChanged(FileItemBase sender, FileItemEventArgs e) { - switch (e.Action) { - case FileItemAction.Invalidated: - case FileItemAction.Done: - //case FileItemAction.Refreshed: - break; - case FileItemAction.Exists: - Exists = Model.Exists; - break; - case FileItemAction.Validated: - case FileItemAction.ValidatedSortOrder: - OnModelValidated(e.Action == FileItemAction.ValidatedSortOrder); - break; - case FileItemAction.ChildrenAdded: - OnModelChildrenAdded(e.Children, e.Index); - break; - case FileItemAction.ChildrenRemoved: - OnModelChildrenRemoved(e.Children); - break; - case FileItemAction.ChildrenCleared: - OnModelChildrenCleared(); - break; - case FileItemAction.GetViewModel: - e.ViewModel = this; - break; - } - } - - /// Raises changes in the view model due to model validation. - private void OnModelValidated(bool sortOrder) { - UI.Invoke(() => { - RaisePropertyChanged(nameof(Percent)); - RaisePropertyChanged(nameof(Size)); - RaisePropertyChanged(nameof(LastWriteTime)); - if (Model.IsContainerType) { - RaisePropertyChanged(nameof(ItemCount)); - RaisePropertyChanged(nameof(FileCount)); - RaisePropertyChanged(nameof(SubdirCount)); - } - if (children != null) { - int count = children.Count; - for (int i = 0; i < count; i++) - children[i].RaisePropertyChanged(nameof(Percent)); - if (sortOrder && isExpanded) - children.Sort(ViewModel.FileComparer.Compare); - } - }); - } - - /// Adds new children to the view model collection. - private void OnModelChildrenAdded(List newChildren, int index) { - if (isExpanded) { - UI.Invoke(() => { - EnsureChildren(); - int count = newChildren.Count; - for (int i = 0; i < count; i++) { - children.Add(new FileItemViewModel(ViewModel, newChildren[i])); - } - children.Sort(ViewModel.FileComparer.Compare); - }); - } - else if (newChildren.Count == Model.ChildCount) { - // We had no children before - UI.Invoke(() => RaisePropertyChanged(nameof(ShowExpander))); - } - } - - /// Removes old children from the view model collection. - private void OnModelChildrenRemoved(List oldChildren) { - if (isExpanded) { - UI.Invoke(() => { - int count = oldChildren.Count; - for (int i = 0; i < count; i++) { - int index = children.IndexOf(oldChildren[i]); - FileItemViewModel oldItem = children[index]; - oldItem.UnhookEvents(); - children.RemoveAt(index); - //children.Remove(e.Children[i]); - } - }); - } - else if (oldChildren.Count > 0 && Model.ChildCount == 0) { - // We have no children now - UI.Invoke(() => RaisePropertyChanged(nameof(ShowExpander))); - } - } - - /// Clears all children from the view model collection. - private void OnModelChildrenCleared() { - UI.Invoke(() => { - if (isExpanded) { - if (children != null) - children.Clear(); - } - RaisePropertyChanged(nameof(ShowExpander)); - }); - } - - #endregion - - #region Expanding - - - public static FileItemViewModel ExpandTo(FileItemBase item) { - Stack ancestores = new Stack(); - - while (item.GetViewModel() == null) { - ancestores.Push(item); - item = item.Parent; - } - - FileItemViewModel view = item.GetViewModel(); - while (ancestores.Count > 0) { - item = ancestores.Pop(); - view = view.ExpandFind(item); - } - return view; - } - - protected void OnExpanding() { - if (Model is FolderItem folder && !folder.IsEmpty) { - List modelChildren = folder.Children; - lock (modelChildren) { - EnsureChildren(); - int count = modelChildren.Count; - for (int i = 0; i < count; i++) - children.Add(new FileItemViewModel(ViewModel, modelChildren[i])); - children.Sort(ViewModel.FileComparer.Compare); - } - } - } - private FileItemViewModel ExpandFind(FileItemBase node) { - FileItemViewModel result = null; - if (Model is FolderItem folder && !folder.IsEmpty) { - List modelChildren = folder.Children; - lock (modelChildren) { - int count = modelChildren.Count; - for (int i = 0; i < count; i++) { - FileItemBase child = modelChildren[i]; - FileItemViewModel view = new FileItemViewModel(ViewModel, child); - if (child == node) - result = view; - children.Add(view); - } - children.Sort(ViewModel.FileComparer.Compare); - } - } - UpdateChildIsVisible(true); - return result; - } - protected void OnCollapsing() { - if (Model is FolderItem folder && !folder.IsEmpty) { - List children = folder.Children; - lock (children) { - int count = this.children.Count; - for (int i = 0; i < count; i++) - this.children[i].UnhookEvents(); - this.children.Clear(); - } - } - } - - #endregion - - #region IDisposable Implementation - - /// Disposes of the . - public void Dispose() { - UnhookEvents(); - } - - /// Hooks the required events for the view model. - private void HookEvents() { - if (!isEventsHooked) { - isEventsHooked = true; - Model.Changed += OnModelChanged; - } - } - - /// Unhooks all events from the view model. - private void UnhookEvents() { - if (isEventsHooked) { - isEventsHooked = false; - Model.Changed -= OnModelChanged; - } - if (isWaitingForExtensionIcon) { - isWaitingForExtensionIcon = false; - ExtensionItem.PropertyChanged -= OnExtensionItemPropertyChanged; - } - // Recursively unhook all events, we forgot to do that in the last implementation - if (children != null) { - int count = children.Count; - for (int i = 0; i < count; i++) { - children[i].UnhookEvents(); - } - } - } - - #endregion - - - public FileItemViewModel FindView(FileItemBase node, bool expand) { - Stack ancestors = new Stack(); - - while (node.Parent != null && node != Model) { - ancestors.Push(node); - node = node.Parent; - } - - FileItemViewModel view = this; - while (ancestors.Count > 0) { - node = ancestors.Pop(); - if (!view.IsExpanded) { - if (!expand) { - return null; - } - else { - view.isExpanded = true; - view = view.ExpandFind(node); - } - } - else { - view = view.children.Find(node); - } - } - return view; - } - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModelFlags.cs b/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModelFlags.cs deleted file mode 100644 index f02cacb..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/FileItemViewModelFlags.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.ViewModel.Files { - /// Flags for the state. - [Serializable] - [Flags] - public enum FileItemViewModelFlags : byte { - /// No flags. - None = 0, - - //Visible = (1 << 0), - /// True if the item is hidden. - Hidden = (1 << 0), - /// True if the item is selected. - Selected = (1 << 1), - /// True if the item is expanded. - Expanded = (1 << 2), - /// True if the item is being edited. - Editing = (1 << 3), - /// True if the item has its events hooked to the model. - EventsHooked = (1 << 4), - /// True if the item is waiting on the extension's icon to cache. - WaitingForExtensionIcon = (1 << 5), - /// The file still exists in the system. - Exists = (1 << 6), - - } - - /// Extensions methods for . - internal static class FileItemViewModelExtensions { - - public static FileItemViewModelFlags SetFlag(this FileItemViewModelFlags flags, FileItemViewModelFlags flag, bool value) { - if (value) - return flags | flag; - else - return flags & ~flag; - } - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/FileTreeFlattener.cs b/WinDirStat.Net.Base/ViewModel/Files/FileTreeFlattener.cs deleted file mode 100644 index 80ed1d1..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/FileTreeFlattener.cs +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Diagnostics; - -namespace WinDirStat.Net.ViewModel.Files { - /// A flattener for a tree. - public sealed class FileTreeFlattener : ObservableCollectionObject, IList { - - #region Fields - - /// - /// The root node of the flat list tree. - /// This is not necessarily the root of the model! - /// - internal FileItemViewModel root; - private readonly bool includeRoot; - private readonly object syncRoot = new object(); - - #endregion - - #region Constructors - - /// Constructs the . - /// - /// The root item of the list. - /// True if the root is visible in the list. - public FileTreeFlattener(FileItemViewModel modelRoot, bool includeRoot) { - this.root = modelRoot; - while (root.listParent != null) - root = root.listParent; - root.treeFlattener = this; - this.includeRoot = includeRoot; - } - - #endregion - - #region Nodes Events - - /// Raises a collection reset event. - public void NodesReset() { - RaiseCollectionChanged(NotifyCollectionChangedAction.Reset); - } - - /// Raises a collection add event. - /// - /// The index the nodes were added at. - /// The nodes that were added. - public void NodesInserted(int index, IEnumerable nodes) { - if (!includeRoot) index--; - foreach (FileItemViewModel node in nodes) { - RaiseCollectionChanged(NotifyCollectionChangedAction.Add, node, index++); - } - } - - /// Raises a collection remove event. - /// - /// The index the nodes were removed at. - /// The nodes that were removed. - public void NodesRemoved(int index, IEnumerable nodes) { - if (!includeRoot) index--; - foreach (FileItemViewModel node in nodes) { - RaiseCollectionChanged(NotifyCollectionChangedAction.Remove, node, index); - } - } - - /// Raises a collection move event. - /// - /// The index the nodes were moved at. - /// The nodes that were moved. - public void NodesMoved(int index, int oldIndex, IEnumerable nodes) { - if (!includeRoot) index--; - foreach (FileItemViewModel node in nodes) { - RaiseCollectionChanged(NotifyCollectionChangedAction.Move, node, index++, oldIndex++); - } - } - - #endregion - - #region Stop - - /// Stops the list and detaches it from the . - public void Stop() { - Debug.Assert(root.treeFlattener == this); - root.treeFlattener = null; - } - - #endregion - - #region IList Implementation - - /// Gets the item at the specified index in the list. - /// - /// The index of the item. - public object this[int index] { - get { - if (index < 0 || index >= this.Count) - throw new ArgumentOutOfRangeException(); - return FileItemViewModel.GetNodeByVisibleIndex(root, includeRoot ? index : index + 1); - } - set => throw new NotSupportedException(); - } - - /// Gets the number of visible items in the list. - public int Count { - get => includeRoot ? root.GetTotalListLength() : root.GetTotalListLength() - 1; - } - - /// Gets the index of the item in the list. - /// - /// The item to get the index of. - /// The index of the item if found, otherwise -1. - public int IndexOf(object item) { - if (item is FileItemViewModel node && node.IsVisible && node.GetListRoot() == root) { - if (includeRoot) - return FileItemViewModel.GetVisibleIndexForNode(node); - else - return FileItemViewModel.GetVisibleIndexForNode(node) - 1; - } - else { - return -1; - } - } - - /// Returns true if the list contains the specified item. - /// - /// The item to check for. - /// True if the item was found. - public bool Contains(object item) { - return IndexOf(item) >= 0; - } - - /// Copies the list to an array. - /// - /// The array to copy to. - /// The starting index in the array to copy to. - public void CopyTo(Array array, int arrayIndex) { - for (int i = 0; i < Count; i++) - array.SetValue(this[i], arrayIndex++); - } - - - /// Gets the enumerator for this list. - /// - /// The enumerator for all visible elements in the list. - public IEnumerator GetEnumerator() { - for (int i = 0; i < Count; i++) - yield return this[i]; - } - - #endregion - - #region NotSupported IList/ICollection Implementation - - bool ICollection.IsSynchronized => false; - - object ICollection.SyncRoot => syncRoot; - - bool IList.IsReadOnly => true; - - bool IList.IsFixedSize => false; - - void IList.Insert(int index, object item) => throw new NotSupportedException(); - - void IList.RemoveAt(int index) => throw new NotSupportedException(); - - int IList.Add(object item) => throw new NotSupportedException(); - - void IList.Clear() => throw new NotSupportedException(); - - void IList.Remove(object item) => throw new NotSupportedException(); - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Files/FileTreeTraversal.cs b/WinDirStat.Net.Base/ViewModel/Files/FileTreeTraversal.cs deleted file mode 100644 index cb2685e..0000000 --- a/WinDirStat.Net.Base/ViewModel/Files/FileTreeTraversal.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; - -namespace WinDirStat.Net.ViewModel.Files { - /// - /// Static helper methods for traversing trees. - /// - internal static class FileTreeTraversal { - /// - /// Converts a tree data structure into a flat list by traversing it in pre-order. - /// - /// The root element of the tree. - /// The function that gets the children of an element. - /// Iterator that enumerates the tree structure in pre-order. - public static IEnumerable PreOrder(T root, Func> recursion) { - return PreOrder(new T[] { root }, recursion); - } - - /// - /// Converts a tree data structure into a flat list by traversing it in pre-order. - /// - /// The root elements of the forest. - /// The function that gets the children of an element. - /// Iterator that enumerates the tree structure in pre-order. - public static IEnumerable PreOrder(IEnumerable input, Func> recursion) { - Stack> stack = new Stack>(); - try { - stack.Push(input.GetEnumerator()); - while (stack.Count > 0) { - while (stack.Peek().MoveNext()) { - T element = stack.Peek().Current; - yield return element; - IEnumerable children = recursion(element); - if (children != null) { - stack.Push(children.GetEnumerator()); - } - } - stack.Pop().Dispose(); - } - } - finally { - while (stack.Count > 0) { - stack.Pop().Dispose(); - } - } - } - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Graph/FileGraphViewModel.cs b/WinDirStat.Net.Base/ViewModel/Graph/FileGraphViewModel.cs deleted file mode 100644 index d8a5095..0000000 --- a/WinDirStat.Net.Base/ViewModel/Graph/FileGraphViewModel.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Services; -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.ViewModel.Graph { - /// The view model for a file treemap display. - public partial class FileGraphViewModel : ViewModelBaseEx { - - #region Private Enums - - /// The modes for highlighting the graph view. - protected enum HighlightMode { - None, - Extension, - Selection, - } - - #endregion - - #region Fields - - public SettingsService Settings { get; } - public TreemapRenderer Treemap { get; } - public UIService UI { get; } - - - private Point2I treemapSize; - private WriteableBitmap treemap; - private Point2I highlightSize; - private WriteableBitmap highlight; - private WriteableBitmap disabledTreemap; - private WriteableBitmap disabledHighlight; - - /// True if the graph is currently dimmed. - private volatile bool isDimmed; - /// True if the running render thread has finished rendering the treemap. - private volatile bool treemapRendered; - /// True if the running render thread is rendering the treemap. - private volatile bool fullRender; - - /// The root treemap item. - private FileItemBase rootItem; - /// The hovered treemap item. - private FileItemBase hoverItem; - - /// The selected file items to highlight. - private FileItemBase[] selection; - /// The extension to highlight. - private string extension; - /// The current mode for highlighting. - private HighlightMode highlightMode; - - /// True if rendering should be done on a separate thread. - private bool renderAsynchronously; - - /// True if resizing is in progress. - private bool resizing; - /// The timer to delay rendering while resizing. - private readonly UITimer resizeTimer; - - /// The thread where the asynchronous rendering is done. - private Thread renderThread; - - /// The current mouse position of inside the graph. - private Point2I mousePosition; - /// True if the mouse is inside the graph. - private bool isMouseOver; - - #endregion - - #region Constructors - - /// Constructs the . - public FileGraphViewModel(SettingsService settings, - TreemapRendererFactory treemapFactory, - UIService ui) - { - Settings = settings; - Treemap = treemapFactory.Create(); - UI = ui; - - Settings.PropertyChanged += OnSettingsPropertyChanged; - - resizeTimer = UI.CreateTimer(TimeSpan.FromSeconds(0.05), true, OnResizeTick); - } - - #endregion - - #region Events Handlers - - private void OnSettingsPropertyChanged(object sender, PropertyChangedEventArgs e) { - switch (e.PropertyName) { - case nameof(SettingsService.TreemapOptions): - case nameof(SettingsService.FilePalette): - RenderAsync(); - break; - case nameof(SettingsService.HighlightColor): - if (highlightMode != HighlightMode.None) - RenderHighlight(treemapSize); - break; - case nameof(SettingsService.RenderPriority): - if (renderThread != null && renderThread.IsAlive) - renderThread.Priority = Settings.RenderPriority; - break; - } - } - - private void OnResizeTick() { - - } - - #endregion - - #region Private Properties - - /// Gets if anything is in the process of being rendered. - private bool IsRendering => renderThread?.IsAlive ?? false; - /// Gets if the treemap is in the process of being rendered. - private bool IsRenderingTreemap => renderThread?.IsAlive ?? false && fullRender; - - /// Gets the treemap highlight color. - private Rgba32Color Options => Settings.HighlightColor; - - #endregion - - #region Properties - - #endregion - - #region Rendering - - private void UpdateDimmed() { - IsDimmed = IsRenderingTreemap || resizing || !IsEnabled; - } - - /// Clears the current render. - private void Clear() { - AbortRender(); - treemap = null; - highlight = null; - treemapSize = Point2I.Zero; - highlightSize = Point2I.Zero; - } - - /// Aborts the current render in progress. - public void AbortRender(bool waitForExit = true) { - if (renderThread != null) { - renderThread.Abort(); - renderThread = null; - UpdateDimmed(); - } - } - - private void RenderHighlightAsync() { - fullRender = !treemapRendered; - RenderAsyncImpl(); - } - - private void RenderAsync() { - fullRender = true; - RenderAsyncImpl(); - } - - private void RenderAsyncImpl() { - if (IsEnabled && rootItem != null) { - AbortRender(); - treemapRendered = false; - //IsDimmed = true; - Point2I size = new Point2I((int) ActualWidth, (int) ActualHeight); - renderThread = new Thread(() => RenderThread(size)) { - Priority = Settings.RenderPriority, - Name = "File GraphView Render", - }; - renderThread.Start(); - UpdateDimmed(); - } - } - - private void RenderThread(Point2I size) { - try { - if (size.X != 0 && size.Y != 0) { - if (fullRender) { - RenderTreemap(size); - } - treemapRendered = true; - if (highlightMode != HighlightMode.None) { - RenderHighlight(size); - } - } - UI.Invoke(() => { - // Let the control know we're not rendering anymore - renderThread = null; - imageTreemap.Source = treemap; - if (highlightMode != HighlightMode.None) - imageHighlight.Source = highlight; - UpdateDimmed(); - }); - } - catch (ThreadAbortException) { } - catch (Exception ex) { - Stopwatch sw = Stopwatch.StartNew(); - UI.Invoke(() => { - Console.WriteLine(ex.ToString()); - renderThread = null; - UpdateDimmed(); - UpdateHover(); - }); - Console.WriteLine($"Took {sw.ElapsedMilliseconds}ms to invoke EXCEPTION Dispatcher"); - } - } - - private void RenderTreemap(Point2I size) { - Stopwatch sw = Stopwatch.StartNew(); - if (treemap == null || treemapSize.X != size.X || treemapSize.Y != size.Y) { - treemapSize = size; - UI.Invoke(() => { - treemap = new WriteableBitmap(size.X, size.Y, 96, 96, PixelFormats.Bgra32, null); - }); - } - Treemap.DrawTreemap(treemap, new Rectangle2I(size), rootItem); - //Treemap.DrawTreemap(treemap, new Rectangle2I(size), fileRoot, options); - Console.WriteLine($"Took {sw.ElapsedMilliseconds}ms to render treemap"); - } - private void RenderHighlight(Point2I size) { - Stopwatch sw = Stopwatch.StartNew(); - if (highlight == null || highlightSize.X != size.X || highlightSize.Y != size.Y) { - highlightSize = size; - UI.Invoke(() => { - highlight = new WriteableBitmap(size.X, size.Y, 96, 96, PixelFormats.Bgra32, null); - }); - Trace.WriteLine($"Took {sw.ElapsedMilliseconds}ms to setup highlight bitmap"); - } - sw.Restart(); - if (highlightMode == HighlightMode.Extension) { - Treemap.HighlightExtensions(highlight, new Rectangle2I(size), rootItem, Settings.HighlightColor, extension); - } - else if (highlightMode == HighlightMode.Selection) { - Treemap.HighlightItems(highlight, new Rectangle2I(size), Settings.HighlightColor, selection); - } - Trace.WriteLine($"Took {sw.ElapsedMilliseconds}ms to render highlight"); - Trace.WriteLine(""); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/Graph/GraphViewModel.cs b/WinDirStat.Net.Base/ViewModel/Graph/GraphViewModel.cs deleted file mode 100644 index b29ad0d..0000000 --- a/WinDirStat.Net.Base/ViewModel/Graph/GraphViewModel.cs +++ /dev/null @@ -1,419 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Services; -using WinDirStat.Net.Structures; - -namespace WinDirStat.Net.ViewModel.Graph { - /// The base view model for a treemap display. - public partial class GraphViewModel : ViewModelBase { - - #region Private Enums - - /// The modes for highlighting the graph view. - protected enum HighlightMode { - None, - Extension, - Selection, - } - - #endregion - - #region Fields - - private readonly object volatileLock = new object(); - - private readonly SettingsService settings; - private readonly TreemapRenderer treemap; - private readonly UIService ui; - - - private Point2I treemapSize; - private Point2I highlightSize; - - private WriteableBitmap treemapImage; - private WriteableBitmap highlightImage; - private WriteableBitmap disabledTreemapImage; - private WriteableBitmap disabledHighlightImage; - - private ImageSource treemapDisplayImage; - private ImageSource highlightDisplayImage; - - private Point2I dimensions; - - - /// The root treemap item. - private volatile ITreemapItem rootItem; - - // Hover - /// The hovered treemap item. - private ITreemapItem hoverItem; - /// The current mouse position of inside the graph. - private Point2I mousePosition; - /// True if the mouse is inside the graph. - private bool isMouseOver; - - // Highlight - /// The selected treemap items to highlight. - private ITreemapItem[] selection; - /// The extension to highlight. - private string extension; - /// The current mode for highlighting. - private HighlightMode highlightMode; - - // Display - /// True if the graph is currently dimmed. - private volatile bool isDimmed; - /// True if the graph is enabled. - private volatile bool isEnabled; - - // Rendering - /// True if rendering should be done on a separate thread. - private bool renderAsynchronously; - /// True if the running render thread has finished rendering the treemap. - private volatile bool treemapRendered; - /// True if the running render thread is rendering the treemap. - private volatile bool fullRender; - /// True if resizing is in progress. - private volatile bool resizing; - /// The timer to delay rendering while resizing. - private readonly UITimer resizeTimer; - /// The thread where the asynchronous rendering is done. - private Thread renderThread; - - private Rgb24Color highlightColor; - - #endregion - - #region Constructors - - /// Constructs the . - public GraphViewModel(SettingsService settings, - TreemapRendererFactory treemapFactory, - UIService ui) - { - this.settings = settings; - treemap = treemapFactory.Create(); - this.ui = ui; - - this.settings.PropertyChanged += OnSettingsPropertyChanged; - - resizeTimer = this.ui.CreateTimer(TimeSpan.FromSeconds(0.05), true, OnResizeTick); - isEnabled = true; - } - - #endregion - - #region Events Handlers - - private void OnSettingsPropertyChanged(object sender, PropertyChangedEventArgs e) { - switch (e.PropertyName) { - /*case nameof(SettingsService.TreemapOptions): - case nameof(SettingsService.FilePalette): - Render(); - break; - case nameof(SettingsService.HighlightColor): - if (highlightMode != HighlightMode.None) - RenderHighlight(treemapSize); - break;*/ - case nameof(SettingsService.RenderPriority): - ui.Invoke(() => { - if (renderThread != null && renderThread.IsAlive) - renderThread.Priority = settings.RenderPriority; - }); - break; - } - } - - private void OnResizeTick() { - - } - - #endregion - - #region Private Properties - - /// Gets if anything is in the process of being rendered. - private bool IsRenderingAsync => renderThread?.IsAlive ?? false; - /// Gets if the treemap is in the process of being rendered. - private bool IsRenderingTreemap => renderThread?.IsAlive ?? false && fullRender; - - /// Gets or sets the treemap highlight color. - public Rgba32Color HighlightColor { - get => highlightColor; - set => Set(ref highlightColor, value); - } - - #endregion - - #region Properties - - /// Gets if the graph view should be dimmed due to rendering or being disabled. - public bool IsDimmed { - get => isDimmed; - protected set { - if (isDimmed != value) { - isDimmed = value; - - if (isDimmed) - HoverItem = null; - else if (isMouseOver) - UpdateHover(); - - RaisePropertyChanged(); - } - } - } - - /// Gets if the graph view is visually enabled. - public bool IsEnabled { - get => isEnabled; - private set { - if (isEnabled != value) { - isEnabled = value; - UpdateDimmed(); - if (!isEnabled) { - AbortRender(); - disabledTreemapImage = treemapImage; - disabledHighlightImage = highlightImage; - TreemapImage = disabledTreemapImage; - HighlightImage = disabledHighlightImage; - } - else { - disabledTreemapImage = null; - disabledHighlightImage = null; - RaisePropertyChanged(nameof(TreemapImage)); - // GraphView will render if (!IsEnabled and RootItem != null) - Render(); - } - RaisePropertyChanged(); - } - } - } - - /// Gets or sets the dimensions of the graph view. - public Point2I Dimensions { - get => dimensions; - set => Set(ref dimensions, value); - } - - /// Gets or sets the current mouse position inside the graph. - public Point2I MousePosition { - get => mousePosition; - set => Set(ref mousePosition, value); - } - - /// ets or sets if the mouse is inside the graph. - public bool IsMouseOver { - get => isMouseOver; - set => Set(ref isMouseOver, value); - } - - /// Gets the image to display the treemap. - public ImageSource TreemapImage { - get => treemapDisplayImage; - private set => Set(ref treemapDisplayImage, value); - } - - /// Gets the image to display the highlight. - public ImageSource HighlightImage { - get => highlightDisplayImage; - private set => Set(ref highlightDisplayImage, value); - } - - public ITreemapItem HoverItem { - get => hoverItem; - set => Set(ref hoverItem, value); - } - - public ITreemapItem RootItem { - get => rootItem; - set { - if (rootItem != value) { - rootItem = value; - - if (rootItem == null) { - AbortRender(); - } - - HighlightNone(); - HoverItem = null; - if (rootItem != null) - Render(); - else - Clear(); - - RaisePropertyChanged(); - } - } - } - - #endregion - - #region Rendering - - public void Refresh() { - Render(); - } - - private void Render() { - if (renderAsynchronously) - RenderAsyncImpl(); - else - RenderImpl(); - } - - private void RenderHighlight() { - fullRender = !treemapRendered; - if (IsRenderingAsync) { - RenderAsyncImpl(); - } - else if (!isDimmed && rootItem != null) { - RenderImpl(); - } - } - - /// Updates the dimmed settings. - private void UpdateDimmed() { - IsDimmed = IsRenderingTreemap || resizing || !IsEnabled; - } - - /// Clears the current render. - private void Clear() { - AbortRender(); - treemapImage = null; - highlightImage = null; - treemapSize = Point2I.Zero; - highlightSize = Point2I.Zero; - } - - /// Aborts the current render in progress. - public void AbortRender(bool waitForExit = true) { - if (renderThread != null) { - renderThread.Abort(); - renderThread = null; - UpdateDimmed(); - } - } - - private void RenderImpl() { - if (IsEnabled && rootItem != null) { - AbortRender(); - treemapRendered = false; - Point2I size = dimensions; - renderThread = null; - RenderThread(size); - } - } - - private void RenderAsyncImpl() { - if (IsEnabled && rootItem != null) { - AbortRender(); - treemapRendered = false; - //IsDimmed = true; - Point2I size = dimensions; - renderThread = new Thread(() => RenderThread(size)) { - Priority = settings.RenderPriority, - Name = "File GraphView Render", - }; - renderThread.Start(); - UpdateDimmed(); - } - } - - private void RenderThread(Point2I size) { - try { - if (size.X != 0 && size.Y != 0) { - if (fullRender) { - RenderTreemap(size); - } - treemapRendered = true; - if (highlightMode != HighlightMode.None) { - RenderHighlight(size); - } - } - ui.Invoke(() => { - // Let the control know we're not rendering anymore - renderThread = null; - TreemapImage = treemapImage; - if (highlightMode != HighlightMode.None) - HighlightImage = highlightImage; - UpdateDimmed(); - }); - } - catch (ThreadAbortException) { } - catch (Exception ex) { - Stopwatch sw = Stopwatch.StartNew(); - ui.Invoke(() => { - Console.WriteLine(ex.ToString()); - renderThread = null; - UpdateDimmed(); - UpdateHover(); - }); - Console.WriteLine($"Took {sw.ElapsedMilliseconds}ms to invoke EXCEPTION Dispatcher"); - } - } - - private void RenderTreemap(Point2I size) { - Stopwatch sw = Stopwatch.StartNew(); - if (treemapImage == null || treemapSize.X != size.X || treemapSize.Y != size.Y) { - treemapSize = size; - ui.Invoke(() => { - treemapImage = new WriteableBitmap(size.X, size.Y, 96, 96, PixelFormats.Bgra32, null); - }); - } - treemap.DrawTreemap(treemapImage, new Rectangle2I(size), rootItem); - //Treemap.DrawTreemap(treemap, new Rectangle2I(size), fileRoot, options); - Console.WriteLine($"Took {sw.ElapsedMilliseconds}ms to render treemap"); - } - private void RenderHighlight(Point2I size) { - Stopwatch sw = Stopwatch.StartNew(); - if (highlightImage == null || highlightSize.X != size.X || highlightSize.Y != size.Y) { - highlightSize = size; - ui.Invoke(() => { - highlightImage = new WriteableBitmap(size.X, size.Y, 96, 96, PixelFormats.Bgra32, null); - }); - Trace.WriteLine($"Took {sw.ElapsedMilliseconds}ms to setup highlight bitmap"); - } - sw.Restart(); - if (highlightMode == HighlightMode.Extension) { - treemap.HighlightExtensions(highlightImage, new Rectangle2I(size), (FileItemBase) rootItem, settings.HighlightColor, extension); - } - else if (highlightMode == HighlightMode.Selection) { - treemap.HighlightItems(highlightImage, new Rectangle2I(size), settings.HighlightColor, selection); - } - Trace.WriteLine($"Took {sw.ElapsedMilliseconds}ms to render highlight"); - Trace.WriteLine(""); - } - - #endregion - - #region Hover - - private void UpdateHover() { - if (rootItem == null) { - HoverItem = null; - return; - } - if (hoverItem != null) { - Rectangle2I rc = HoverItem.Rectangle; - if (rc.Contains(mousePosition)) - return; // Hover is the same - } - HoverItem = TreemapRenderer.FindItemAtPoint(rootItem, mousePosition); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/MainViewModel.Commands.cs b/WinDirStat.Net.Base/ViewModel/MainViewModel.Commands.cs deleted file mode 100644 index 4b6bfd8..0000000 --- a/WinDirStat.Net.Base/ViewModel/MainViewModel.Commands.cs +++ /dev/null @@ -1,361 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.ViewModel { - partial class MainViewModel { - - #region File Menu - - public IRelayUICommand Open { - get => GetCommand("Open...", Images.Open, Shortcuts.Open, - OnOpen); - } - public IRelayUICommand Save { - get => GetCommand("Save...", Images.Save, Shortcuts.Save, - OnSave, CanExecuteIsOpen); - } - public IRelayUICommand Reload { - get => GetCommand("Reload", Images.Reload, Shortcuts.Reload, - OnReload, CanExecuteIsOpen); - } - public IRelayUICommand Close { - get => GetCommand("Close", Images.Close, Shortcuts.Close, - OnClose, CanExecuteIsOpen); - } - public IRelayCommand Cancel { - get => GetCommand("Cancel", (IImage) null, Shortcuts.Cancel, - OnCancel, CanExecuteIsScanning); - } - public IRelayUICommand Elevate { - get => GetCommand("Elevate", Images.Elevate, Shortcuts.Elevate, - OnElevate, CanExecuteElevate); - } - public IRelayUICommand Exit { - get => GetCommand("Exit", Images.Exit, Shortcuts.Exit, - OnExit); - } - - #endregion - - #region Context Menu/Toolbar - - public IRelayUICommand Expand { - get => GetCommand("Expand", Images.Expand, Shortcuts.Expand, - OnExpand, CanExecuteExpand); - } - public IRelayUICommand Collapse { - get => GetCommand("Collapse", Images.Expand, Shortcuts.Expand, - OnExpand, CanExecuteExpand); - } - - public IRelayUICommand OpenItem { - get => GetCommand("Open Item", Images.Run, Shortcuts.OpenItem, - OnOpenItem, CanExecuteOpenItem); - } - public IRelayUICommand CopyPath { - get => GetCommand("Copy Path", Images.CopyPath, Shortcuts.CopyPath, - OnCopyPath, CanExecuteIsSelectionSingleFileType); - } - public IRelayUICommand Explore { - get => GetCommand("Explore Here", Images.Explore, Shortcuts.Explore, - OnExplore, CanExecuteExplore); - } - public IRelayUICommand CommandPrompt { - get => GetCommand("Command Prompt Here", Images.Cmd, Shortcuts.CommandPrompt, - OnCommandPrompt, CanExecuteCommandPrompt); - } - public IRelayUICommand PowerShell { - get => GetCommand("PowerShell Here", Images.PowerShell, Shortcuts.PowerShell, - OnPowerShell, CanExecuteIsSelectionSingleFileType); - } - public IRelayUICommand RefreshSelected { - get => GetCommand("Refresh Selected", Images.RefreshSelected, Shortcuts.RefreshSelected, - OnRefreshSelected, CanExecuteRefreshSelected); - } - public IRelayUICommand DeleteRecycle { - get => GetCommand("Delete (to Recycle Bin)", Images.RecycleBin, Shortcuts.DeleteRecycle, - OnDeleteRecycle, CanExecuteDeleteSingle); - } - public IRelayUICommand DeletePermanently { - get => GetCommand("Delete (Permanently!)", Images.Delete, Shortcuts.DeletePermanently, - OnDeletePermanently, CanExecuteDeleteSingle); - } - public IRelayUICommand Properties { - get => GetCommand("Properties", Images.Properties, Shortcuts.Properties, - OnProperties, CanExecuteOpenItem); - } - - #endregion - - #region Options Menu - - public IRelayUICommand ShowFreeSpace { - get => GetCommand("Show Free Space", Images.FreeSpace, Shortcuts.Properties, - OnShowFreeSpace); - } - public IRelayUICommand ShowUnknown { - get => GetCommand("Show Unknown", Images.UnknownSpace, Shortcuts.Properties, - OnShowUnknown); - } - public IRelayUICommand ShowTotalSpace { - get => GetCommand("Show Total Space", Images.ShowTotalSpace, Shortcuts.Properties, - OnShowTotalSpace); - } - public IRelayUICommand ShowFileTypes { - get => GetCommand("Show File Types", Images.FileCollection, Shortcuts.Properties, - OnShowFileTypes); - } - public IRelayUICommand ShowTreemap { - get => GetCommand("Show Treemap", Images.ShowTreemap, Shortcuts.Properties, - OnShowTreemap); - } - public IRelayUICommand ShowToolBar { - get => GetCommand("Show Toolbar", (IImage) null, Shortcuts.Properties, - OnShowToolBar); - } - public IRelayUICommand ShowStatusBar { - get => GetCommand("Show Statusbar", (IImage) null, Shortcuts.Properties, - OnShowStatusBar); - } - public IRelayUICommand Configure { - get => GetCommand("Configure WinDirStat...", Images.Settings, - OnConfigure); - } - - #endregion - - #region Other - - public IRelayUICommand EmptyRecycleBin { - get => GetCommand("Empty Recycle Bins", Images.EmptyRecycleBin, - OnEmptyRecycleBin, CanExecuteEmptyRecycleBin); - } - - #endregion - - - #region CanExecute - - private bool CanExecuteIsOpen() { - return IsOpen; - } - private bool CanExecuteIsScanning() { - return IsScanning; - } - - private bool CanExecuteHasSelection() { - return SelectedFiles.Count > 0; - } - private bool CanExecuteIsSingleSelection() { - return SelectedFiles.Count == 1; - } - - private bool CanExecuteIsSelectionFileType() { - return SelectedFiles.Count > 0 && !SelectedFiles.Any(f => !f.Model.IsFileType); - } - private bool CanExecuteIsSelectionSingleFileType() { - return SelectedFiles.Count == 1 && SelectedFiles[0].Model.IsFileType; - } - private bool CanExecuteCommandPrompt() { - return CanExecuteIsSelectionSingleFileType(); - } - private bool CanExecuteCopyPath() { - return CanExecuteIsSelectionSingleFileType(); - } - - private bool CanExecuteExpand() { - return SelectedFiles.Count == 1; - } - private bool CanExecuteOpenItem() { - return SelectedFiles.Count == 1 && (SelectedFile.Model.IsFileType || - SelectedFile.Model.IsAbsoluteRootType); - } - private bool CanExecuteExplore() { - return SelectedFiles.Count == 1 && (SelectedFile.Model.IsFileType || - SelectedFile.Model.Type == FileItemType.FileCollection || - SelectedFile.Model.IsAbsoluteRootType); - } - private bool CanExecuteDelete() { - return SelectedFiles.Count > 0 && !SelectedFiles.Any(f => !f.Model.IsFileType || f.Model.IsAnyRootType); - } - private bool CanExecuteDeleteSingle() { - return SelectedFiles.Count == 1 && SelectedFile.Model.IsFileType && !SelectedFile.Model.IsAnyRootType; - } - private bool CanExecuteRefreshSelected() { - return IsOpen && SelectedFiles.Count > 0 && !SelectedFiles.Any(f => !f.Model.IsFileType && !f.Model.IsContainerType); - } - private bool CanExecuteEmptyRecycleBin() { - return allRecycleBinInfo.ItemCount != 0 && allRecycleBinInfo.Size != 0; - } - private bool CanExecuteElevate() { - return !OS.IsElevated; - } - - #endregion - - #region File Menu - - private void OnOpen() { - DriveSelectResult result = Dialogs.ShowDriveSelect(WindowOwner); - if (result != null) { - Scanning.CloseAsync(() => Scanning.ScanAsync(result)); - } - } - private void OnSave() { - // TODO: Implement saving scanned file tree - } - private void OnReload() { - Scanning.ReloadAsync(); - } - private void OnClose() { - Scanning.Close(false); - } - private void OnCancel() { - Scanning.Cancel(false); - } - private void OnElevate() { - // Dialog warn progress will be lost. - // If yes, close then start new process. - MessageResult result = MessageResult.Yes; - if (Scanning.ScanState != ScanState.NotStarted) { - result = Dialogs.ShowWarning(WindowOwner, - "Elevating the process will start a new instance and all progress will be lost. Would you like to continue?", - "Elevate", MessageButton.YesNo); - } - if (result == MessageResult.Yes) { - try { - OS.StartNewElevated(); - UI.Shutdown(); - Dispose(); - } - catch { - Dialogs.ShowError(WindowOwner, "Failed to start elevated process!", "Error"); - } - } - } - private void OnExit() { - UI.Shutdown(); - Dispose(); - } - - #endregion - - #region Context Menu/Toolbar - - private void OnExpand() { - SelectedFile.IsExpanded = !SelectedFile.IsExpanded; - } - private void OnOpenItem() { - if (SelectedFile.Type == FileItemType.Computer) - OS.ExploreComputer(); - OS.RunItem(SelectedFile.FullName); - } - private void OnCopyPath() { - Clipboard.SetText($"\"{SelectedFile.FullName}\""); - } - private void OnExplore() { - switch (SelectedFile.Type) { - case FileItemType.Computer: - OS.ExploreComputer(); - break; - case FileItemType.File: - OS.ExploreFile(SelectedFile.FullName); - break; - default: - OS.ExploreFolder(SelectedFile.FullName); - break; - } - } - private void OnCommandPrompt() { - string directory = SelectedFile.FullName; - if (SelectedFile.Type == FileItemType.File) - directory = SelectedFile.Parent.FullName; - OS.OpenCommandPrompt(directory); - } - private void OnPowerShell() { - string directory = SelectedFile.FullName; - if (SelectedFile.Type == FileItemType.File) - directory = SelectedFile.Parent.FullName; - OS.OpenPowerShell(directory); - } - private void OnRefreshSelected() { - HashSet filesToRefresh = new HashSet(); - IsolateRefreshableFiles(filesToRefresh, SelectedFiles.Select(f => f.Model)); - if (filesToRefresh.Count > 0) - Scanning.RefreshFilesAsync(filesToRefresh); - } - private void OnDeleteRecycle() { - Scanning.RecycleFile(SelectedFile.Model); - } - private void OnDeletePermanently() { - Scanning.DeleteFile(SelectedFile.Model); - } - private void OnProperties() { - OS.OpenProperties(SelectedFile.FullName); - } - - private void IsolateRefreshableFiles(HashSet filesToRefresh, IEnumerable files) { - foreach (FileItemBase file in files) { - if (file.IsFileType) { - filesToRefresh.Add(file); - } - else if (file.IsContainerType) { - IsolateRefreshableFiles(filesToRefresh, file.Children); - } - } - } - - #endregion - - #region Options - - private void OnShowFreeSpace() { - Settings.ShowFreeSpace = !Settings.ShowFreeSpace; - } - private void OnShowUnknown() { - Settings.ShowUnknown = !Settings.ShowUnknown; - } - private void OnShowTotalSpace() { - Settings.ShowTotalSpace = !Settings.ShowTotalSpace; - } - private void OnShowFileTypes() { - Settings.ShowFileTypes = !Settings.ShowFileTypes; - } - private void OnShowTreemap() { - Settings.ShowTreemap = !Settings.ShowTreemap; - } - private void OnShowToolBar() { - Settings.ShowToolBar = !Settings.ShowToolBar; - } - private void OnShowStatusBar() { - Settings.ShowStatusBar = !Settings.ShowStatusBar; - } - - #endregion - - #region Other - - private void OnEmptyRecycleBin() { - OS.EmptyRecycleBin(WindowOwner); - } - - private void OnConfigure() { - // Open settings window - //Dialogs.ShowSettings(WindowOwner); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/MainViewModel.Methods.cs b/WinDirStat.Net.Base/ViewModel/MainViewModel.Methods.cs deleted file mode 100644 index 9c22ec5..0000000 --- a/WinDirStat.Net.Base/ViewModel/MainViewModel.Methods.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.ViewModel { - partial class MainViewModel { - - public void Loaded() { - } - - public void SortFiles() { - SuppressFileTreeRefresh = true; - RootItem?.Sort(FileComparer.Compare); - SuppressFileTreeRefresh = false; - } - - public void SortExtensions() { - Extensions.Sort(ExtensionComparer.Compare); - } - - public void ActivateItem() { - // TODO: Determine the default action for each item type - } - - public void UpdateEmptyRecycleBin() { - Debug.WriteLine("UpdateEmptyRecycleBin"); - RecycleBinInfo info = OS.GetAllRecycleBinInfo(); - string label = "Empty Recycle Bins"; - if (info != null) { - label += " ("; - if (info.ItemCount == 0 && info.Size == 0) { - label += "Empty"; - } - else { - label += $"{info.ItemCount:N0} "; - if (info.ItemCount == 1) - label += $"Item"; - else - label += $"Items"; - label += $", {FormatBytes.Format(info.Size)}"; - } - label += ")"; - } - EmptyRecycleBinLabel = label; - allRecycleBinInfo = info; - EmptyRecycleBin.RaiseCanExecuteChanged(); - } - - public void WindowShown() { - Open.Execute(); - } - } -} diff --git a/WinDirStat.Net.Base/ViewModel/MainViewModel.cs b/WinDirStat.Net.Base/ViewModel/MainViewModel.cs deleted file mode 100644 index 581ed1f..0000000 --- a/WinDirStat.Net.Base/ViewModel/MainViewModel.cs +++ /dev/null @@ -1,387 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Utils; -using WinDirStat.Net.ViewModel.Comparers; -using WinDirStat.Net.ViewModel.Extensions; -using WinDirStat.Net.ViewModel.Files; - -namespace WinDirStat.Net.ViewModel { - /// The main view model for the program. - public partial class MainViewModel : ViewModelWindowBase { - - #region Fields - - public SettingsService Settings { get; } - public ScanningService Scanning { get; } - public IIconCacheService IconCache { get; } - public IUIService UI { get; } - public IBitmapFactory BitmapFactory { get; } - /// Gets the images service. - public ImagesServiceBase Images { get; } - public IClipboardService Clipboard { get; } - public IOSService OS { get; } - public IWindowDialogService Dialogs { get; } - public IShortcutsService Shortcuts { get; } - public TreemapRenderer Treemap { get; } - - public ExtensionItemViewModelCollection Extensions { get; } - - public ObservableCollection SelectedFiles { get; } - public FileItemViewModel SelectedFile { get; private set; } - private ExtensionItemViewModel selectedExtension; - - public FileComparer FileComparer { get; } - public ExtensionComparer ExtensionComparer { get; } - - private long gcRAMUsage; - private FileItemViewModel rootItem; - private RootItem graphViewRootItem; - private readonly IUITimer ramTimer; - private readonly IUITimer statusTimer; - - private RecycleBinInfo allRecycleBinInfo; - private string emptyRecycleBinLabel; - - private bool suppressRefresh; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the MainViewModel class. - /// - public MainViewModel(SettingsService settings, - ScanningService scanning, - IIconCacheService iconCache, - IUIService ui, - IBitmapFactory bitmapFactory, - ImagesServiceBase images, - IClipboardService clipboard, - IOSService os, - IWindowDialogService dialogs, - TreemapRendererFactory treemapFactory, - IShortcutsService shortcuts, - RelayCommandService relayFactory) - { - Settings = settings; - Scanning = scanning; - IconCache = iconCache; - UI = ui; - BitmapFactory = bitmapFactory; - Images = images; - Clipboard = clipboard; - OS = os; - Dialogs = dialogs; - Shortcuts = shortcuts; - Treemap = treemapFactory.Create(); - - Settings.PropertyChanged += OnSettingsPropertyChanged; - Scanning.PropertyChanged += OnScanningPropertyChanged; - - Extensions = new ExtensionItemViewModelCollection(this); - - SelectedFiles = new ObservableCollection(); - SelectedFiles.CollectionChanged += OnSelectedFilesChanged; - - FileComparer = new FileComparer(); - ExtensionComparer = new ExtensionComparer(); - UpdateEmptyRecycleBin(); - - GCRAMUsage = GC.GetTotalMemory(false); - if (IsInDesignMode) { - // Code runs in Blend --> create design time data. - } - else { - // Code runs "for real" - ramTimer = UI.StartTimer(Settings.RAMInterval, true, OnRAMUsageTick); - statusTimer = UI.CreateTimer(Settings.StatusInterval, true, OnStatusTick); - } - } - - #endregion - - #region Properties - - /// Gets the title to display for the window. - public override string Title { - get { - string title = "WinDirStat.Net"; - if (Scanning.ProgressState != ScanProgressState.NotStarted) { - var paths = Scanning.RootPaths.Select(p => PathUtils.TrimSeparatorEnd(p)); - title = $"{string.Join("|", paths)} - {title}"; - } - if (OS.IsElevated) - title += " (Administrator)"; - return title; - } - } - - /// Gets the Garbage Collector's RAM Usage. - public long GCRAMUsage { - get => gcRAMUsage; - set => Set(ref gcRAMUsage, value); - } - - /// Gets the root file tree item. - public FileItemViewModel RootItem { - get => rootItem; - private set { - if (rootItem != value) { - if (rootItem != null) { - SuppressFileTreeRefresh = true; - rootItem.IsExpanded = false; - SuppressFileTreeRefresh = false; - rootItem.Dispose(); - } - rootItem = value; - RaisePropertyChanged(); - } - } - } - - /// Gets treemap's root file tree item. - public RootItem GraphViewRootItem { - get => graphViewRootItem; - private set => Set(ref graphViewRootItem, value); - } - - #endregion - - #region ScanProperties - - /// Gets if a scan operation is in progress. - public bool IsScanning => Scanning.IsScanning; - /// Gets if a refresh operation is in progress. - public bool IsRefreshing => Scanning.IsRefreshing; - /// Gets if a scan is finished and open. - public bool IsOpen => Scanning.IsOpen; - /// Gets the scan time. - public TimeSpan ScanTime => Scanning.ScanTime; - /// Gets the scan progress. - public double ScanProgress => Scanning.Progress; - /// Gets if scan progress can be displayed. - public bool CanDisplayScanProgress => Scanning.CanDisplayProgress; - - /// Gets or sets if the current scan operation is suspended. - public bool IsScanSuspended { - get => Scanning.IsSuspended; - set => Scanning.IsSuspended = value; - } - - ///Gets if the file list has a selection. - public bool HasFileSelection => SelectedFile != null; - - ///Gets the file type list selection. - public ExtensionItemViewModel SelectedExtension { - get => selectedExtension; - set { - if (selectedExtension != value) { - bool hasSelectionChanged = ((selectedExtension == null) != (value == null)); - selectedExtension = value; - RaisePropertyChanged(); - if (hasSelectionChanged) - RaisePropertyChanged(nameof(HasExtensionSelection)); - } - } - } - - ///Gets if the file type list has a selection. - public bool HasExtensionSelection => selectedExtension != null; - - /// Gets the label to display for the empty recycle bin command. - public string EmptyRecycleBinLabel { - get => emptyRecycleBinLabel; - private set => Set(ref emptyRecycleBinLabel, value); - } - - /// Gets if the UI refreshing should be supressed due to validation. - public bool SuppressFileTreeRefresh { - get => suppressRefresh || Scanning.SuppressFileTreeRefresh; - private set { - if (suppressRefresh != value) { - suppressRefresh = value; - if (!Scanning.SuppressFileTreeRefresh) { - if (!suppressRefresh) - RootItem?.RaiseChildrenReset(); - RaisePropertyChanged(nameof(SuppressFileTreeRefresh)); - } - } - } - } - - #endregion - - #region Visibility Properties - - /// Gets if the file types list should be hidden. - public bool HideFileTypes { - get => (!Settings.ShowFileTypes || (!Scanning.IsRefreshing && !Scanning.IsOpen)) && !IsInDesignMode; - } - /// Gets if the treemap view should be hidden. - public bool HideTreemap { - get => (!Settings.ShowTreemap || (!Scanning.IsRefreshing && !Scanning.IsOpen)) && !IsInDesignMode; - } - /// Gets if the toolbar should be hidden. - public bool HideToolBar => !Settings.ShowToolBar && !IsInDesignMode; - /// Gets if the status bar should be hidden. - public bool HideStatusBar => !Settings.ShowStatusBar && !IsInDesignMode; - /// Gets if the graph view is enabled and able to refres. - public bool GraphViewEnabled => Settings.ShowTreemap && !Scanning.IsRefreshing && Scanning.IsOpen; - /// - /// Gets if the elevate command should be hidden due to the process already being elevated. - /// - public bool HideElevateCommand => OS.IsElevated; - - #endregion - - #region Event Handlers - - private void OnRAMUsageTick() { - GCRAMUsage = GC.GetTotalMemory(false); - } - - private void OnStatusTick() { - RaisePropertyChanged(nameof(ScanTime)); - RaisePropertyChanged(nameof(ScanProgress)); - } - - private void OnSettingsPropertyChanged(object sender, PropertyChangedEventArgs e) { - UI.Invoke(() => { - switch (e.PropertyName) { - case nameof(SettingsService.RAMInterval): - ramTimer.Interval = Settings.RAMInterval; - break; - case nameof(SettingsService.StatusInterval): - statusTimer.Interval = Settings.StatusInterval; - break; - case nameof(SettingsService.ShowFileTypes): - RaisePropertyChanged(nameof(HideFileTypes)); - break; - case nameof(SettingsService.ShowTreemap): - RaisePropertyChanged(nameof(HideTreemap)); - RaisePropertyChanged(nameof(GraphViewEnabled)); - break; - case nameof(SettingsService.ShowToolBar): - RaisePropertyChanged(nameof(HideToolBar)); - break; - case nameof(SettingsService.ShowStatusBar): - RaisePropertyChanged(nameof(HideStatusBar)); - break; - } - }); - } - - private void OnScanningPropertyChanged(object sender, PropertyChangedEventArgs e) { - UI.Invoke(() => { - switch (e.PropertyName) { - case nameof(ScanningService.RootItem): - if (Scanning.RootItem == null) { - GraphViewRootItem = null; - RootItem = null; - } - else { - RootItem = new FileItemViewModel(this, Scanning.RootItem); - } - break; - case nameof(ScanningService.ProgressState): - switch (Scanning.ProgressState) { - case ScanProgressState.Starting: - //GraphViewRootItem = null; - break; - case ScanProgressState.Started: - statusTimer.Start(); - break; - case ScanProgressState.Ending: - statusTimer.Stop(); - break; - case ScanProgressState.Ended: - Extensions.Sort(ExtensionComparer.Compare); - GraphViewRootItem = Scanning.RootItem; - break; - case ScanProgressState.NotStarted: - GraphViewRootItem = null; - RootItem?.Dispose(); - RootItem = null; - //UpdateEmptyRecycleBin(); - break; - } - RaisePropertyChanged(nameof(Title)); - RaisePropertyChanged(nameof(ScanProgress)); - break; - case nameof(ScanningService.ScanState): - RaisePropertyChanged(nameof(HideFileTypes)); - RaisePropertyChanged(nameof(HideTreemap)); - RaisePropertyChanged(nameof(HideToolBar)); - RaisePropertyChanged(nameof(HideStatusBar)); - break; - case nameof(ScanningService.ScanTime): - RaisePropertyChanged(nameof(ScanTime)); - break; - case nameof(ScanningService.Progress): - RaisePropertyChanged(nameof(ScanProgress)); - break; - case nameof(ScanningService.CanDisplayProgress): - RaisePropertyChanged(nameof(CanDisplayScanProgress)); - break; - case nameof(ScanningService.IsOpen): - RaisePropertyChanged(nameof(IsOpen)); - RaisePropertyChanged(nameof(GraphViewEnabled)); - break; - case nameof(ScanningService.IsScanning): - RaisePropertyChanged(nameof(IsScanning)); - break; - case nameof(ScanningService.IsRefreshing): - RaisePropertyChanged(nameof(IsRefreshing)); - RaisePropertyChanged(nameof(GraphViewEnabled)); - //if (!Scanning.IsRefreshing) - // UpdateEmptyRecycleBin(); - break; - case nameof(ScanningService.SuppressFileTreeRefresh): - if (!suppressRefresh) { - RootItem?.RaiseChildrenReset(); - RaisePropertyChanged(nameof(SuppressFileTreeRefresh)); - } - break; - } - }); - } - - private void OnSelectedFilesChanged(object sender, NotifyCollectionChangedEventArgs e) { - FileItemViewModel newSelectedFile = SelectedFiles.FirstOrDefault(); - if (SelectedFile != newSelectedFile) { - SelectedFile = newSelectedFile; - RaisePropertyChanged(nameof(SelectedFile)); - if ((SelectedFile == null) != (newSelectedFile == null)) - RaisePropertyChanged(nameof(HasFileSelection)); - } - } - - #endregion - - #region IDisposable Implementation - - public void Dispose() { - Scanning.Dispose(); - statusTimer.Stop(); - ramTimer.Stop(); - } - - #endregion - - } -} diff --git a/WinDirStat.Net.Base/ViewModel/ViewModelCommandBase.cs b/WinDirStat.Net.Base/ViewModel/ViewModelCommandBase.cs deleted file mode 100644 index cc07618..0000000 --- a/WinDirStat.Net.Base/ViewModel/ViewModelCommandBase.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Windows.Input; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -#if WPF -using GalaSoft.MvvmLight.CommandWpf; -#else -using GalaSoft.MvvmLight.Command; -#endif - -namespace WinDirStat.Net.ViewModel { - /// An addition to the class with extra helper functions. - public abstract class ViewModelCommandBase : ViewModelBase { - - #region Fields - - /// The list of loaded commands. - private readonly Dictionary commands = new Dictionary(); - - #endregion - - #region Constructors - - public ViewModelCommandBase(IRelayCommandService relayCommand) - - #endregion - - #region Properties - - /// Gets all commands created with . - public IEnumerable Commands => commands.Values; - - #endregion - - #region GetCommand (Basic) - - /// - /// Gets the commnd if one exists, or assigns the passed command. - /// - /// - /// The new command to assign if one does not exist. - /// The name of the command. - /// The command from the command list. - protected TCommand GetCommand(TCommand newCommand, - [CallerMemberName] string commandName = null) - where TCommand : ICommand - { - if (!commands.TryGetValue(commandName, out ICommand command)) { - command = newCommand; - commands.Add(commandName, command); - } - return (TCommand) command; - } - - /// - /// Gets the commnd if one exists, or assigns calls the specified create command function. - /// - /// - /// The function to create the new command if one does not exist. - /// The name of the command. - /// The command from the command list. - protected TCommand GetCommand(Func createCommand, - [CallerMemberName] string commandName = null) - where TCommand : ICommand - { - if (!commands.TryGetValue(commandName, out ICommand command)) { - command = createCommand(); - commands.Add(commandName, command); - } - return (TCommand) command; - } - - #endregion - - #region GetCommand (RelayCommand) - - /// Gets or creates a new command with the specified parameters. - /// - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayCommand GetCommand(Action execute, Func canExecute = null, - [CallerMemberName] string commandName = null) - { - return GetCommand(() => new RelayCommand(execute, canExecute), commandName); - } - - #endregion - - #region GetCommand (RelayCommand) - - /// Gets or creates a new command with the specified parameters. - /// - /// The parameter type of the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayCommand GetCommand(Action execute, Func canExecute = null, - [CallerMemberName] string commandName = null) - { - return GetCommand(() => new RelayCommand(execute, canExecute), commandName); - } - - #endregion - - #region GetCommand (RelayUICommand) - - /// Gets or creates a new command with the specified parameters. - /// - /// The display text for the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayUICommand GetCommand(string text, Action execute, Func canExecute = null, - [CallerMemberName] string commandName = null) - { - return GetCommand(text, null, null, execute, canExecute, commandName); - } - - /// Gets or creates a new command with the specified parameters. - /// - /// The display text for the command. - /// The display icon for the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayUICommand GetCommand(string text, IImage icon, Action execute, - Func canExecute = null, [CallerMemberName] string commandName = null) - { - return GetCommand(text, icon, null, execute, canExecute, commandName); - } - - /// Gets or creates a new command with the specified parameters. - /// - /// The display text for the command. - /// The display icon for the command. - /// The keybind for the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayUICommand GetCommand(string text, IShortcut keyGesture, Action execute, - Func canExecute = null, [CallerMemberName] string commandName = null) - { - return GetCommand(text, null, keyGesture, execute, canExecute, commandName); - } - - /// Gets or creates a new command with the specified parameters. - /// - /// The display text for the command. - /// The display icon for the command. - /// The keybind for the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayUICommand GetCommand(string text, IImage icon, IShortcut keyGesture, - Action execute, Func canExecute = null, [CallerMemberName] string commandName = null) - { - return GetCommand(() => new RelayUICommand(text, icon, keyGesture, execute, canExecute), commandName); - } - - #endregion - - #region GetCommand (RelayUICommand) - - /// Gets or creates a new command with the specified parameters. - /// - /// The parameter type of the command. - /// The display text for the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayUICommand GetCommand(string text, Action execute, - Func canExecute = null, [CallerMemberName] string commandName = null) - { - return GetCommand(text, null, null, execute, canExecute, commandName); - } - - /// Gets or creates a new command with the specified parameters. - /// - /// The parameter type of the command. - /// The display text for the command. - /// The display icon for the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayUICommand GetCommand(string text, IImage icon, Action execute, - Func canExecute = null, [CallerMemberName] string commandName = null) - { - return GetCommand(text, icon, null, execute, canExecute, commandName); - } - - /// Gets or creates a new command with the specified parameters. - /// - /// The parameter type of the command. - /// The display text for the command. - /// The display icon for the command. - /// The keybind for the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayUICommand GetCommand(string text, IShortcut keyGesture, Action execute, - Func canExecute = null, [CallerMemberName] string commandName = null) - { - return GetCommand(text, null, keyGesture, execute, canExecute, commandName); - } - - /// Gets or creates a new command with the specified parameters. - /// - /// The parameter type of the command. - /// The display text for the command. - /// The display icon for the command. - /// The keybind for the command. - /// The execute method for the command. - /// The optional canExecute method for the command. - /// The name of the command to get or set. - /// The existing or created command. - protected RelayUICommand GetCommand(string text, IImage icon, IShortcut keyGesture, - Action execute, Func canExecute = null, [CallerMemberName] string commandName = null) - { - return GetCommand(() => new RelayUICommand(text, icon, keyGesture, execute, canExecute), commandName); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/ViewModelControlBase.cs b/WinDirStat.Net.Base/ViewModel/ViewModelControlBase.cs deleted file mode 100644 index 4ecd762..0000000 --- a/WinDirStat.Net.Base/ViewModel/ViewModelControlBase.cs +++ /dev/null @@ -1,25 +0,0 @@ -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.ViewModel { - /// An addition to the class with extra helper functions. - public abstract class ViewModelControlBase : ViewModelCommandBase { - - #region Fields - - /// The control owning this view model. - private IControl controlOwner; - - #endregion - - #region Properties - - /// Gets or sets the control owning this view model. - public IControl WindowOwner { - get => controlOwner; - set => Set(ref controlOwner, value); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/ViewModel/ViewModelWindowBase.cs b/WinDirStat.Net.Base/ViewModel/ViewModelWindowBase.cs deleted file mode 100644 index a26b313..0000000 --- a/WinDirStat.Net.Base/ViewModel/ViewModelWindowBase.cs +++ /dev/null @@ -1,32 +0,0 @@ -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.ViewModel { - /// An addition to the class with extra helper functions. - public abstract class ViewModelWindowBase : ViewModelCommandBase { - - #region Fields - - /// The window owning this view model. - private IWindow windowOwner; - - #endregion - - #region Virtual Properties - - /// Gets the title to display for the window. - public virtual string Title => "WinDirStat.Net"; - - #endregion - - #region Properties - - /// Gets or sets the window owning this view model. - public IWindow WindowOwner { - get => windowOwner; - set => Set(ref windowOwner, value); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Base/WinDirStat.Net.Base.csproj b/WinDirStat.Net.Base/WinDirStat.Net.Base.csproj deleted file mode 100644 index 3702582..0000000 --- a/WinDirStat.Net.Base/WinDirStat.Net.Base.csproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - WinDirStat.Net.Base - WinDirStat.Net - true - latest - Debug;Release - - - - - - - - - - - - net462 - - - - TRACE;DEBUG;WINDOWS;WPF - full - true - - - - TRACE;WINDOWS;WPF - - - - - - - - - - - - - - - - - - Rendering\TreemapRenderer.cs - - - Services\ScanningService.cs - - - Services\SettingsService.cs - - - ViewModel\DriveSelectViewModel.cs - - - ViewModel\MainViewModel.cs - - - ViewModel\Commands\RelayUICommand.cs - - - ViewModel\Files\FileItemViewModel.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WinDirStat.Net.Windows/Native/Win32.FindFile.cs b/WinDirStat.Net.Windows/Native/Win32.FindFile.cs deleted file mode 100644 index 0fc76db..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.FindFile.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - - /// - /// Searches a directory for a file or subdirectory with a name and attributes that match those - /// specified. - /// - /// - /// - /// The directory or path, and the file name. The file name can include wildcard characters, for - /// example, an asterisk (*) or a question mark (?). - /// - /// The information level of the returned data. - /// - /// A reference to the that receives the file data. - /// - /// - /// The type of filtering to perform that is different from wildcard matching. - /// - /// - /// A pointer to the search criteria if the specified fSearchOp needs structured search information. - /// - /// Specifies additional flags that control the search. - /// - /// If the function succeeds, the return value is a search handle used in a subsequent call to - /// or , and the - /// parameter contains information about the first file or directory found. - /// - /// If the function fails or fails to locate files from the search string in the lpFileName - /// parameter, the return value is . - /// - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr FindFirstFileEx( - string lpFileName, - FindExInfoLevels fInfoLevelId, - out Win32FindData lpFindFileData, - FindExSearchOps fSearchOp, - IntPtr lpSearchFilter, - [MarshalAs(UnmanagedType.U4)] FindExFlags dwAdditionalFlags); - - /// - /// Continues a file search from a previous call to the function. - /// - /// - /// - /// The search handle returned by a previous call to the function. - /// - /// - /// A pointer to the structure that receives information about the found - /// file or subdirectory. - /// - /// - /// If the function succeeds, the return value is true and the - /// parameter contains information about the next file or directory found. - /// - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern bool FindNextFile( - IntPtr hFindFile, - out Win32FindData lpFindFileData); - - /// - /// Closes a file search handle opened by the function. - /// - /// - /// The file search handle. - /// If the function succeeds, the return value is true. - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool FindClose( - IntPtr hFindFile); - - /// - /// Contains information about the file that is found by the , or function. - /// - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct Win32FindData { - /// The file attributes of a file. - [MarshalAs(UnmanagedType.U4)] - public FileAttributes dwFileAttributes; - /// - /// A structure that specifies when a file or directory was created. - /// - public FILETIME ftCreationTime; - /// - /// For a file, the structure specifies when the file was last read from, written to, or for - /// executable files, run. - /// - /// For a directory, the structure specifies when the directory is created. If the underlying - /// file system does not support last access time, this member is zero. - /// - /// On the FAT file system, the specified date for both files and directories is correct, but the - /// time of day is always set to midnight. - /// - public FILETIME ftLastAccessTime; - /// - /// For a file, the structure specifies when the file was last written to, truncated, or - /// overwritten. The date and time are not updated when file attributes or security descriptors - /// are changed. - /// - public FILETIME ftLastWriteTime; - /// The high-order value of the file size, in bytes. - public int nFileSizeHigh; - /// The low-order value of the file size, in bytes. - public uint nFileSizeLow; - /// Reserved for future use. - public uint dwReserved0; - /// Reserved for future use. - public uint dwReserved1; - /// The name of the file. - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string cFileName; - //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - //public string cAlternateFileName; - - /// True if the file is a directory. - public bool IsDirectory { - get => (dwFileAttributes.HasFlag(FileAttributes.Directory)); - } - /// True if the file is a symbolic link. - public bool IsSymbolicLink { - get => (dwFileAttributes.HasFlag(FileAttributes.ReparsePoint)); - } - /// True if the file is a relative directory and should be ignored. - public bool IsRelativeDirectory { - get => (cFileName == "." || cFileName == ".."); - } - /// The full size of the file. - public long Size { - get => ((long) nFileSizeHigh << 32) | nFileSizeLow; - } - - /// The UTC creation time of the file. - public DateTime CreationTimeUtc { - get => ftCreationTime.ToDateTimeUtc(); - } - /// The local creation time of the file. - public DateTime CreationTime { - get => ftCreationTime.ToDateTime(); - } - /// The UTC last access time of the file. - public DateTime LastAccessTimeUtc { - get => ftLastAccessTime.ToDateTimeUtc(); - } - /// The local last access time of the file. - public DateTime LastAccessTime { - get => ftLastAccessTime.ToDateTime(); - } - /// The UTC last write time of the file. - public DateTime LastWriteTimeUtc { - get => ftLastWriteTime.ToDateTimeUtc(); - } - /// The local last write time of the file. - public DateTime LastWriteTime { - get => ftLastWriteTime.ToDateTime(); - } - } - - public enum FindExInfoLevels { - /// - /// The FindFirstFileEx function retrieves a standard set of attribute information. The data is - /// returned in a structure. - /// - Standard, - /// - /// The FindFirstFileEx function does not query the short file name, improving overall - /// enumeration speed.The data is returned in a WIN32_FIND_DATA structure, and the - /// cAlternateFileName member is always a NULL string. Windows Server 2008, Windows Vista, - /// Windows Server 2003 and Windows XP: This value is not supported until Windows Server 2008 R2 - /// and Windows 7. - /// - Basic, - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - MaxInfoLevel, - } - public enum FindExSearchOps { - /// - /// The search for a file that matches a specified file name. The lpSearchFilter parameter of - /// must be NULL when this search operation is used. - /// - NameMatch, - /// - /// This is an advisory flag. If the file system supports directory filtering, the function - /// searches for a file that matches the specified name and is also a directory. If the file - /// system does not support directory filtering, this flag is silently ignored. The - /// lpSearchFilter parameter of the FindFirstFileEx function must be NULL when this search value - /// is used. If directory filtering is desired, this flag can be used on all file systems, but - /// because it is an advisory flag and only affects file systems that support it, the application - /// must examine the file attribute data stored in the lpFindFileData parameter of the function to determine whether the function has returned a handle to a - /// directory. - /// - LimitToDirectories, - /// This filtering type is not available. - LimitToDevices, - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - MaxSearchOp, - } - [Flags] - public enum FindExFlags : uint { - /// No flags. - None = 0, - /// Searches are case-sensitive. - CaseSensitive = 1, - /// - /// Uses a larger buffer for directory queries, which can increase performance of the find - /// operation. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This - /// value is not supported until Windows Server 2008 R2 and Windows 7. - /// - LargeFetch = 2, - /// - /// Limits the results to files that are physically on disk. This flag is only relevant when a - /// file virtualization filter is present. - /// - OnDiskEntriesOnly = 4, - } - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.ImageList.cs b/WinDirStat.Net.Windows/Native/Win32.ImageList.cs deleted file mode 100644 index 26d0363..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.ImageList.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - [DllImport("comctl32.dll", SetLastError = true)] - public static extern int ImageList_GetImageCount( - IntPtr hImageList); - - [DllImport("comctl32.dll", SetLastError = true)] - public static extern IntPtr ImageList_Duplicate( - IntPtr hImageList); - - [DllImport("comctl32.dll", SetLastError = true)] - public static extern IntPtr ImageList_Destroy( - IntPtr hImageList); - - [DllImport("comctl32.dll", SetLastError = true)] - public static extern int ImageList_Add( - IntPtr hImageList, - IntPtr image, - IntPtr mask); - - [DllImport("comctl32.dll", SetLastError = true)] - public static extern IntPtr ImageList_ExtractIcon( - IntPtr hInstance, - IntPtr hImageList, - int i); - - [DllImport("comctl32.dll", SetLastError = true)] - public static extern IntPtr ImageList_GetIcon( - IntPtr hImageList, - int i, - [MarshalAs(UnmanagedType.U4)] ImageListDrawFlags flags); - - [Flags] - public enum ImageListDrawFlags : uint { - Normal = 0x00000000, - Transparent = 0x00000001, - Blend25 = 0x00000002, - Focus = 0x00000002, - Blend50 = 0x00000004, - Selected = 0x00000004, - Blend = 0x00000004, - Mask = 0x00000010, - Image = 0x00000020, - Rop = 0x00000040, - OverlayMask = 0x00000F00, - PreserveAlpha = 0x00001000, - Scale = 0x00002000, - DpiScale = 0x00004000, - Async = 0x00008000, - } - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.RecycleBin.cs b/WinDirStat.Net.Windows/Native/Win32.RecycleBin.cs deleted file mode 100644 index 3833d1c..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.RecycleBin.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - - /// Information about the Recycle Bin returned by . - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct SHRecycleBinInfo { - public static readonly int CBSize = Marshal.SizeOf(); - - /// The size of this structure. - public int cbSize; - /// The size of items in the Recycle Bin. - public long i64Size; - /// The number of items in the Recycle Bin. - public long i64NumItems; - } - - /// Flags for . - [Flags] - public enum SHEmptyRecycleBinFlags : uint { - /// No flags. - None = 0, - /// No dialog box confirming the deletion of the objects will be displayed. - NoConfirmation = 0x00000001, - /// No dialog box indicating the progress will be displayed. - NoProgressUI = 0x00000002, - /// No sound will be played when the operation is complete. - NoSound = 0x00000004, - } - - /// - /// Retrieves the size of the Recycle Bin and the number of items in it, for a specified drive. - /// - /// - /// - /// The address of a null-terminated string of maximum length MAX_PATH to contain the path of the - /// root drive on which the Recycle Bin is located. This parameter can contain the address of a - /// string formatted with the drive, folder, and subfolder names (C:\Windows\System...). - /// - /// - /// The reference to a structure that receives the Recycle Bin - /// information. The cbSize member of the structure must be set to the size of the structure before - /// calling this API. - /// - /// False if the function succeeds. - [DllImport("shell32.dll", CharSet = CharSet.Auto)] - public static extern bool SHQueryRecycleBin( - string pszRootPath, - ref SHRecycleBinInfo pSHQueryRBInfo); - - /// Empties the Recycle Bin on the specified drive. - /// - /// - /// A handle to the parent window of any dialog boxes that might be displayed during the operation. - /// This parameter can be null. - /// - /// - /// The address of a null-terminated string of maximum length MAX_PATH that contains the path of the - /// root drive on which the Recycle Bin is located. This parameter can contain the address of a - /// string formatted with the drive, folder, and subfolder names, for example c:\windows\system. It - /// can also contain an empty string or null. If this value is an empty string or null, all Recycle - /// Bins on all drives will be emptied. - /// - /// - /// - [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Auto)] - public static extern bool SHEmptyRecycleBin( - IntPtr hWnd, - string pszRootPath, - [MarshalAs(UnmanagedType.U4)] SHEmptyRecycleBinFlags dwFlags); - - - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.SHFileOperation.cs b/WinDirStat.Net.Windows/Native/Win32.SHFileOperation.cs deleted file mode 100644 index 6e541ed..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.SHFileOperation.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - - /// File Operation Function Type for SHFileOperation. - public enum FileOperationFunc : uint { - /// Move the objects. - Move = 0x0001, - /// Copy the objects. - Copy = 0x0002, - /// Delete (or recycle) the objects. - Delete = 0x0003, - /// Rename the objects. - Rename = 0x0004, - } - - /// Possible flags for the SHFileOperation method. - [Flags] - public enum FileOperationFlags : ushort { - /// No flags. - None = 0, - - /// Do not show a dialog during the process - Silent = 0x0004, - /// Do not ask the user to confirm selection. - NoConfirmation = 0x0010, - /// - /// Delete the file to the recycle bin. (Required flag to send a file to the bin) - /// - AllowUndo = 0x0040, - /// Do not show the names of the files or folders that are being recycled. - SimpleProgress = 0x0100, - /// Surpress errors, if any occur during the process. - NoErrorUI = 0x0400, - /// - /// Warn if files are too big to fit in the recycle bin and will need to be deleted completely. - /// - WarnFilesTooBigForRecycleBin = 0x4000, - } - - /// SHFILEOPSTRUCT for SHFileOperation from COM. - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public struct SHFileOperationStruct { - public IntPtr hwnd; - [MarshalAs(UnmanagedType.U4)] - public FileOperationFunc wFunc; - [MarshalAs(UnmanagedType.LPTStr)] - public string pFrom; - [MarshalAs(UnmanagedType.LPTStr)] - public string pTo; - [MarshalAs(UnmanagedType.U2)] - public FileOperationFlags fFlags; - [MarshalAs(UnmanagedType.Bool)] - public bool fAnyOperationsAborted; - public IntPtr hNameMappings; - [MarshalAs(UnmanagedType.LPTStr)] - public string lpszProgressTitle; - } - - /// - /// Copies, moves, renames, or deletes a file system object. This function has been replaced in - /// Windows Vista by IFileOperation. - /// - /// - /// - /// A reference to an that contains information this function - /// needs to carry out the specified operation. This parameter must contain a valid value that is not - /// nulll. You are responsible for validating the value. If you do not validate it, you will - /// experience unexpected results. - /// - /// False on success. - [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Auto)] - public static extern bool SHFileOperation(ref SHFileOperationStruct FileOp); - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.SHGetFileInfo.cs b/WinDirStat.Net.Windows/Native/Win32.SHGetFileInfo.cs deleted file mode 100644 index 1ae4772..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.SHGetFileInfo.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - - /// Contains information about a file object. - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct SHFileInfo { - /// The marshaled size of the struct. - public static readonly int CBSize = Marshal.SizeOf(); - - /// - /// A handle to the icon that represents the file. You are responsible for destroying this handle - /// with DestroyIcon when you no longer need it. - /// - public IntPtr hIcon; - /// The index of the icon image within the system image list. - public int iIcon; - /// - /// An array of values that indicates the attributes of the file object. For information about - /// these values, see the IShellFolder::GetAttributesOf method. - /// - public uint dwAttributes; - /// - /// A string that contains the name of the file as it appears in the Windows Shell, or the path - /// and file name of the file that contains the icon representing the file. - /// - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string szDisplayName; - /// A string that describes the type of file. - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] - public string szTypeName; - } - - /// - /// The flags that specify the file information to retrieve for . - /// - [Flags] - public enum SHFileInfoFlags : uint { - None = 0, - LargeIcon = 0x000000000, - - SmallIcon = 0x000000001, - OpenIcon = 0x000000002, - ShellIconSize = 0x000000004, - PIDL = 0x000000008, - - UseFileAttributes = 0x000000010, - AddOverlays = 0x000000020, - OverlayIndex = 0x000000040, - - Icon = 0x000000100, - DisplayName = 0x000000200, - TypeName = 0x000000400, - Attributes = 0x000000800, - - IconLocation = 0x000001000, - ExeType = 0x000002000, - SysIconIndex = 0x000004000, - LinkOverlay = 0x000008000, - - Selected = 0x000010000, - AttrSpecified = 0x000020000, - } - - /// - /// Retrieves information about an object in the file system, such as a file, folder, directory, or - /// drive root. - /// - /// - /// - /// A string of maximum length MAX_PATH that contains the path and file name. Both absolute and - /// relative paths are valid. - /// - /// - /// A combination of one or more file attribute flags. If does not include - /// the flag, this parameter is ignored. - /// - /// A structure to receive the file information. - /// Use here. - /// - /// The flags that specify the file information to retrieve. This parameter can be a combination of - /// the following values. - /// - /// Returns a value whose meaning depends on the uFlags parameter. - [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr SHGetFileInfo( - string pszPath, - [MarshalAs(UnmanagedType.U4)] FileAttributes dwFileAttributes, - ref SHFileInfo psfi, - int cbFileInfo, - [MarshalAs(UnmanagedType.U4)] SHFileInfoFlags uFlags); - - [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr SHGetFileInfo( - IntPtr pszPath, - [MarshalAs(UnmanagedType.U4)] FileAttributes dwFileAttributes, - ref SHFileInfo psfi, - int cbFileInfo, - [MarshalAs(UnmanagedType.U4)] SHFileInfoFlags uFlags); - - [DllImport("shell32.dll", SetLastError = true)] - public static extern bool SHGetSpecialFolderLocation( - IntPtr hwnd, - [MarshalAs(UnmanagedType.I4)] Environment.SpecialFolder csidl, - ref IntPtr ppidl); - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.SHGetStockIconInfo.cs b/WinDirStat.Net.Windows/Native/Win32.SHGetStockIconInfo.cs deleted file mode 100644 index 2e9026f..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.SHGetStockIconInfo.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - /// - /// Used by to identify which stock system icon to retrieve. - /// - public enum SHStockIconID : uint { - DocNoAssoc = 0, - DocAssoc = 1, - Application = 2, - Folder = 3, - FolderOpen = 4, - Drive525 = 5, - Drive35 = 6, - DriveRemove = 7, - DriveFixed = 8, - DriveNet = 9, - DriveNetDisabled = 10, - DriveCD = 11, - DriveRAM = 12, - World = 13, - Server = 15, - Printer = 16, - MyNetwork = 17, - Find = 22, - Help = 23, - Share = 28, - Link = 29, - SlowFile = 30, - Recycler = 31, - RecyclerFull = 32, - MediaCDAudio = 40, - Lock = 47, - AutoList = 49, - PrinterNet = 50, - ServerShare = 51, - PrinterFax = 52, - PrenterFaxNet = 53, - PrinterFile = 54, - Stack = 55, - MediaSVCD = 56, - StuffedFolder = 57, - DriveUnknown = 58, - DriveDVD = 59, - MediaDVD = 60, - MediaDVDRAM = 61, - MediaDVDRW = 62, - MediaDVDR = 63, - MediaDVDROM = 64, - MediaCDAudioPlus = 65, - MediaCDRW = 66, - MediaCDR = 67, - MediaCDBurn = 68, - MediaCDBlank = 69, - MediaCDROM = 70, - AudioFiles = 71, - ImageFiles = 72, - VideoFiles = 73, - MixedFiles = 74, - FolderBack = 75, - FolderFront = 76, - Shield = 77, - Warning = 78, - Info = 79, - Error = 80, - Key = 81, - Software = 82, - Rename = 83, - Delete = 84, - MediaAudioDVD = 85, - MediaMovieDVD = 86, - MediaEnhancedCD = 87, - MediaEnhancedDVD = 88, - MediaHDDVD = 89, - MediaBluray = 90, - MediaVCD = 91, - MediaDVDPlusR = 92, - MediaDVDPlusRW = 93, - DesktopPC = 94, - MobilePC = 95, - Users = 96, - MediaSmartMedia = 97, - MediaCompactFlash = 98, - DeviceCellPhone = 99, - DeviceCamera = 100, - DeviceVideoCamera = 101, - DeviceAudioPlayer = 102, - NetworkConnect = 103, - Internet = 104, - ZipFile = 105, - Settings = 106, - DriveHDDVD = 132, - DriveBD = 133, - MediaHDDVDROM = 134, - MediaHDDVDR = 135, - MediaHDDVDRAM = 136, - MediaBDROM = 137, - MediaBDR = 138, - MediaBDRE = 139, - ClusteredDrive = 140, - MaxIcons = 175, - } - - [Flags] - public enum SHStockIconFlags : uint { - None = 0, - - IconLocation = 0, - LargeIcon = 0x000000000, - SmallIcon = 0x000000001, - ShellIconSize = 0x000000004, - Icon = 0x000000100, - SysIconIndex = 0x000004000, - LinkOverlay = 0x000008000, - Selected = 0x000010000, - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct SHStockIconInfo { - /// The marshaled size of the struct. - public static readonly int CBSize = Marshal.SizeOf(); - - public int cbSize; - public IntPtr hIcon; - public int iSysIconIndex; - public int iIcon; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string szPath; - } - - [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern bool SHGetStockIconInfo( - [MarshalAs(UnmanagedType.U4)] SHStockIconID siid, - [MarshalAs(UnmanagedType.U4)] SHStockIconFlags uFlags, - ref SHStockIconInfo psii); - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.Shell.cs b/WinDirStat.Net.Windows/Native/Win32.Shell.cs deleted file mode 100644 index 4e09c31..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.Shell.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - - /// - /// Requests the form of an item's display name to retrieve through . - /// - public enum SIGetDisplayName : uint { - /// - /// Returns the display name relative to the parent folder. In UI this name is generally ideal - /// for display to the user. - /// - NormalDisplay = 0x00000000, - /// - /// Returns the parsing name relative to the parent folder. This name is not suitable for use in - /// UI. - /// - ParentRelativeParsing = 0x80018001, - /// - /// Returns the parsing name relative to the desktop. This name is not suitable for use in UI. - /// - DesktopAbsoluteParsing = 0x80028000, - /// - /// Returns the editing name relative to the parent folder. In UI this name is suitable for - /// display to the user. - /// - ParentRelativeEditing = 0x80031001, - /// - /// Returns the editing name relative to the desktop. In UI this name is suitable for display to - /// the user. - /// - DesktopAbsoluteEditing = 0x8004c000, - /// - /// Returns the item's file system path, if it has one. Only items that report SFGAO_FILESYSTEM - /// have a file system path. When an item does not have a file system path, a call to on that item will fail. In UI this name is suitable for display to - /// the user in some cases, but note that it might not be specified for all items. - /// - FileSysPath = 0x80058000, - /// - /// Returns the item's URL, if it has one. Some items do not have a URL, and in those cases a - /// call to will fail. This name is suitable for display to the - /// user in some cases, but note that it might not be specified for all items. - /// - Url = 0x80068000, - /// - /// Returns the path relative to the parent folder in a friendly format as displayed in an - /// address bar. This name is suitable for display to the user. - /// - ParentRelativeForAddressBar = 0x8007c001, - /// Returns the path relative to the parent folder. - ParentRelative = 0x80080001, - /// Introduced in Windows 8. - ParentRelativeForUI = 0x80094001, - } - - // https://stackoverflow.com/a/29198314/7517185 - - /// - /// Translates a Shell namespace object's display name into an item identifier list and returns the - /// attributes of the object. This function is the preferred method to convert a string to a pointer - /// to an item identifier list (PIDL). - /// - /// - /// A string that contains the display name to parse. - /// This parameter is normally set to null. - /// - /// - /// - /// - [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern bool SHParseDisplayName( - string pszName, - IntPtr pbc, - out IntPtr ppidl, - int sfgaoIn, - out int psfgaoOut); - - /// Retrieves the display name of an item identified by its IDList. - /// - /// A PIDL that identifies the item. - /// - /// A value from the enumeration that specifies the type of display - /// name to retrieve. - /// - /// - /// A value that, when this function returns successfully, receives the display name. - /// - /// If this function succeeds, it returns false. Otherwise, it returns true. - [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern bool SHGetNameFromIDList( - IntPtr pidl, - SIGetDisplayName sigdnName, - out string ppszName); - - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.ShellExecute.cs b/WinDirStat.Net.Windows/Native/Win32.ShellExecute.cs deleted file mode 100644 index 0d2bbe0..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.ShellExecute.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - - [Flags] - public enum ShellExecuteMaskFlags : uint { - Default = 0x00000000, - ClassName = 0x00000001, - ClassKey = 0x00000003, - IDList = 0x00000004, - InvokeIDList = 0x0000000c, // Note SEE_MASK_INVOKEIDLIST(0xC) implies SEE_MASK_IDLIST(0x04) - HotKey = 0x00000020, - NoCloseProcess = 0x00000040, - ConnectNetDRV = 0x00000080, - NoAsync = 0x00000100, - FlagDDEWait = NoAsync, - DOEnvSubset = 0x00000200, - FlagNoUI = 0x00000400, - Unicode = 0x00004000, - NoConsole = 0x00008000, - AsyncOK = 0x00100000, - HMonitor = 0x00200000, - NoZoneChecks = 0x00800000, - NoQueryClassStore = 0x01000000, - WaitForInputIdle = 0x02000000, - MaskFlagLogUsage = 0x04000000, - } - - public enum ShowCommands : int { - Hide = 0, - ShowNormal = 1, - Normal = 1, - ShowMinimized = 2, - ShowMaximized = 3, - Maximize = 3, - ShowNoActive = 4, - Show = 5, - Minimize = 6, - ShowMinNoActive = 7, - ShowNA = 8, - Restore = 9, - ShowDefault = 10, - ForceMinimize = 11, - Max = 11 - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public struct ShellExecuteInfo { - public static readonly int CBSize = Marshal.SizeOf(); - - public int cbSize; - [MarshalAs(UnmanagedType.U4)] - public ShellExecuteMaskFlags fMask; - public IntPtr hwnd; - [MarshalAs(UnmanagedType.LPTStr)] - public string lpVerb; - [MarshalAs(UnmanagedType.LPTStr)] - public string lpFile; - [MarshalAs(UnmanagedType.LPTStr)] - public string lpParameters; - [MarshalAs(UnmanagedType.LPTStr)] - public string lpDirectory; - [MarshalAs(UnmanagedType.I4)] - public ShowCommands nShow; - public IntPtr hInstApp; - public IntPtr lpIDList; - [MarshalAs(UnmanagedType.LPTStr)] - public string lpClass; - public IntPtr hkeyClass; - public uint dwHotKey; - public IntPtr hIcon; - public IntPtr hProcess; - } - - [DllImport("shell32.dll", CharSet = CharSet.Auto)] - public static extern bool ShellExecuteEx(ref ShellExecuteInfo lpExecInfo); - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.Windows.cs b/WinDirStat.Net.Windows/Native/Win32.Windows.cs deleted file mode 100644 index d1042f3..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.Windows.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using System.Windows; - -namespace WinDirStat.Net.Windows.Native { - partial class Win32 { - - public enum WindowLongs : int { - ExStyle = -20, - HInstance = -6, - HwndParent = -8, - ID = -12, - Style = -16, - UserData = -21, - WndProc = -4, - User = 0x8, - MsgResult = 0x0, - DlgProc = 0x4 - } - - public const int GWL_STYLE = -16; - - [Flags] - public enum WindowStyles : uint { - None = 0, - VScroll = 0x00200000, - HScroll = 0x00100000, - Visible = 0x10000000, - Border = 0x00800000, - Overlapped = 0x00000000, - Tiled = 0x00000000, - Maximize = 0x01000000, - Minimize = 0x20000000, - Iconic = 0x20000000, - ThickFrame = 0x00040000, - SizeBox = 0x00040000, - Popup = 0x80000000, - PopupWindow = Popup | Border | SysMenu, - DlgFrame = 0x00400000, - Caption = 0x00C00000, - ChildWindow = 0x40000000, - SysMenu = 0x00080000, - MinimizeBox = 0x00020000, - MaximizeBox = 0x00010000, - OverlappedWindow = Overlapped | Caption | SysMenu | ThickFrame | MinimizeBox | MaximizeBox, - Child = 0x40000000, - ClipChildren = 0x02000000, - ClipSiblings = 0x04000000, - Disabled = 0x08000000, - Group = 0x00020000, - Tabstop = 0x00010000, - TiledWindow = Tiled | Caption | SysMenu | ThickFrame | MinimizeBox | MaximizeBox, - } - - [DllImport("user32.dll")] - public static extern uint GetWindowLong( - IntPtr hWnd, - [MarshalAs(UnmanagedType.U4)] WindowLongs nIndex); - - [DllImport("user32.dll")] - public static extern uint SetWindowLong( - IntPtr hWnd, - [MarshalAs(UnmanagedType.U4)] WindowLongs nIndex, - uint dwNewLong); - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32.cs b/WinDirStat.Net.Windows/Native/Win32.cs deleted file mode 100644 index 84a43cd..0000000 --- a/WinDirStat.Net.Windows/Native/Win32.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace WinDirStat.Net.Windows.Native { - /// A static class for native methods, structs, and enums. - public static partial class Win32 { - - /// An invalid handle value of -1 returned from some functions. - public static readonly IntPtr InvalidHandle = new IntPtr(-1); - - /// Invalid low-order file size returned by . - public const uint InvalidFileSize = 0xFFFFFFFF; - - /// - /// Retrieves information about the amount of space that is available on a disk volume, which is the - /// total amount of space, the total amount of free space, and the total amount of free space - /// available to the user that is associated with the calling thread. - /// - /// - /// A directory on the disk. - /// - /// Receives the total number of free bytes on a disk that are available to the user who is - /// associated with the calling thread. - /// - /// - /// A pointer to a variable that receives the total number of bytes on a disk that are available to - /// the user who is associated with the calling thread. - /// - /// Receives the total number of free bytes on a disk. - /// If the function succeeds, the return value is true. - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetDiskFreeSpaceEx( - string lpDirectoryName, - out ulong lpFreeBytesAvailable, - out ulong lpTotalNumberOfBytes, - out ulong lpTotalNumberOfFreeBytes); - - /// - /// Retrieves the actual number of bytes of disk storage used to store a specified file. If the file - /// is located on a volume that supports compression and the file is compressed, the value obtained - /// is the compressed size of the specified file. If the file is located on a volume that supports - /// sparse files and the file is a sparse file, the value obtained is the sparse size of the - /// specified file. - /// - /// - /// The name of the file. - /// - /// The high-order DWORD of the compressed file size. The function's return value is the low-order - /// DWORD of the compressed file size. - /// - /// - /// If the function succeeds, the return value is the low-order DWORD of the actual number of bytes - /// of disk storage used to store the specified file, and if lpFileSizeHigh is non-NULL, the function - /// puts the high-order DWORD of that actual value into the DWORD pointed to by that parameter. This - /// is the compressed file size for compressed files, the actual file size for noncompressed files. - /// - /// If the function fails, and lpFileSizeHigh is NULL, the return value is INVALID_FILE_SIZE. To get - /// extended error information, call GetLastError. - /// - [DllImport("kernel32.dll", SetLastError = true)] - public static extern uint GetCompressedFileSize( - string lpFileName, - out int lpFileSizeHigh); - - /// Destroys an icon and frees any memory the icon occupied. - /// - /// A handle to the icon to be destroyed. The icon must not be in use. - /// If the function succeeds, the return value is true. - [DllImport("user32.dll", SetLastError = true)] - public static extern bool DestroyIcon( - IntPtr hIcon); - - /// - /// The DeleteObject function deletes a logical pen, brush, font, bitmap, region, or palette, freeing - /// all system resources associated with the object. After the object is deleted, the specified - /// handle is no longer valid. - /// - /// - /// A handle to a logical pen, brush, font, bitmap, region, or palette. - /// If the function succeeds, the return value is true. - [DllImport("gdi32.dll", SetLastError = true)] - public static extern bool DeleteObject( - IntPtr hObject); - - /// - /// Retrieves the path of the system directory. The system directory contains system files such as - /// dynamic-link libraries and drivers. - /// - /// - /// Receives the path - /// The maximum size of the buffer. - /// If the function succeeds, the return value is the length. - [DllImport("kernel32.dll", SetLastError = true)] - public static extern uint GetSystemDirectory(out string lpBuffer, int uSize); - - } -} diff --git a/WinDirStat.Net.Windows/Native/Win32Extensions.cs b/WinDirStat.Net.Windows/Native/Win32Extensions.cs deleted file mode 100644 index e641a7b..0000000 --- a/WinDirStat.Net.Windows/Native/Win32Extensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; - -namespace WinDirStat.Net.Windows.Native { - /// Extentions for native Win32 structures. - internal static class Win32Extensions { - - #region ToDateTime - - /// Converts the native to a local . - public static DateTime ToDateTime(this FILETIME fileTime) { - long ticks = ((long) fileTime.dwHighDateTime << 32) | unchecked((uint) fileTime.dwLowDateTime); - return DateTime.FromFileTime(ticks); - } - - /// Converts the native to a UTC . - public static DateTime ToDateTimeUtc(this FILETIME fileTime) { - long ticks = ((long) fileTime.dwHighDateTime << 32) | unchecked((uint) fileTime.dwLowDateTime); - return DateTime.FromFileTimeUtc(ticks); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Windows/Services/Structures/WindowsScanFileInfo.cs b/WinDirStat.Net.Windows/Services/Structures/WindowsScanFileInfo.cs deleted file mode 100644 index d35d06b..0000000 --- a/WinDirStat.Net.Windows/Services/Structures/WindowsScanFileInfo.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Filesystem.Ntfs; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Windows.Native; - -namespace WinDirStat.Net.Windows.Services.Structures { - /// Information about a file used to populate a file item. - public class WindowsScanFileInfo : IScanFileInfo { - - #region Fields - - /// The name of the file. - public string Name { get; } - /// The full path of the file. - public string FullName { get; } - /// The size of the file. - public long Size { get; } - /// The attributes of the file. - public FileAttributes Attributes { get; } - /// The UTC creation time of the file. - public DateTime CreationTimeUtc { get; } - /// The UTC last access time of the file. - public DateTime LastAccessTimeUtc { get; } - /// The UTC last write time of the file. - public DateTime LastWriteTimeUtc { get; } - - #endregion - - #region Constructors - - /// - /// Constructs the from a . - /// - internal WindowsScanFileInfo(Win32.Win32FindData find, string path) { - Name = find.cFileName; - FullName = path; - Size = find.Size; - Attributes = find.dwFileAttributes; - CreationTimeUtc = find.CreationTimeUtc; - LastAccessTimeUtc = find.LastAccessTimeUtc; - LastWriteTimeUtc = find.LastWriteTimeUtc; - } - - /// Constructs the from a . - internal WindowsScanFileInfo(INtfsNode node) { - Name = node.Name; - FullName = node.FullName; - Size = (long) node.Size; - Attributes = node.Attributes; - CreationTimeUtc = node.CreationTime; - LastAccessTimeUtc = node.LastAccessTime; - LastWriteTimeUtc = node.LastChangeTime; - } - - #endregion - - #region Properties - - /// Gets if the file is a directory. - public bool IsDirectory => Attributes.HasFlag(FileAttributes.Directory); - /// Gets if the file is a symbolic link. - public bool IsSymbolicLink => Attributes.HasFlag(FileAttributes.ReparsePoint); - - #endregion - } -} diff --git a/WinDirStat.Net.Windows/Services/WindowsIconCacheService.cs b/WinDirStat.Net.Windows/Services/WindowsIconCacheService.cs deleted file mode 100644 index da8eadf..0000000 --- a/WinDirStat.Net.Windows/Services/WindowsIconCacheService.cs +++ /dev/null @@ -1,387 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using static WinDirStat.Net.Windows.Native.Win32; - -namespace WinDirStat.Net.Windows.Services { - /// A service for caching file and folder icons. - public class WindowsIconCacheService : ObservableObject, IIconCacheService { - - #region Constants - - private const SHFileInfoFlags CacheIconFlags = - SHFileInfoFlags.SysIconIndex | SHFileInfoFlags.SmallIcon; - - private const SHFileInfoFlags CacheFileTypeFlags = CacheIconFlags | - SHFileInfoFlags.UseFileAttributes | SHFileInfoFlags.TypeName; - - private const SHFileInfoFlags CacheSpecialFolderFlags = CacheIconFlags | - SHFileInfoFlags.PIDL; - - private const SHStockIconFlags CacheStockIconFlags = - SHStockIconFlags.SysIconIndex | SHStockIconFlags.Icon | SHStockIconFlags.SmallIcon; - - #endregion - - #region Fields - - /// The default file icon. - private IImage fileIcon; - /// The default folder icon. - private IImage folderIcon; - /// The default drive icon. - private IImage volumeIcon; - /// The default shortcut icon. - private IImage shortcutIcon; - - /// The service for performing UI actions such as dispatcher invoking. - private readonly IUIService ui; - /// The service for creating and loading bitmaps. - private readonly IBitmapFactory bitmapFactory; - private readonly Dictionary cachedIcons; - private readonly Dictionary cachedSpecialFolders; - private readonly Dictionary cachedFileTypes; - private readonly ObservableCollection cachedIconList; - - #endregion - - #region Constructors - - /// Constructs the . - public WindowsIconCacheService(IUIService ui, - IBitmapFactory bitmapFactory) { - this.ui = ui; - this.bitmapFactory = bitmapFactory; - - cachedIcons = new Dictionary(); - cachedSpecialFolders = new Dictionary(); - cachedFileTypes = new Dictionary(); - cachedIconList = new ObservableCollection(); - } - - #endregion - - #region Properties - - /// Gets the number of cached icons. - public int Count => cachedIcons.Count; - - #endregion - - #region Icon Properties - - /// Gets the default file icon. - public IImage FileIcon { - get => fileIcon ?? (fileIcon = CacheStockIcon(SHStockIconID.DocNoAssoc)); - } - /// Gets the default folder icon. - public IImage FolderIcon { - get => folderIcon ?? (folderIcon = CacheStockIcon(SHStockIconID.Folder)); - } - /// Gets the default drive icon. - public IImage VolumeIcon { - get => volumeIcon ?? (volumeIcon = CacheStockIcon(SHStockIconID.DriveFixed)); - } - /// Gets the default shortcut icon. - public IImage ShortcutIcon { - get => shortcutIcon ?? (shortcutIcon = CacheStockIcon(SHStockIconID.Link)); - } - - #endregion - - #region Icon Caching - - /// Caches the icon of the specified file. - /// - /// The path of the file. - /// The cached icon on success, otherwise null. - public IImage CacheIcon(string path) { - return ui.Invoke(() => CacheIconImpl(path, 0, SHFileInfoFlags.None, out _, out _)); - } - /// Asynchronousy caches the icon of the specified file. - /// - /// The path of the file. - /// The method that returns the icon upon completion. - public void CacheIconAsync(string path, ICacheIconCallback callback) { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - ui.BeginInvoke(() => callback(CacheIcon(path)), false); - } - - /// Caches the icon and display name of the specified file. - /// - /// The path of the file. - /// The cached icon and icon on success, otherwise null. - public IIconAndName CacheIconAndDisplayName(string path) { - return ui.Invoke(() => { - IImage icon = CacheIconImpl(path, 0, SHFileInfoFlags.DisplayName, out string name, out _); - if (icon != null) - return new IIconAndName(icon, name); - return null; - }); - } - /// Asynchronousy caches the icon and display name of the specified file. - /// - /// The path of the file. - /// The method that returns the icon and name upon completion. - public void CacheIconAndDisplayNameAsync(string path, ICacheIconAndNameCallback callback) { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - ui.BeginInvoke(() => callback(CacheIconAndDisplayName(path)), false); - } - - /// Caches the file type's icon and type name. - /// - /// The extension of the file type. - /// The cached icon and type name on success, otherwise null. - public IIconAndName CacheFileType(string extension) { - return ui.Invoke(() => { - if (!cachedFileTypes.TryGetValue(extension, out IIconAndName iconName)) { - try { - // Empty extensions will just return the Local Disk instead of a proper file - string extensionPath = extension; - if (extension == ExtensionItem.EmptyExtension) - extensionPath = Guid.NewGuid().ToString(); - IImage icon = CacheIconImpl(extensionPath, FileAttributes.Normal, - CacheFileTypeFlags, out _, out string typeName); - if (icon != null) - iconName = new IIconAndName(icon, typeName); - cachedFileTypes.Add(extension, iconName); - } - catch { } - } - return iconName; - }); - } - /// Asynchronousy caches the file type's icon and type name. - /// - /// The extension of the file type. - /// The method that returns the icon and type name upon completion. - public void CacheFileTypeAsync(string extension, ICacheIconAndNameCallback callback) { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - ui.BeginInvoke(() => callback(CacheFileType(extension)), false); - } - - /// Caches the special folder's icon and display name. - /// - /// The special folder type. - /// The cached icon and name on success, otherwise null. - public IIconAndName CacheSpecialFolder(Environment.SpecialFolder folder) { - return ui.Invoke(() => { - if (!cachedSpecialFolders.TryGetValue(folder, out IIconAndName iconName)) { - try { - IImage icon = CacheSpecialFolderImpl(folder, 0, SHFileInfoFlags.DisplayName, - out string name, out _); - if (icon != null) - iconName = new IIconAndName(icon, name); - cachedSpecialFolders.Add(folder, iconName); - } - catch { } - } - return iconName; - }); - } - /// Asynchronousy caches the special folder's icon and display name. - /// - /// The special folder type. - /// The method that returns the icon and name upon completion. - public void CacheSpecialFolderAsync(Environment.SpecialFolder folder, ICacheIconAndNameCallback callback) { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - ui.BeginInvoke(() => callback(CacheSpecialFolder(folder)), false); - } - - #endregion - - #region Private Icon Caching - - /// Caches a stock icon. - /// - /// The id of the stock icon. - /// The icon on success, otherwise null. - private IImage CacheStockIcon(SHStockIconID id) { - return ui.Invoke(() => CacheStockIconImpl(id, SHStockIconFlags.None)); - } - - #endregion - - #region Cache Implementation - - /// The implementation for caching icons with a path. - /// - /// The file path or extension. - /// The optional file attributes. - /// Get flags for getting the icon. - /// - /// The output display name if is used in . - /// - /// - /// The output type name if is used in . - /// - /// The icon on success, otherwise null. - private IImage CacheIconImpl(string path, FileAttributes attributes, SHFileInfoFlags flags, - out string displayName, out string typeName) - { - displayName = null; - typeName = null; - flags |= CacheIconFlags; - - IImage icon = null; - SHFileInfo fileInfo = new SHFileInfo(); - IntPtr hImageList = SHGetFileInfo(path, attributes, ref fileInfo, SHFileInfo.CBSize, flags); - try { - if (hImageList == IntPtr.Zero) - return null; - - if (flags.HasFlag(SHFileInfoFlags.DisplayName)) - displayName = fileInfo.szDisplayName; - if (flags.HasFlag(SHFileInfoFlags.TypeName)) - typeName = fileInfo.szTypeName; - - icon = TryAddIconToCache(fileInfo.iIcon, () => ExtractIcon(hImageList, fileInfo.iIcon)); - if (icon != null) - Debug.WriteLine($"Cache[{Count}]: " + path); - else - Debug.WriteLine($"Failed to load icon for \"{path}\"!"); - } - finally { - ImageList_Destroy(hImageList); - } - return icon; - } - - /// The implementation for caching icons with a special folder. - /// - /// The special folder to get the icon of. - /// The optional file attributes. - /// Get flags for getting the icon. - /// - /// The output display name if is used in . - /// - /// - /// The output type name if is used in . - /// - /// The icon on success, otherwise null. - private IImage CacheSpecialFolderImpl(Environment.SpecialFolder folder, FileAttributes attributes, - SHFileInfoFlags flags, out string displayName, out string typeName) - { - displayName = null; - typeName = null; - flags |= CacheSpecialFolderFlags; - - IntPtr pidl = IntPtr.Zero; - IImage icon = null; - SHFileInfo fileInfo = new SHFileInfo(); - if (SHGetSpecialFolderLocation(IntPtr.Zero, folder, ref pidl)) - return null; - IntPtr hImageList = SHGetFileInfo(pidl, attributes, ref fileInfo, SHFileInfo.CBSize, flags); - try { - if (hImageList == IntPtr.Zero) - return null; - - if (flags.HasFlag(SHFileInfoFlags.DisplayName)) - displayName = fileInfo.szDisplayName; - if (flags.HasFlag(SHFileInfoFlags.TypeName)) - typeName = fileInfo.szTypeName; - - icon = TryAddIconToCache(fileInfo.iIcon, () => ExtractIcon(hImageList, fileInfo.iIcon)); - if (icon != null) - Debug.WriteLine($"Cache[{Count}]: " + pidl); - else - Debug.WriteLine($"Failed to load icon for \"{pidl}\"!"); - } - finally { - ImageList_Destroy(hImageList); - Marshal.FreeCoTaskMem(pidl); - } - return icon; - } - - /// The implementation for caching stock icons. - /// - /// The id of the stock icon. - /// The flags for caching the stock icon. - /// The icon on success, otherwise null. - private IImage CacheStockIconImpl(SHStockIconID id, SHStockIconFlags flags) { - flags |= CacheStockIconFlags; - - IImage icon = null; - SHStockIconInfo stockInfo = new SHStockIconInfo { - cbSize = SHStockIconInfo.CBSize, - }; - if (SHGetStockIconInfo(id, flags, ref stockInfo)) - return null; - try { - if (!cachedIcons.TryGetValue(stockInfo.iSysIconIndex, out icon)) { - icon = TryAddIconToCache(stockInfo.iSysIconIndex, () => ExtractIcon(stockInfo.hIcon)); - if (icon != null) - Debug.WriteLine($"Cache[{Count}]: " + id); - else - Debug.WriteLine($"Failed to load icon for \"{id}\"!"); - } - } - finally { - DestroyIcon(stockInfo.hIcon); - } - return icon; - } - - #endregion - - #region Add/Extracting - - /// - /// Tries to add the icon to the cache, if it does exist, is called to get - /// the icon. - /// - /// - /// The system index of the icon. - /// The method to extract the icon. - /// The extracted icon on success, otherwise null. - private IImage TryAddIconToCache(int systemIndex, Func extract) { - if (!cachedIcons.TryGetValue(systemIndex, out IImage icon)) { - try { - icon = extract(); - cachedIcons.Add(systemIndex, icon); - cachedIconList.Add(icon); - } - catch { } - } - return icon; - } - - /// Extracts the icon from the image list. - /// - /// The handle to the image list. - /// The system index of the icon. - /// The extracted icon on success, otherwise null. - private IImage ExtractIcon(IntPtr hImageList, int systemIndex) { - IntPtr hIcon = ImageList_GetIcon(hImageList, systemIndex, ImageListDrawFlags.Normal); - try { - return ExtractIcon(hIcon); - } - finally { - if (hIcon != IntPtr.Zero) - DestroyIcon(hIcon); - } - } - - /// Extracts the icon from the handle. - /// - /// The handle to the icon. - /// The extracted icon on success, otherwise null. - protected IImage ExtractIcon(IntPtr hIcon) { - return bitmapFactory.FromHIcon(hIcon); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Windows/Services/WindowsOSService.cs b/WinDirStat.Net.Windows/Services/WindowsOSService.cs deleted file mode 100644 index f50ffa6..0000000 --- a/WinDirStat.Net.Windows/Services/WindowsOSService.cs +++ /dev/null @@ -1,241 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Security.Principal; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using static WinDirStat.Net.Windows.Native.Win32; - -namespace WinDirStat.Net.Windows.Services { - /// A service for OS-specific actions. - public class WindowsOSService : IOSService { - - #region Fields - - /// The service for performing UI actions such as dispatcher invoking. - private readonly IUIService ui; - /// True if the current process has elevated privileges. - private bool? isElevated; - - #endregion - - #region Constructors - - /// Constructs the . - public WindowsOSService(IUIService ui) { - this.ui = ui; - } - - #endregion - - #region Privileges - - /// Gets if the current process has elevated privileges. - public bool IsElevated { - get { - if (!isElevated.HasValue) - isElevated = WindowsIdentity.GetCurrent().Owner - .IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid); - return isElevated.Value; - } - } - - public void StartNewElevated(string arguments = "") { - Process current = Process.GetCurrentProcess(); - ProcessStartInfo startInfo = new ProcessStartInfo { - FileName = current.MainModule.FileName, - Arguments = arguments + " " + string.Join(" ", Environment.GetCommandLineArgs().Select(a => "\"" + a + "\"")), - WorkingDirectory = Directory.GetCurrentDirectory(), - Verb = "runas", - }; - Process.Start(startInfo).Dispose(); - } - - #endregion - - #region RunItem - - /// Opens the specified item using the default action. - /// - /// The file to open. - public void RunItem(string file) { - ProcessStartInfo startInfo = new ProcessStartInfo { - FileName = file, - }; - Process.Start(startInfo)?.Dispose(); - } - - #endregion - - #region Explore - - /// Opens the computer folder in Explorer. - public void ExploreComputer() { - ProcessStartInfo startInfo = new ProcessStartInfo { - FileName = "explorer.exe", - Arguments = "::{20d04fe0-3aea-1069-a2d8-08002b30309d}", - }; - Process.Start(startInfo)?.Dispose(); - } - - /// Opens the folder in Explorer. - /// - /// The path of the folder to open. - public void ExploreFolder(string folderPath) { - ProcessStartInfo startInfo = new ProcessStartInfo { - FileName = "explorer.exe", - Arguments = $"\"{folderPath}\"", - }; - Process.Start(startInfo)?.Dispose(); - } - - /// Opens the parent folder in Explorer and selects the file. - /// - /// The path of the file to select. - public void ExploreFile(string filePath) { - ProcessStartInfo startInfo = new ProcessStartInfo { - FileName = "explorer.exe", - Arguments = $"/select,\"{filePath}\"", - }; - Process.Start(startInfo)?.Dispose(); - } - - /// Opens the properties window for the computer. - public bool OpenComputerProperties(string filePath) { - return OpenProperties("::{20d04fe0-3aea-1069-a2d8-08002b30309d}"); - } - - /// Opens the properties window of the file. - /// The path of the file to view the properties of. - public bool OpenProperties(string filePath) { - ShellExecuteInfo info = new ShellExecuteInfo { - cbSize = ShellExecuteInfo.CBSize, - lpVerb = "properties", - lpFile = filePath, - nShow = ShowCommands.Show, - fMask = ShellExecuteMaskFlags.InvokeIDList, - }; - return ShellExecuteEx(ref info); - } - - #endregion - - #region Console - - /// Opens the command prompt in the specified working directory. - /// - /// The working directory to open the command prompt in. - public void OpenCommandPrompt(string directory) { - ProcessStartInfo startInfo = new ProcessStartInfo { - FileName = "cmd.exe", - WorkingDirectory = directory, - }; - Process.Start(startInfo)?.Dispose(); - } - - /// Opens PowerShell in the specified working directory. - /// - /// The working directory to open PowerShell in. - public void OpenPowerShell(string directory) { - ProcessStartInfo startInfo = new ProcessStartInfo { - FileName = "powershell.exe", - WorkingDirectory = directory, - }; - Process.Start(startInfo)?.Dispose(); - } - - #endregion - - #region Delete/Recycle - - /// Permanently deletes the file. - /// - /// The path of the file to delete. - /// True if the operation was successful. - public bool DeleteFile(string file) { - return DeleteOrRecycleFile(file, false); - } - - /// Sends the file or directory to the recycle bin. - /// - /// The path of the file to delete. - /// True if the operation was successful. - public bool RecycleFile(string file) { - return DeleteOrRecycleFile(file, true); - } - - /// Deletes or recycles the file based on the conditional value. - /// - /// The path of the file to delete. - /// True if the file should be recycled. - /// True if the operation was successful. - public bool DeleteOrRecycleFile(string file, bool recycle) { - return ui.Invoke(() => { - FileOperationFlags flags = FileOperationFlags.None; - if (recycle) - flags = FileOperationFlags.AllowUndo | FileOperationFlags.WarnFilesTooBigForRecycleBin; - SHFileOperationStruct fileOp = new SHFileOperationStruct { - wFunc = FileOperationFunc.Delete, - pFrom = file + '\0' + '\0', - fFlags = flags, - }; - return !SHFileOperation(ref fileOp); - }); - } - - /// Empties the recycle bin at the specified path. - /// - /// The window to own the dialogs. - /// The path of the recycle bin - /// True if the operation was successful. - public bool EmptyRecycleBin(IWindow owner, string path = "") { - return ui.Invoke(() => { - return !SHEmptyRecycleBin(owner.Handle, path, SHEmptyRecycleBinFlags.None); - }); - } - - /// Gets the stats about the specified recycle bin. - /// - /// The path of the recycle bin - /// The info about the recycle bin on success, otherwise null. - public RecycleBinInfo GetRecycleBinInfo(string path) { - //return ui.Invoke(() => { - SHRecycleBinInfo rbInfo = new SHRecycleBinInfo { - cbSize = SHRecycleBinInfo.CBSize, - }; - if (!SHQueryRecycleBin(path, ref rbInfo)) - return new RecycleBinInfo(path, rbInfo.i64NumItems, rbInfo.i64Size); - return null; - //}); - } - - /// Gets the stats about every recycle bin. - /// - /// The info about the recycle bin on success, otherwise null. - public RecycleBinInfo GetAllRecycleBinInfo() { - //return ui.Invoke(() => { - long itemCount = 0; - long size = 0; - foreach (DriveInfo driveInfo in DriveInfo.GetDrives()) { - if (driveInfo.IsReady && driveInfo.DriveType != DriveType.Unknown && - driveInfo.DriveType != DriveType.NoRootDirectory) - { - RecycleBinInfo rbInfo = GetRecycleBinInfo(driveInfo.Name); - if (rbInfo != null) { - itemCount += rbInfo.ItemCount; - size += rbInfo.Size; - } - } - } - return new RecycleBinInfo(itemCount, size); - //}); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Windows/Services/WindowsScanningService.Mft.cs b/WinDirStat.Net.Windows/Services/WindowsScanningService.Mft.cs deleted file mode 100644 index 8adcc7b..0000000 --- a/WinDirStat.Net.Windows/Services/WindowsScanningService.Mft.cs +++ /dev/null @@ -1,165 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Filesystem.Ntfs; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Utils; -using WinDirStat.Net.Windows.Services.Structures; - -namespace WinDirStat.Net.Windows.Services { - partial class WindowsScanningService { - - #region Private Structures - - private class FileNodeIndexes { - public FileItemBase FileItem; - public FolderItem FileCollection; - public FileItem FirstFile; - public uint NodeIndex; - public uint ParentNodeIndex; - public string FullName; - - public FileNodeIndexes(FileItemBase fileItem, INtfsNode ntfsNode) { - FileItem = fileItem; - NodeIndex = ntfsNode.NodeIndex; - ParentNodeIndex = ntfsNode.ParentNodeIndex; - FullName = PathUtils.TrimSeparatorDotEnd(ntfsNode.FullName); - } - } - - #endregion - - private void ScanMtf(ScanningState state, CancellationToken token) { - FileNodeIndexes[] fileItemsLookup; - List fileItems = new List(); - - DriveInfo driveInfo = new DriveInfo(Path.GetPathRoot(state.RootPath)); - using (NtfsReader ntfs = new NtfsReader(driveInfo, RetrieveMode.StandardInformations)) { - fileItemsLookup = new FileNodeIndexes[ntfs.NodeCount]; - ReadMft(state, ntfs, fileItemsLookup, fileItems, token); - } - - foreach (FileNodeIndexes indexes in fileItems) { - FileItemBase item = indexes.FileItem; - FileNodeIndexes parentIndexes = fileItemsLookup[indexes.ParentNodeIndex]; - if (indexes.NodeIndex == indexes.ParentNodeIndex) { - // This must be the drive root - } - else if (parentIndexes != null) { - ((FolderItem) parentIndexes.FileItem).AddItem(item, - ref parentIndexes.FileCollection, ref parentIndexes.FirstFile); - } - else { - // This must be the root - } - if (AsyncChecks(token)) - return; - } - } - - private void ReadMft(ScanningState state, NtfsReader ntfs, FileNodeIndexes[] fileItemsLookup, - List fileItems, CancellationToken token) - { - foreach (INtfsNode node in ntfs.EnumerateNodes(state.RootPath)) { - string fullPath = PathUtils.TrimSeparatorDotEnd(node.FullName); - bool isRoot = (node.NodeIndex == node.ParentNodeIndex); - if (!isRoot && SkipFile(state, Path.GetFileName(fullPath), fullPath)) - continue; - FileItemBase child; - bool reparsePoint = node.Attributes.HasFlag(FileAttributes.ReparsePoint); - if (isRoot) { - child = state.Root; - } - else if (node.Attributes.HasFlag(FileAttributes.Directory)) { - if (!state.IsDrive && state.RootPath == node.FullName.ToUpperInvariant()) { - child = state.Root; - } - else { - child = new FolderItem(new WindowsScanFileInfo(node)); - } - } - else { - ExtensionItem extension = Extensions.GetOrAddFromPath(node.Name); - FileItem file = new FileItem(new WindowsScanFileInfo(node), extension); - child = file; - if (!reparsePoint) - TotalScannedSize += child.Size; - } - FileNodeIndexes indexes = new FileNodeIndexes(child, node); - fileItemsLookup[node.NodeIndex] = indexes; - - if (!reparsePoint) - fileItems.Add(indexes); - - if (AsyncChecks(token)) - return; - } - } - - - /*private void ScanMtf(ScanningState state, CancellationToken token) { - Dictionary fileItems = new Dictionary(); - - DriveInfo driveInfo = new DriveInfo(Path.GetPathRoot(state.RootPath)); - using (NtfsReader ntfs = new NtfsReader(driveInfo, RetrieveMode.StandardInformations)) { - ReadMft(state, ntfs, fileItems, token); - } - - foreach (FileNodeIndexes indexes in fileItems.Values) { - FileItemBase item = indexes.FileItem; - if (indexes.NodeIndex == indexes.ParentNodeIndex) { - // This must be the drive root - } - else if (fileItems.TryGetValue(indexes.ParentNodeIndex, out var parentIndexes)) { - ((FolderItem) parentIndexes.FileItem).AddItem(item, - ref parentIndexes.FileCollection, ref parentIndexes.FirstFile); - } - else { - // This must be the root - } - if (AsyncChecks(token)) - return; - } - } - - private void ReadMft(ScanningState state, NtfsReader ntfs, Dictionary fileNodes, - CancellationToken token) { - foreach (INtfsNode node in ntfs.EnumerateNodes(state.RootPath)) { - string fullPath = PathUtils.TrimSeparatorDotEnd(node.FullName); - bool isRoot = (node.NodeIndex == node.ParentNodeIndex); - if (!isRoot && SkipFile(state, Path.GetFileName(fullPath), fullPath)) - continue; - FileItemBase child; - if (isRoot) { - child = state.Root; - } - else if (node.Attributes.HasFlag(FileAttributes.Directory)) { - if (!state.IsDrive && state.RootPath == node.FullName.ToUpperInvariant()) { - child = state.Root; - } - else { - child = new FolderItem(new ScanFileInfo(node)); - } - } - else { - ExtensionItem extension = Extensions.GetOrAddFromPath(node.Name); - FileItem file = new FileItem(new ScanFileInfo(node), extension); - child = file; - if (!node.Attributes.HasFlag(FileAttributes.ReparsePoint)) { - state.ScannedSize += child.Size; - TotalScannedSize += child.Size; - } - } - fileNodes[node.NodeIndex] = new FileNodeIndexes(child, node); - - if (AsyncChecks(token)) - return; - } - }*/ - } -} diff --git a/WinDirStat.Net.Windows/Services/WindowsScanningService.Native.cs b/WinDirStat.Net.Windows/Services/WindowsScanningService.Native.cs deleted file mode 100644 index 58949fa..0000000 --- a/WinDirStat.Net.Windows/Services/WindowsScanningService.Native.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Utils; -using WinDirStat.Net.Windows.Services; -using WinDirStat.Net.Windows.Services.Structures; -using static WinDirStat.Net.Windows.Native.Win32; - -namespace WinDirStat.Net.Windows.Services { - partial class WindowsScanningService { - private struct FolderState { - public FolderItem Folder; - public ScanningState State; - - public FolderState(ScanningState state) { - Folder = state.Root; - State = state; - } - - public FolderState(FolderItem folder, ScanningState state) { - State = state; - Folder = folder; - } - } - - private void ScanNative(CancellationToken token) { - Queue subdirs = new Queue(); - foreach (ScanningState state in scanningStates) - subdirs.Enqueue(new FolderState(state)); - do { - ReadNative(subdirs, token); - } while (subdirs.Any() && !AsyncChecks(token)); - } - - private void ReadNative(Queue subdirs, CancellationToken token) { - Win32FindData find = new Win32FindData(); - FolderState folderState = subdirs.Dequeue(); - ScanningState state = folderState.State; - FolderItem parent = folderState.Folder; - bool findResult; - string parentPath = parent.FullName; - string searchPattern = PathUtils.CombineNoChecks(parentPath, "*"); - if (!searchPattern.StartsWith(@"\\?\")) - searchPattern = @"\\?\" + searchPattern; - IntPtr hFind = FindFirstFileEx(searchPattern, - FindExInfoLevels.Basic, out find, - FindExSearchOps.NameMatch, IntPtr.Zero, - FindExFlags.LargeFetch); - if (hFind == InvalidHandle) - return; - - FolderItem fileCollection = null; - FileItem firstFile = null; - bool subdirsAdded = false; - try { - do { - string filePath = PathUtils.CombineNoChecks(parentPath, find.cFileName); - if (find.IsRelativeDirectory || SkipFile(state, find.cFileName, filePath)) { - // Skip these types of entries - findResult = FindNextFile(hFind, out find); - continue; - } - FileItemBase child; - if (find.IsDirectory) { - FolderItem folder = new FolderItem(new WindowsScanFileInfo(find, filePath)); - child = folder; - if (!find.IsSymbolicLink) { - subdirsAdded = true; - subdirs.Enqueue(new FolderState(folder, state)); - } - } - else { - ExtensionItem extension = Extensions.GetOrAddFromPath(filePath); - FileItem file = new FileItem(new WindowsScanFileInfo(find, filePath), extension); - child = file; - if (!find.IsSymbolicLink) - TotalScannedSize += child.Size; - } - parent.AddItem(child, ref fileCollection, ref firstFile); - - if (AsyncChecks(token)) - return; - - findResult = FindNextFile(hFind, out find); - } while (findResult); - - if (!subdirsAdded) - parent.Finish(); - //if (parent.IsWatched) - // parent.RaiseChanged(FileItemAction.ChildrenDone); - } - finally { - FindClose(hFind); - } - } - } -} diff --git a/WinDirStat.Net.Windows/Services/WindowsScanningService.Refresh.cs b/WinDirStat.Net.Windows/Services/WindowsScanningService.Refresh.cs deleted file mode 100644 index 3ce6e55..0000000 --- a/WinDirStat.Net.Windows/Services/WindowsScanningService.Refresh.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Windows.Services { - partial class WindowsScanningService { - - protected override void Refresh(RefreshFiles[] refreshFiles, CancellationToken token) { - CanDisplayProgress = RootItem.Type == FileItemType.Volume || - (RootItem.Type == FileItemType.Computer && - !RootItem.Children.Any(f => f.Type != FileItemType.Volume && - f.Type != FileItemType.FreeSpace && f.Type != FileItemType.Unknown)); - if (CanDisplayProgress) { - if (RootItem.Type == FileItemType.Volume) { - try { - if (RootItem.CheckExists()) { - DriveInfo driveInfo = new DriveInfo(RootItem.RootPath); - TotalSize = driveInfo.TotalSize; - TotalFreeSpace = driveInfo.TotalFreeSpace; - } - else { - CanDisplayProgress = false; - } - } - catch { - CanDisplayProgress = false; - } - } - else if (RootItem.Type == FileItemType.Computer) { - bool anySuccess = false; - foreach (FileItemBase child in RootItem.Children) { - if (child is RootItem root) { - try { - if (root.CheckExists()) { - DriveInfo driveInfo = new DriveInfo(root.RootPath); - TotalSize += driveInfo.TotalSize; - TotalFreeSpace += driveInfo.TotalFreeSpace; - anySuccess = true; - continue; - } - } - catch { } - TotalSize += root.CachedTotalSize; - TotalFreeSpace += root.CachedFreeSpace; - } - } - if (!anySuccess) - CanDisplayProgress = false; - } - } - // Reset the progress if applicable - TotalScannedSize = Extensions.TotalSize - refreshFiles.Sum(rf => rf.Files.Sum(f => f.Size)); - ProgressState = ScanProgressState.Started; - - foreach (RefreshFiles refresh in refreshFiles) { - FolderItem parent = refresh.Parent; - FolderItem fileCollection = parent.GetFileCollection(); - - Queue subdirs = new Queue(); - - foreach (FileItemBase refreshChild in refresh.Files) { - if (!refreshChild.Refresh()) { - string fullName = refreshChild.FullName; - parent.RemoveItem(refreshChild, ref fileCollection); - - // See if the type changed (file <-> directory) - FileItemBase child = null; - if (refreshChild.Type == FileItemType.File) { - DirectoryInfo info = new DirectoryInfo(fullName); - if (info.Exists) { - FolderItem folder = new FolderItem(info); - child = folder; - // Folder exists enqueue it for scanning - if (!info.Attributes.HasFlag(FileAttributes.ReparsePoint)) - subdirs.Enqueue(folder); - } - } - else if (refreshChild.Type == FileItemType.Directory) { - FileInfo info = new FileInfo(fullName); - if (info.Exists) { - ExtensionItem extension = Extensions.GetOrAddFromPath(fullName); - FileItem file = new FileItem(info, extension); - child = file; - // File exists, add it to the scanned size - if (!info.Attributes.HasFlag(FileAttributes.ReparsePoint)) - TotalScannedSize += child.Size; - } - } - if (child != null) { - FileItem firstFile = parent.GetFirstFile(); - parent.AddItem(child, ref fileCollection, ref firstFile); - } - } - else if (!refreshChild.IsReparsePointFile) { - // Folder exists enqueue it for scanning - if (refreshChild is FolderItem folder) - subdirs.Enqueue(folder); - // File exists, add it to the scanned size - else - TotalScannedSize += refreshChild.Size; - } - - if (AsyncChecks(token)) - return; - } - - if (subdirs.Count > 0) - RefreshFolders(subdirs, token); - - if (AsyncChecks(token)) - return; - } - } - - private void RefreshFolders(Queue subdirs, CancellationToken token) { - scanningStates = new List(); - foreach (FolderItem subdir in subdirs) - scanningStates.Add(CreateState(subdir)); - - // Master file tables cannot be scanned inline, so scan them one at a time first - for (int i = 0; i < scanningStates.Count; i++) { - ScanningState state = scanningStates[i]; - try { - ScanMtf(state, token); - scanningStates.RemoveAt(i--); - } - catch (Exception) { - // We don't have permission, are not elevated, or path is not an NTFS drive - // We'll scan this path normally instead - } - } - - if (scanningStates.Count > 0) - ScanNative(token); - - scanningStates = null; - } - } -} diff --git a/WinDirStat.Net.Windows/Services/WindowsScanningService.cs b/WinDirStat.Net.Windows/Services/WindowsScanningService.cs deleted file mode 100644 index 6cb842d..0000000 --- a/WinDirStat.Net.Windows/Services/WindowsScanningService.cs +++ /dev/null @@ -1,220 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using GalaSoft.MvvmLight; -using WinDirStat.Net.Model.Extensions; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Services; -using WinDirStat.Net.Utils; -using WinDirStat.Net.Windows.Native; -using System.Runtime.InteropServices; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Windows.Services { - public partial class WindowsScanningService : ScanningService { - - #region Private Classes - - private class ScanningState { - public long TotalSize; - public long FreeSpace; - public string RootPath; - public bool IsDrive; - public string RecycleBinPath; - public FolderItem Root; - } - - #endregion - - #region Fields - - private List scanningStates; - - #endregion - - #region Constructors - - public WindowsScanningService(SettingsService settings, - IOSService os, - IUIService ui) - : base(settings, - os, - ui) - { - } - - #endregion - - public long GetCompressedFileSize(string filePath) { - uint low = Win32.GetCompressedFileSize(filePath, out int high); - if (low == Win32.InvalidFileSize) { - int error = Marshal.GetLastWin32Error(); - if (error != 0) - throw new Win32Exception(error); - } - return ((long) high << 32) | low; - } - - /// Runs the actual scan on any number of root paths. - /// - /// The root paths to scan. - /// The token for cleanly cancelling the operations. - protected override void Scan(string[] rootPaths, CancellationToken token) { - // See if we can perform a single scan - if (rootPaths.Length == 1) { - Scan(rootPaths[0], token); - return; - } - - scanningStates = rootPaths.Select(p => CreateState(p, false)).ToList(); - CanDisplayProgress = !scanningStates.Any(s => !s.IsDrive); - - TotalSize = scanningStates.Sum(s => s.TotalSize); - TotalFreeSpace = scanningStates.Sum(s => s.FreeSpace); - - // Computer Root - RootItem computerRoot = new RootItem(this); - foreach (ScanningState state in scanningStates) { - computerRoot.AddItem(state.Root); - } - - RootItem = computerRoot; - ProgressState = ScanProgressState.Started; - - // Master file tables cannot be scanned inline, so scan them one at a time first - for (int i = 0; i < scanningStates.Count; i++) { - ScanningState state = scanningStates[i]; - try { - ScanMtf(state, token); - scanningStates.RemoveAt(i--); - } - catch (Exception) { - // We don't have permission, are not elevated, or path is not an NTFS drive - // We'll scan this path normally instead - } - } - - // Are there any leftover states to work on? - if (scanningStates.Any()) - ScanNative(token); - - FinishScan(token); - } - - /// Runs the actual scan on a single root path. - /// - /// The single root path to scan. - /// The token for cleanly cancelling the operations. - private void Scan(string rootPath, CancellationToken token) { - ScanningState state = CreateState(rootPath, true); - scanningStates = new List() { state }; - CanDisplayProgress = scanningStates[0].IsDrive; - - TotalSize = state.TotalSize; - TotalFreeSpace = state.FreeSpace; - - RootItem = (RootItem) state.Root; - ProgressState = ScanProgressState.Started; - - try { - ScanMtf(state, token); - } - catch (Exception) { - // We don't have permission, are not elevated, or path is not an NTFS drive - // We'll scan this path normally instead - ScanNative(token); - } - FinishScan(token); - } - - /// Performs the final opreations after a scan. - /// - private void FinishScan(CancellationToken token) { - scanningStates = null; - if (!token.IsCancellationRequested) { - RootItem.Finish(); - } - } - - /// Creates a for the specified root path. - /// - /// The path to create a state for. - /// - /// True if the there is only one state. - /// This means this is the absolute root item instead of Computer. - /// - /// The newly created and initialized . - private ScanningState CreateState(string rootPath, bool single) { - rootPath = Path.GetFullPath(rootPath); - string pathRoot = Path.GetPathRoot(rootPath); - ScanningState state = new ScanningState { - IsDrive = PathUtils.IsSamePath(pathRoot, rootPath), - RecycleBinPath = Path.Combine(pathRoot, "$Recycle.Bin"), - Root = new RootItem(this, new DirectoryInfo(rootPath), single), - RootPath = rootPath.ToUpperInvariant(), - }; - if (state.IsDrive) { - Win32.GetDiskFreeSpaceEx(rootPath, out _, out ulong totalSize, out ulong freeSpace); - state.TotalSize = (long) totalSize; - state.FreeSpace = (long) freeSpace; - } - return state; - } - - /// - /// Creates a for the specified . - /// - /// - /// The folder to create the state for. - /// The newly created and initialized . - private ScanningState CreateState(FolderItem folder) { - string rootPath = folder.FullName; - string pathRoot = Path.GetPathRoot(rootPath); - ScanningState state = new ScanningState { - IsDrive = PathUtils.IsSamePath(pathRoot, rootPath), - RecycleBinPath = Path.Combine(pathRoot, "$Recycle.Bin"), - Root = folder, - RootPath = rootPath.ToUpperInvariant(), - }; - if (state.IsDrive) { - Win32.GetDiskFreeSpaceEx(rootPath, out _, out ulong totalSize, out ulong freeSpace); - state.TotalSize = (long) totalSize; - state.FreeSpace = (long) freeSpace; - } - return state; - } - - /// Checks if we should ignore this file in the scan. - /// - /// The scan state for this file. - /// The name of the file. - /// The full path of the file. - /// True if the file should be skipped. - private bool SkipFile(ScanningState state, string name, string path) { - if (name.Length == 0) - Console.WriteLine("WHAT"); - // We still want to see all those delicious files that were thrown away - if (name[0] == '$' && !path.StartsWith(state.RecycleBinPath)) - return true; - - // Certified spam - //if (string.Compare(name, "desktop.ini", true) == 0) - // return true; - - return false; - } - - protected override void FinishedCleanup() { - scanningStates = null; - } - - protected override void ClosedCleanup() { - } - } -} diff --git a/WinDirStat.Net.Windows/WinDirStat.Net.Windows.csproj b/WinDirStat.Net.Windows/WinDirStat.Net.Windows.csproj deleted file mode 100644 index f66832f..0000000 --- a/WinDirStat.Net.Windows/WinDirStat.Net.Windows.csproj +++ /dev/null @@ -1,49 +0,0 @@ - - - - net462 - latest - true - Debug;Release - - - - - - - - - - - - - - Native\Win32.cs - - - Native\Win32.cs - - - Native\Win32.cs - - - Native\Win32.cs - - - Native\Win32.cs - - - Native\Win32.cs - - - Native\Win32.cs - - - Native\Win32.cs - - - Native\Win32.cs - - - - diff --git a/WinDirStat.Net.Wpf/App.config b/WinDirStat.Net.Wpf/App.config deleted file mode 100644 index b50c74f..0000000 --- a/WinDirStat.Net.Wpf/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/WinDirStat.Net.Wpf/App.ico b/WinDirStat.Net.Wpf/App.ico deleted file mode 100644 index 4e4be1aed7c019b0cd8c122721fef50c01a72057..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 321053 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 X}0Q$S>d)=19mZ#!hrvsISXX)`@ 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 tLDNKjY%@SxW%$Np^qR^&ODmP#2U$dxg - - - - - - - - - \ No newline at end of file diff --git a/WinDirStat.Net.Wpf/App.xaml.cs b/WinDirStat.Net.Wpf/App.xaml.cs deleted file mode 100644 index db4a889..0000000 --- a/WinDirStat.Net.Wpf/App.xaml.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; - -namespace WinDirStat.Net.Wpf { - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application { - } -} diff --git a/WinDirStat.Net.Wpf/Controls/CommandButton.cs b/WinDirStat.Net.Wpf/Controls/CommandButton.cs deleted file mode 100644 index 2da9ec1..0000000 --- a/WinDirStat.Net.Wpf/Controls/CommandButton.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using WinDirStat.Net.Model; -using WinDirStat.Net.Utils; -using WinDirStat.Net.ViewModel; -using WinDirStat.Net.Wpf.Services.Structures; -using WinDirStat.Net.Wpf.Utils; -using WinDirStat.Net.Wpf.ViewModel; - -namespace WinDirStat.Net.Wpf.Controls { - public class CommandButton : ImageButton { - private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - CommandButton button = (CommandButton) d; - - if (e.OldValue is IWpfRelayCommand oldUICommand) - oldUICommand.PropertyChanged -= button.OnCommandPropertyChanged; - if (e.NewValue is IWpfRelayCommand newUICommand) - newUICommand.PropertyChanged += button.OnCommandPropertyChanged; - - d.CoerceValue(SourceProperty); - //d.CoerceValue(ContentProperty); - d.CoerceValue(ToolTipProperty); - } - - private void OnCommandPropertyChanged(object sender, PropertyChangedEventArgs e) { - CoerceValue(SourceProperty); - //CoerceValue(ContentProperty); - CoerceValue(ToolTipProperty); - } - - // Set the header to the command text if no header has been explicitly specified - /*private static object CoerceContent(DependencyObject d, object value) { - CommandButton button = (CommandButton) d; - RelayUICommand uiCommand; - - // If no header has been set, use the command's text - if (button.IsValueUnsetAndNull(ContentProperty) && button.Command is RelayUICommand uiCommand) { - value = uiCommand.Text; - } - - return value; - }*/ - - - // Set the icon to the command text if no icon has been explicitly specified - private static object CoerceSource(DependencyObject d, object value) { - CommandButton button = (CommandButton) d; - - // If no icon has been set, use the command's icon - if (button.IsValueUnsetAndNull(SourceProperty, value) && button.Command is IWpfRelayCommand uiCommand) { - value = uiCommand.Icon; - } - return value; - } - - // Gets the input gesture text from the command text if it hasn't been explicitly specified - private static object CoerceToolTip(DependencyObject d, object value) { - CommandButton button = (CommandButton) d; - - if (button.IsValueUnsetAndNull(ToolTipProperty, value) && button.Command is IWpfRelayCommand uiCommand) { - - string tooltip = ""; - if (!string.IsNullOrEmpty(uiCommand.Text)) { - tooltip += uiCommand.Text; - // Remove ellipses - if (tooltip.EndsWith("...")) - tooltip = tooltip.Substring(0, tooltip.Length - 3); - } - if (uiCommand.InputGesture != null) { - if (!string.IsNullOrEmpty(tooltip)) - tooltip += " "; - tooltip += $"({uiCommand.InputGesture.GetDisplayStringForCulture(CultureInfo.CurrentCulture)})"; - } - return tooltip; - } - - return value; - } - - static CommandButton() { - CommandProperty.AddOwner(typeof(CommandButton), - new FrameworkPropertyMetadata(OnCommandChanged)); - //ContentProperty.AddOwner(typeof(CommandButton), - // new FrameworkPropertyMetadata(null, CoerceContent)); - SourceProperty.AddOwner(typeof(CommandButton), - new FrameworkPropertyMetadata(null, CoerceSource)); - ToolTipProperty.AddOwner(typeof(CommandButton), - new FrameworkPropertyMetadata(null, CoerceToolTip)); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/CommandMenuItem.cs b/WinDirStat.Net.Wpf/Controls/CommandMenuItem.cs deleted file mode 100644 index 3fee95b..0000000 --- a/WinDirStat.Net.Wpf/Controls/CommandMenuItem.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using WinDirStat.Net.Model; -using WinDirStat.Net.Utils; -using WinDirStat.Net.ViewModel; -using WinDirStat.Net.Wpf.Services.Structures; -using WinDirStat.Net.Wpf.Utils; -using WinDirStat.Net.Wpf.ViewModel; - -namespace WinDirStat.Net.Wpf.Controls { - public class CommandMenuItem : ImageMenuItem { - private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - CommandMenuItem menuItem = (CommandMenuItem) d; - - if (e.OldValue is IWpfRelayCommand oldUICommand) - oldUICommand.PropertyChanged -= menuItem.OnCommandPropertyChanged; - if (e.NewValue is IWpfRelayCommand newUICommand) - newUICommand.PropertyChanged += menuItem.OnCommandPropertyChanged; - - d.CoerceValue(SourceProperty); - d.CoerceValue(HeaderProperty); - d.CoerceValue(InputGestureTextProperty); - } - - private void OnCommandPropertyChanged(object sender, PropertyChangedEventArgs e) { - CoerceValue(SourceProperty); - CoerceValue(HeaderProperty); - CoerceValue(InputGestureTextProperty); - } - - // Set the header to the command text if no header has been explicitly specified - private static object CoerceHeader(DependencyObject d, object value) { - CommandMenuItem menuItem = (CommandMenuItem) d; - IWpfRelayCommand uiCommand; - - // If no header has been set, use the command's text - bool unset = menuItem.IsValueUnsetAndNull(HeaderProperty, value); - if (menuItem.IsValueUnsetAndNull(HeaderProperty, value)) { - uiCommand = menuItem.Command as IWpfRelayCommand; - if (uiCommand != null) { - value = uiCommand.Text; - } - return value; - } - - // If the header had been set to a UICommand by the ItemsControl, replace it with the command's text - uiCommand = value as IWpfRelayCommand; - - if (uiCommand != null) { - // The header is equal to the command. - // If this MenuItem was generated for the command, then go ahead and overwrite the header - // since the generator automatically set the header. - ItemsControl parent = ItemsControl.ItemsControlFromItemContainer(menuItem); - if (parent != null) { - object originalItem = parent.ItemContainerGenerator.ItemFromContainer(menuItem); - if (originalItem == value) - return uiCommand.Text; - } - } - - return value; - } - - - // Set the icon to the command text if no icon has been explicitly specified - private static object CoerceSource(DependencyObject d, object value) { - CommandMenuItem menuItem = (CommandMenuItem) d; - - // If no icon has been set, use the command's text - if (menuItem.IsValueUnsetAndNull(SourceProperty, value) && - menuItem.Command is IWpfRelayCommand uiCommand) - { - value = uiCommand.Icon; - } - - return value; - } - - // Gets the input gesture text from the command text if it hasn't been explicitly specified - private static object CoerceInputGestureText(DependencyObject d, object value) { - MenuItem menuItem = (MenuItem) d; - - if (menuItem.IsValueUnsetAndNull(InputGestureTextProperty, value) && - menuItem.Command is IWpfRelayCommand uiCommand && uiCommand.InputGesture != null) - { - return uiCommand.InputGesture.GetDisplayStringForCulture(CultureInfo.CurrentCulture); - } - - return value; - } - - static CommandMenuItem() { - CommandProperty.AddOwner(typeof(CommandMenuItem), - new FrameworkPropertyMetadata(OnCommandChanged)); - HeaderProperty.AddOwner(typeof(CommandMenuItem), - new FrameworkPropertyMetadata(null, CoerceHeader)); - SourceProperty.AddOwner(typeof(CommandMenuItem), - new FrameworkPropertyMetadata(null, CoerceSource)); - InputGestureTextProperty.AddOwner(typeof(CommandMenuItem), - new FrameworkPropertyMetadata(null, CoerceInputGestureText)); - } - - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/EditTextBox.cs b/WinDirStat.Net.Wpf/Controls/FileList/EditTextBox.cs deleted file mode 100644 index 4a174a4..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/EditTextBox.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Data; -using System.Windows; -using WinDirStat.Net.ViewModel.Files; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - class EditTextBox : TextBox { - static EditTextBox() { - DefaultStyleKeyProperty.OverrideMetadata(typeof(EditTextBox), - new FrameworkPropertyMetadata(typeof(EditTextBox))); - } - - public EditTextBox() { - Loaded += delegate { Init(); }; - } - - public FileTreeViewItem Item { get; set; } - - public FileItemViewModel Node { - get { return Item.Node; } - } - - void Init() { - Text = Node.LoadEditText(); - Focus(); - SelectAll(); - } - - protected override void OnKeyDown(KeyEventArgs e) { - if (e.Key == Key.Enter) { - Commit(); - } - else if (e.Key == Key.Escape) { - Node.IsEditing = false; - } - } - - protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) { - if (Node.IsEditing) { - Commit(); - } - } - - bool commiting; - - void Commit() { - if (!commiting) { - commiting = true; - - Node.IsEditing = false; - if (!Node.SaveEditText(Text)) { - Item.Focus(); - } - //Node.RaisePropertyChanged("Text"); - - //if (Node.SaveEditText(Text)) { - // Node.IsEditing = false; - // Node.RaisePropertyChanged("Text"); - //} - //else { - // Init(); - //} - - commiting = false; - } - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/ExtensionMethods.cs b/WinDirStat.Net.Wpf/Controls/FileList/ExtensionMethods.cs deleted file mode 100644 index 3b98cbf..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/ExtensionMethods.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Media; -using System.Windows; -using System.Collections; -using System.Windows.Input; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - public static class ExtensionMethods { - public static T FindAncestor(this DependencyObject d) where T : class { - return AncestorsAndSelf(d).OfType().FirstOrDefault(); - } - - public static IEnumerable AncestorsAndSelf(this DependencyObject d) { - while (d != null) { - yield return d; - d = VisualTreeHelper.GetParent(d); - } - } - - public static void AddOnce(this IList list, object item) { - if (!list.Contains(item)) { - list.Add(item); - } - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/FileGridView.cs b/WinDirStat.Net.Wpf/Controls/FileList/FileGridView.cs deleted file mode 100644 index 1f37727..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/FileGridView.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Controls; -using System.Windows; -using WinDirStat.Net.Wpf.Controls.SortList; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - public class FileGridView : SortView { - static FileGridView() { - ItemContainerStyleKey = - new ComponentResourceKey(typeof(FileTreeView), "GridViewItemContainerStyleKey"); - } - - public static ResourceKey ItemContainerStyleKey { get; private set; } - - protected override object ItemContainerDefaultStyleKey { - get { - return ItemContainerStyleKey; - } - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/FileTreeNodeView.cs b/WinDirStat.Net.Wpf/Controls/FileList/FileTreeNodeView.cs deleted file mode 100644 index df54396..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/FileTreeNodeView.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Windows.Controls; -using System.Windows; -using System.Windows.Controls.Primitives; -using System.Windows.Media; -using System.Windows.Input; -using System.ComponentModel; -using System.Collections.Specialized; -using WinDirStat.Net.ViewModel.Files; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - public class FileTreeNodeView : Control { - static FileTreeNodeView() { - DefaultStyleKeyProperty.OverrideMetadata(typeof(FileTreeNodeView), - new FrameworkPropertyMetadata(typeof(FileTreeNodeView))); - } - - public static readonly DependencyProperty TextBackgroundProperty = - DependencyProperty.Register("TextBackground", typeof(Brush), typeof(FileTreeNodeView)); - - public Brush TextBackground { - get => (Brush) GetValue(TextBackgroundProperty); - set => SetValue(TextBackgroundProperty, value); - } - - public FileItemViewModel Node { - get { return DataContext as FileItemViewModel; } - } - - public FileTreeViewItem ParentItem { get; private set; } - - public static readonly DependencyProperty CellEditorProperty = - DependencyProperty.Register("CellEditor", typeof(Control), typeof(FileTreeNodeView), - new FrameworkPropertyMetadata()); - - public Control CellEditor { - get => (Control) GetValue(CellEditorProperty); - set => SetValue(CellEditorProperty, value); - } - - public FileTreeView ParentTreeView { - get { return ParentItem.ParentTreeView; } - } - - internal LinesRenderer LinesRenderer { get; private set; } - - public override void OnApplyTemplate() { - base.OnApplyTemplate(); - LinesRenderer = Template.FindName("linesRenderer", this) as LinesRenderer; - UpdateTemplate(); - } - - protected override void OnVisualParentChanged(DependencyObject oldParent) { - base.OnVisualParentChanged(oldParent); - ParentItem = this.FindAncestor(); - ParentItem.NodeView = this; - } - - protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { - base.OnPropertyChanged(e); - if (e.Property == DataContextProperty) { - UpdateDataContext(e.OldValue as FileItemViewModel, e.NewValue as FileItemViewModel); - } - } - - void UpdateDataContext(FileItemViewModel oldNode, FileItemViewModel newNode) { - if (newNode != null) { - newNode.PropertyChanged += Node_PropertyChanged; - if (Template != null) { - UpdateTemplate(); - } - } - if (oldNode != null) { - oldNode.PropertyChanged -= Node_PropertyChanged; - } - } - - void Node_PropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(FileItemViewModel.IsEditing)) { - OnIsEditingChanged(); - } - else if (e.PropertyName == nameof(FileItemViewModel.IsLast)) { - if (ParentTreeView.ShowLines) { - foreach (var child in Node.VisibleDescendantsAndSelf()) { - var container = ParentTreeView.ItemContainerGenerator.ContainerFromItem(child) as FileTreeViewItem; - if (container != null) { - container.NodeView.LinesRenderer.InvalidateVisual(); - } - } - } - } - else if (e.PropertyName == nameof(FileItemViewModel.IsExpanded)) { - if (Node.IsExpanded) - ParentTreeView.HandleExpanding(Node); - } - } - - void OnIsEditingChanged() { - var textEditorContainer = Template.FindName("textEditorContainer", this) as Border; - if (Node.IsEditing) { - if (CellEditor == null) - textEditorContainer.Child = new EditTextBox() { Item = ParentItem }; - else - textEditorContainer.Child = CellEditor; - } - else { - textEditorContainer.Child = null; - } - } - - void UpdateTemplate() { - var spacer = Template.FindName("spacer", this) as FrameworkElement; - spacer.Width = CalculateIndent(); - - var expander = Template.FindName("expander", this) as ToggleButton; - if (ParentTreeView.Root == Node && !ParentTreeView.ShowRootExpander) { - expander.Visibility = Visibility.Collapsed; - } - else { - expander.ClearValue(VisibilityProperty); - } - } - - internal double CalculateIndent() { - int result = 18 * Node.Level; - if (ParentTreeView.ShowRoot) { - if (!ParentTreeView.ShowRootExpander) { - if (ParentTreeView.Root != Node) { - result -= 15; - } - } - } - else { - result -= 19; - } - if (result < 0) { - Debug.WriteLine("Negative indent level detected for node " + Node); - result = 0; - } - return result; - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/FileTreeView.cs b/WinDirStat.Net.Wpf/Controls/FileList/FileTreeView.cs deleted file mode 100644 index c1a7cab..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/FileTreeView.cs +++ /dev/null @@ -1,711 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Threading; -using WinDirStat.Net.Wpf.Controls.SortList; -using WinDirStat.Net.Utils; -using WinDirStat.Net.ViewModel.Files; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - public class FileTreeView : SortListView { - static FileTreeView() { - DefaultStyleKeyProperty.OverrideMetadata(typeof(FileTreeView), - new FrameworkPropertyMetadata(typeof(FileTreeView))); - - SelectionModeProperty.OverrideMetadata(typeof(FileTreeView), - new FrameworkPropertyMetadata(SelectionMode.Extended)); - - AlternationCountProperty.OverrideMetadata(typeof(FileTreeView), - new FrameworkPropertyMetadata(2)); - - DefaultItemContainerStyleKey = - new ComponentResourceKey(typeof(FileTreeView), "DefaultItemContainerStyleKey"); - - VirtualizingStackPanel.VirtualizationModeProperty.OverrideMetadata(typeof(FileTreeView), - new FrameworkPropertyMetadata(VirtualizationMode.Recycling)); - - RegisterCommands(); - } - - public static readonly RoutedEvent ActivateEvent = - EventManager.RegisterRoutedEvent("Activate", RoutingStrategy.Bubble, - typeof(RoutedEventHandler), typeof(FileTreeView)); - - public event RoutedEventHandler Activate { - add => AddHandler(ActivateEvent, value); - remove => RemoveHandler(ActivateEvent, value); - } - - public static ResourceKey DefaultItemContainerStyleKey { get; private set; } - - public FileTreeView() { - SetResourceReference(ItemContainerStyleProperty, DefaultItemContainerStyleKey); - } - - public static readonly DependencyProperty RootProperty = - DependencyProperty.Register("Root", typeof(FileItemViewModel), typeof(FileTreeView)); - - public FileItemViewModel Root { - get => (FileItemViewModel) GetValue(RootProperty); - set => SetValue(RootProperty, value); - } - - public static readonly DependencyProperty ShowRootProperty = - DependencyProperty.Register("ShowRoot", typeof(bool), typeof(FileTreeView), - new FrameworkPropertyMetadata(true)); - - public bool ShowRoot { - get => (bool) GetValue(ShowRootProperty); - set => SetValue(ShowRootProperty, value); - } - - public static readonly DependencyProperty ShowRootExpanderProperty = - DependencyProperty.Register("ShowRootExpander", typeof(bool), typeof(FileTreeView), - new FrameworkPropertyMetadata(false)); - - public bool ShowRootExpander { - get => (bool) GetValue(ShowRootExpanderProperty); - set => SetValue(ShowRootExpanderProperty, value); - } - - public static readonly DependencyProperty AllowDropOrderProperty = - DependencyProperty.Register("AllowDropOrder", typeof(bool), typeof(FileTreeView)); - - public bool AllowDropOrder { - get => (bool) GetValue(AllowDropOrderProperty); - set => SetValue(AllowDropOrderProperty, value); - } - - public static readonly DependencyProperty ShowLinesProperty = - DependencyProperty.Register("ShowLines", typeof(bool), typeof(FileTreeView), - new FrameworkPropertyMetadata(true)); - - public bool ShowLines { - get => (bool) GetValue(ShowLinesProperty); - set => SetValue(ShowLinesProperty, value); - } - - public static bool GetShowAlternation(DependencyObject obj) { - return (bool) obj.GetValue(ShowAlternationProperty); - } - - public static void SetShowAlternation(DependencyObject obj, bool value) { - obj.SetValue(ShowAlternationProperty, value); - } - - public static readonly DependencyProperty ShowAlternationProperty = - DependencyProperty.RegisterAttached("ShowAlternation", typeof(bool), typeof(FileTreeView), - new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits)); - - protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { - base.OnPropertyChanged(e); - if (e.Property == RootProperty || - e.Property == ShowRootProperty || - e.Property == ShowRootExpanderProperty) { - Reload(); - } - } - - FileTreeFlattener flattener; - - void Reload() { - if (flattener != null) { - flattener.Stop(); - flattener = null; - } - if (Root != null) { - if (!(ShowRoot && ShowRootExpander)) { - Root.IsExpanded = true; - } - flattener = new FileTreeFlattener(Root, ShowRoot); - flattener.CollectionChanged += Flattener_CollectionChanged; - this.ItemsSource = flattener; - } - else { - this.ItemsSource = null; - } - } - - void Flattener_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - // Deselect nodes that are being hidden, if any remain in the tree - if (e.Action == NotifyCollectionChangedAction.Remove && Items.Count > 0) { - List selectedOldItems = null; - foreach (FileItemViewModel node in e.OldItems) { - if (node.IsSelected) { - if (selectedOldItems == null) - selectedOldItems = new List(); - selectedOldItems.Add(node); - } - } - if (selectedOldItems != null) { - var list = SelectedItems.Cast().Except(selectedOldItems).ToList(); - SetSelectedItems(list); - if (SelectedItem == null && this.IsKeyboardFocusWithin) { - // if we removed all selected nodes, then move the focus to the node - // preceding the first of the old selected nodes - SelectedIndex = Math.Max(0, e.OldStartingIndex - 1); - if (SelectedIndex >= 0) - FocusNode((FileItemViewModel) SelectedItem); - } - } - } - } - - protected override DependencyObject GetContainerForItemOverride() { - return new FileTreeViewItem(); - } - - protected override bool IsItemItsOwnContainerOverride(object item) { - return item is FileTreeViewItem; - } - - protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { - base.PrepareContainerForItemOverride(element, item); - FileTreeViewItem container = element as FileTreeViewItem; - container.ParentTreeView = this; - // Make sure that the line renderer takes into account the new bound data - if (container.NodeView != null) { - container.NodeView.LinesRenderer.InvalidateVisual(); - } - } - - bool doNotScrollOnExpanding; - - /// - /// Handles the node expanding event in the tree view. - /// This method gets called only if the node is in the visible region (a SharpTreeNodeView exists). - /// - internal void HandleExpanding(FileItemViewModel node) { - if (doNotScrollOnExpanding) - return; - /*FileNode lastVisibleChild = node; - while (true) { - FileNode tmp = lastVisibleChild.Children.LastOrDefault(c => c.IsVisible); - if (tmp != null) { - lastVisibleChild = tmp; - } - else { - break; - } - } - if (lastVisibleChild != node) { - // Make the the expanded children are visible; but don't scroll down - // to much (keep node itself visible) - base.ScrollIntoView(lastVisibleChild); - // For some reason, this only works properly when delaying it... - Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action( - delegate { - base.ScrollIntoView(node); - })); - }*/ - } - - protected override void OnKeyDown(KeyEventArgs e) { - FileTreeViewItem container = e.OriginalSource as FileTreeViewItem; - switch (e.Key) { - case Key.Left: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { - if (container.Node.IsExpanded) { - container.Node.IsExpanded = false; - } - else if (container.Node.Parent != null) { - this.FocusNode(container.Node.Parent); - } - e.Handled = true; - } - break; - case Key.Right: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { - if (!container.Node.IsExpanded && container.Node.ShowExpander) { - container.Node.IsExpanded = true; - } - else if (container.Node.Children.Count > 0) { - // jump to first child: - container.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down)); - } - e.Handled = true; - } - break; - case Key.Return: - if (container != null && Keyboard.Modifiers == ModifierKeys.None && this.SelectedItems.Count == 1 && this.SelectedItem == container.Node) { - e.Handled = true; - container.Node.ActivateItem(); - } - break; - case Key.Space: - if (container != null && Keyboard.Modifiers == ModifierKeys.None && this.SelectedItems.Count == 1 && this.SelectedItem == container.Node) { - e.Handled = true; - /*if (container.Node.IsCheckable) { - if (container.Node.IsChecked == null) // If partially selected, we want to select everything - container.Node.IsChecked = true; - else - container.Node.IsChecked = !container.Node.IsChecked; - } - else {*/ - container.Node.ActivateItem(); - //} - } - break; - case Key.Add: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { - if (container.Node.ShowExpander) - container.Node.IsExpanded = true; - e.Handled = true; - } - break; - case Key.Subtract: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { - container.Node.IsExpanded = false; - e.Handled = true; - } - break; - case Key.Multiply: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { - if (container.Node.ShowExpander) { - container.Node.IsExpanded = true; - ExpandRecursively(container.Node); - } - e.Handled = true; - } - break; - case Key.Divide: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { - if (container.Node.Parent != null) { - FocusNode(container.Node.Parent); - } - e.Handled = true; - } - break; - } - if (!e.Handled) - base.OnKeyDown(e); - } - - void ExpandRecursively(FileItemViewModel node) { - if (node.CanExpandRecursively) { - node.IsExpanded = true; - foreach (FileItemViewModel child in node.Children) { - ExpandRecursively(child); - } - } - } - - /// - /// Scrolls the specified node in view and sets keyboard focus on it. - /// - public void FocusNode(FileItemViewModel node) { - if (node == null) - throw new ArgumentNullException("node"); - ScrollIntoView(node); - // WPF's ScrollIntoView() uses the same if/dispatcher construct, so we call OnFocusItem() after the item was brought into view. - if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) { - OnFocusItem(node); - } - else { - this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(this.OnFocusItem), node); - } - } - - public void ScrollIntoView(FileItemViewModel node) { - if (node == null) - throw new ArgumentNullException("node"); - doNotScrollOnExpanding = true; - foreach (FileItemViewModel ancestor in node.Ancestors()) - ancestor.IsExpanded = true; - doNotScrollOnExpanding = false; - base.ScrollIntoView(node); - } - - object OnFocusItem(object item) { - if (ItemContainerGenerator.ContainerFromItem(item) is FrameworkElement element) { - element.Focus(); - Keyboard.Focus(element); - } - return null; - } - - #region Track selection - - protected override void OnSelectionChanged(SelectionChangedEventArgs e) { - foreach (FileItemViewModel node in e.RemovedItems) { - node.IsSelected = false; - } - foreach (FileItemViewModel node in e.AddedItems) { - node.IsSelected = true; - } - base.OnSelectionChanged(e); - } - - #endregion - - #region Drag and Drop (Disabled) - /*protected override void OnDragEnter(DragEventArgs e) { - OnDragOver(e); - } - - protected override void OnDragOver(DragEventArgs e) { - e.Effects = DragDropEffects.None; - - if (Root != null && !ShowRoot) { - e.Handled = true; - e.Effects = Root.GetDropEffect(e, Root.Children.Count); - } - } - - protected override void OnDrop(DragEventArgs e) { - e.Effects = DragDropEffects.None; - - if (Root != null && !ShowRoot) { - e.Handled = true; - e.Effects = Root.GetDropEffect(e, Root.Children.Count); - if (e.Effects != DragDropEffects.None) - Root.InternalDrop(e, Root.Children.Count); - } - } - - internal void HandleDragEnter(WinDirTreeViewItem item, DragEventArgs e) { - HandleDragOver(item, e); - } - - internal void HandleDragOver(WinDirTreeViewItem item, DragEventArgs e) { - HidePreview(); - e.Effects = DragDropEffects.None; - - var target = GetDropTarget(item, e); - if (target != null) { - e.Handled = true; - e.Effects = target.Effect; - ShowPreview(target.Item, target.Place); - } - } - - internal void HandleDrop(WinDirTreeViewItem item, DragEventArgs e) { - try { - HidePreview(); - - var target = GetDropTarget(item, e); - if (target != null) { - e.Handled = true; - e.Effects = target.Effect; - target.Node.InternalDrop(e, target.Index); - } - } - catch (Exception ex) { - Debug.WriteLine(ex.ToString()); - throw; - } - } - - internal void HandleDragLeave(WinDirTreeViewItem item, DragEventArgs e) { - HidePreview(); - e.Handled = true; - } - - class DropTarget { - public WinDirTreeViewItem Item; - public DropPlace Place; - public double Y; - public WinDirNode Node; - public int Index; - public DragDropEffects Effect; - } - - DropTarget GetDropTarget(WinDirTreeViewItem item, DragEventArgs e) { - var dropTargets = BuildDropTargets(item, e); - var y = e.GetPosition(item).Y; - foreach (var target in dropTargets) { - if (target.Y >= y) { - return target; - } - } - return null; - } - - List BuildDropTargets(WinDirTreeViewItem item, DragEventArgs e) { - var result = new List(); - var node = item.Node; - - if (AllowDropOrder) { - TryAddDropTarget(result, item, DropPlace.Before, e); - } - - TryAddDropTarget(result, item, DropPlace.Inside, e); - - if (AllowDropOrder) { - if (node.IsExpanded && node.Children.Count > 0) { - var firstChildItem = ItemContainerGenerator.ContainerFromItem(node.Children[0]) as WinDirTreeViewItem; - TryAddDropTarget(result, firstChildItem, DropPlace.Before, e); - } - else { - TryAddDropTarget(result, item, DropPlace.After, e); - } - } - - var h = item.ActualHeight; - var y1 = 0.2 * h; - var y2 = h / 2; - var y3 = h - y1; - - if (result.Count == 2) { - if (result[0].Place == DropPlace.Inside && - result[1].Place != DropPlace.Inside) { - result[0].Y = y3; - } - else if (result[0].Place != DropPlace.Inside && - result[1].Place == DropPlace.Inside) { - result[0].Y = y1; - } - else { - result[0].Y = y2; - } - } - else if (result.Count == 3) { - result[0].Y = y1; - result[1].Y = y3; - } - if (result.Count > 0) { - result[result.Count - 1].Y = h; - } - return result; - } - - void TryAddDropTarget(List targets, WinDirTreeViewItem item, DropPlace place, DragEventArgs e) { - WinDirNode node; - int index; - - GetNodeAndIndex(item, place, out node, out index); - - if (node != null) { - var effect = node.GetDropEffect(e, index); - if (effect != DragDropEffects.None) { - DropTarget target = new DropTarget() { - Item = item, - Place = place, - Node = node, - Index = index, - Effect = effect - }; - targets.Add(target); - } - } - } - - void GetNodeAndIndex(WinDirTreeViewItem item, DropPlace place, out WinDirNode node, out int index) { - node = null; - index = 0; - - if (place == DropPlace.Inside) { - node = item.Node; - index = node.Children.Count; - } - else if (place == DropPlace.Before) { - if (item.Node.Parent != null) { - node = item.Node.Parent; - index = node.Children.IndexOf(item.Node); - } - } - else { - if (item.Node.Parent != null) { - node = item.Node.Parent; - index = node.Children.IndexOf(item.Node) + 1; - } - } - } - - WinDirNodeView previewNodeView; - InsertMarker insertMarker; - DropPlace previewPlace; - - enum DropPlace { - Before, Inside, After - } - - void ShowPreview(WinDirTreeViewItem item, DropPlace place) { - previewNodeView = item.NodeView; - previewPlace = place; - - if (place == DropPlace.Inside) { - previewNodeView.TextBackground = SystemColors.HighlightBrush; - previewNodeView.Foreground = SystemColors.HighlightTextBrush; - } - else { - if (insertMarker == null) { - var adornerLayer = AdornerLayer.GetAdornerLayer(this); - var adorner = new GeneralAdorner(this); - insertMarker = new InsertMarker(); - adorner.Child = insertMarker; - adornerLayer.Add(adorner); - } - - insertMarker.Visibility = Visibility.Visible; - - var p1 = previewNodeView.TransformToVisual(this).Transform(new Point()); - var p = new Point(p1.X + previewNodeView.CalculateIndent() + 4.5, p1.Y - 3); - - if (place == DropPlace.After) { - p.Y += previewNodeView.ActualHeight; - } - - insertMarker.Margin = new Thickness(p.X, p.Y, 0, 0); - - WinDirNodeView secondNodeView = null; - var index = flattener.IndexOf(item.Node); - - if (place == DropPlace.Before) { - if (index > 0) { - secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index - 1) as WinDirTreeViewItem).NodeView; - } - } - else if (index + 1 < flattener.Count) { - secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index + 1) as WinDirTreeViewItem).NodeView; - } - - var w = p1.X + previewNodeView.ActualWidth - p.X; - - if (secondNodeView != null) { - var p2 = secondNodeView.TransformToVisual(this).Transform(new Point()); - w = Math.Max(w, p2.X + secondNodeView.ActualWidth - p.X); - } - - insertMarker.Width = w + 10; - } - } - - void HidePreview() { - if (previewNodeView != null) { - previewNodeView.ClearValue(WinDirNodeView.TextBackgroundProperty); - previewNodeView.ClearValue(WinDirNodeView.ForegroundProperty); - if (insertMarker != null) { - insertMarker.Visibility = Visibility.Collapsed; - } - previewNodeView = null; - } - }*/ - #endregion - - #region Cut / Copy / Paste / Delete Commands (Disabled) - - static void RegisterCommands() { - /*CommandManager.RegisterClassCommandBinding(typeof(WinDirTreeView), - new CommandBinding(ApplicationCommands.Cut, HandleExecuted_Cut, HandleCanExecute_Cut)); - - CommandManager.RegisterClassCommandBinding(typeof(WinDirTreeView), - new CommandBinding(ApplicationCommands.Copy, HandleExecuted_Copy, HandleCanExecute_Copy)); - - CommandManager.RegisterClassCommandBinding(typeof(WinDirTreeView), - new CommandBinding(ApplicationCommands.Paste, HandleExecuted_Paste, HandleCanExecute_Paste)); - - CommandManager.RegisterClassCommandBinding(typeof(WinDirTreeView), - new CommandBinding(ApplicationCommands.Delete, HandleExecuted_Delete, HandleCanExecute_Delete));*/ - } - - /*static void HandleExecuted_Cut(object sender, ExecutedRoutedEventArgs e) { - e.Handled = true; - WinDirTreeView treeView = (WinDirTreeView) sender; - var nodes = treeView.GetTopLevelSelection().ToArray(); - if (nodes.Length > 0) - nodes[0].Cut(nodes); - } - - static void HandleCanExecute_Cut(object sender, CanExecuteRoutedEventArgs e) { - WinDirTreeView treeView = (WinDirTreeView) sender; - var nodes = treeView.GetTopLevelSelection().ToArray(); - e.CanExecute = nodes.Length > 0 && nodes[0].CanCut(nodes); - e.Handled = true; - } - - static void HandleExecuted_Copy(object sender, ExecutedRoutedEventArgs e) { - e.Handled = true; - WinDirTreeView treeView = (WinDirTreeView) sender; - var nodes = treeView.GetTopLevelSelection().ToArray(); - if (nodes.Length > 0) - nodes[0].Copy(nodes); - } - - static void HandleCanExecute_Copy(object sender, CanExecuteRoutedEventArgs e) { - WinDirTreeView treeView = (WinDirTreeView) sender; - var nodes = treeView.GetTopLevelSelection().ToArray(); - e.CanExecute = nodes.Length > 0 && nodes[0].CanCopy(nodes); - e.Handled = true; - } - - static void HandleExecuted_Paste(object sender, ExecutedRoutedEventArgs e) { - WinDirTreeView treeView = (WinDirTreeView) sender; - var data = Clipboard.GetDataObject(); - if (data != null) { - var selectedNode = (treeView.SelectedItem as WinDirNode) ?? treeView.Root; - if (selectedNode != null) - selectedNode.Paste(data); - } - e.Handled = true; - } - - static void HandleCanExecute_Paste(object sender, CanExecuteRoutedEventArgs e) { - WinDirTreeView treeView = (WinDirTreeView) sender; - var data = Clipboard.GetDataObject(); - if (data == null) { - e.CanExecute = false; - } - else { - var selectedNode = (treeView.SelectedItem as WinDirNode) ?? treeView.Root; - e.CanExecute = selectedNode != null && selectedNode.CanPaste(data); - } - e.Handled = true; - } - - static void HandleExecuted_Delete(object sender, ExecutedRoutedEventArgs e) { - e.Handled = true; - WinDirTreeView treeView = (WinDirTreeView) sender; - var nodes = treeView.GetTopLevelSelection().ToArray(); - if (nodes.Length > 0) - nodes[0].Delete(nodes); - } - - static void HandleCanExecute_Delete(object sender, CanExecuteRoutedEventArgs e) { - WinDirTreeView treeView = (WinDirTreeView) sender; - var nodes = treeView.GetTopLevelSelection().ToArray(); - e.CanExecute = nodes.Length > 0 && nodes[0].CanDelete(nodes); - e.Handled = true; - }*/ - - /// - /// Gets the selected items which do not have any of their ancestors selected. - /// - public IEnumerable GetTopLevelSelection() { - var selection = this.SelectedItems.OfType(); - var selectionHash = new HashSet(selection); - return selection.Where(item => item.Ancestors().All(a => !selectionHash.Contains(a))); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/FileTreeViewItem.cs b/WinDirStat.Net.Wpf/Controls/FileList/FileTreeViewItem.cs deleted file mode 100644 index 3ceaa65..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/FileTreeViewItem.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Controls; -using System.Windows; -using System.Windows.Media; -using System.Windows.Input; -using System.Diagnostics; -using WinDirStat.Net.ViewModel.Files; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - public class FileTreeViewItem : ListViewItem { - static FileTreeViewItem() { - DefaultStyleKeyProperty.OverrideMetadata(typeof(FileTreeViewItem), - new FrameworkPropertyMetadata(typeof(FileTreeViewItem))); - } - - public FileItemViewModel Node { - get { return DataContext as FileItemViewModel; } - } - - public FileTreeNodeView NodeView { get; internal set; } - public FileTreeView ParentTreeView { get; internal set; } - - protected override void OnKeyDown(KeyEventArgs e) { - switch (e.Key) { - case Key.F2: - if (Node.IsEditable && ParentTreeView != null && ParentTreeView.SelectedItems.Count == 1 && ParentTreeView.SelectedItems[0] == Node) { - Node.IsEditing = true; - e.Handled = true; - } - break; - case Key.Escape: - if (Node.IsEditing) { - Node.IsEditing = false; - e.Handled = true; - } - break; - } - } - - #region Mouse - - Point startPoint; - bool wasSelected; - bool wasDoubleClick; - - protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { - wasSelected = IsSelected; - if (!IsSelected) { - base.OnMouseLeftButtonDown(e); - } - - if (Mouse.LeftButton == MouseButtonState.Pressed) { - startPoint = e.GetPosition(null); - CaptureMouse(); - - if (e.ClickCount == 2) { - wasDoubleClick = true; - } - } - } - - /*protected override void OnMouseMove(MouseEventArgs e) { - if (IsMouseCaptured) { - var currentPoint = e.GetPosition(null); - if (Math.Abs(currentPoint.X - startPoint.X) >= SystemParameters.MinimumHorizontalDragDistance || - Math.Abs(currentPoint.Y - startPoint.Y) >= SystemParameters.MinimumVerticalDragDistance) { - - var selection = ParentTreeView.GetTopLevelSelection().ToArray(); - Node.StartDrag(this, selection); - } - } - }*/ - - protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { - if (wasDoubleClick) { - wasDoubleClick = false; - Node.ActivateItem(); - if (!e.Handled) { - if (!Node.IsRoot || ParentTreeView.ShowRootExpander) { - Node.IsExpanded = !Node.IsExpanded; - } - } - } - - ReleaseMouseCapture(); - if (wasSelected) { - base.OnMouseLeftButtonDown(e); - } - } - - protected override void OnContextMenuOpening(ContextMenuEventArgs e) { - if (Node != null) - Node.ShowContextMenu(e); - } - - #endregion - - #region Drag and Drop - - /*protected override void OnDragEnter(DragEventArgs e) { - ParentTreeView.HandleDragEnter(this, e); - } - - protected override void OnDragOver(DragEventArgs e) { - ParentTreeView.HandleDragOver(this, e); - } - - protected override void OnDrop(DragEventArgs e) { - ParentTreeView.HandleDrop(this, e); - } - - protected override void OnDragLeave(DragEventArgs e) { - ParentTreeView.HandleDragLeave(this, e); - }*/ - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/GeneralAdorner.cs b/WinDirStat.Net.Wpf/Controls/FileList/GeneralAdorner.cs deleted file mode 100644 index 9a9e702..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/GeneralAdorner.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Documents; -using System.Windows; -using System.Windows.Media; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - public class GeneralAdorner : Adorner { - public GeneralAdorner(UIElement target) - : base(target) { - } - - FrameworkElement child; - - public FrameworkElement Child { - get => child; - set { - if (child != value) { - RemoveVisualChild(child); - RemoveLogicalChild(child); - child = value; - AddLogicalChild(value); - AddVisualChild(value); - InvalidateMeasure(); - } - } - } - - protected override int VisualChildrenCount { - get { return child == null ? 0 : 1; } - } - - protected override Visual GetVisualChild(int index) { - return child; - } - - protected override Size MeasureOverride(Size constraint) { - if (child != null) { - child.Measure(constraint); - return child.DesiredSize; - } - return new Size(); - } - - protected override Size ArrangeOverride(Size finalSize) { - if (child != null) { - child.Arrange(new Rect(finalSize)); - return finalSize; - } - return new Size(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/InsertMarker.cs b/WinDirStat.Net.Wpf/Controls/FileList/InsertMarker.cs deleted file mode 100644 index 4eeb55d..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/InsertMarker.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Controls; -using System.Windows; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - public class InsertMarker : Control { - static InsertMarker() { - DefaultStyleKeyProperty.OverrideMetadata(typeof(InsertMarker), - new FrameworkPropertyMetadata(typeof(InsertMarker))); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FileList/LinesRenderer.cs b/WinDirStat.Net.Wpf/Controls/FileList/LinesRenderer.cs deleted file mode 100644 index 2ad6b40..0000000 --- a/WinDirStat.Net.Wpf/Controls/FileList/LinesRenderer.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Media; - -namespace WinDirStat.Net.Wpf.Controls.FileList { - class LinesRenderer : FrameworkElement { - static LinesRenderer() { - pen = new Pen(Brushes.LightGray, 1); - pen.Freeze(); - } - - static Pen pen; - - FileTreeNodeView NodeView { - get { return TemplatedParent as FileTreeNodeView; } - } - - protected override void OnRender(DrawingContext dc) { - double indent = NodeView.CalculateIndent(); - Point p = new Point(indent + 4.5, 0); - double endY = Math.Floor(ActualHeight / 2) + 0.5; - - if (!NodeView.Node.IsRoot || NodeView.ParentTreeView.ShowRootExpander) { - dc.DrawLine(pen, new Point(p.X, endY), new Point(p.X + 10.5, endY)); - } - - if (NodeView.Node.IsRoot) return; - - if (NodeView.Node.IsLast) { - dc.DrawLine(pen, p, new Point(p.X, endY)); - } - else { - dc.DrawLine(pen, p, new Point(p.X, ActualHeight)); - } - - var current = NodeView.Node; - while (true) { - p.X -= 18; - current = current.Parent; - if (p.X < 0) break; - if (!current.IsLast) { - dc.DrawLine(pen, p, new Point(p.X, ActualHeight)); - } - } - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FlashyProgressBar.cs b/WinDirStat.Net.Wpf/Controls/FlashyProgressBar.cs deleted file mode 100644 index f5f3921..0000000 --- a/WinDirStat.Net.Wpf/Controls/FlashyProgressBar.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Controls; - -namespace WinDirStat.Net.Wpf.Controls { - public class FlashyProgressBar : ProgressBar { - - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FocusBehavior.cs b/WinDirStat.Net.Wpf/Controls/FocusBehavior.cs deleted file mode 100644 index 7cdacdf..0000000 --- a/WinDirStat.Net.Wpf/Controls/FocusBehavior.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Diagnostics; -using System.Windows; -using System.Windows.Input; -using System.Windows.Interactivity; - -namespace WinDirStat.Net.Wpf.Controls { - /// A behavior for binding to readonly focus of the element. - public class FocusBehavior : Behavior { - - #region Dependency Properties - - /// Gets the property for standard control focus. - public static readonly DependencyProperty IsFocusedProperty = - DependencyProperty.Register( - "IsFocused", typeof(bool), typeof(FocusBehavior), - new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); - - /// Gets the property for keyboard control focus. - public static readonly DependencyProperty IsKeyboardFocusedProperty = - DependencyProperty.Register( - "IsKeyboardFocused", typeof(bool), typeof(FocusBehavior), - new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); - - /// Gets if the control has standard focus. - public bool IsFocused { - get => (bool) GetValue(IsFocusedProperty); - set => SetValue(IsFocusedProperty, value); - } - - /// Gets if the control has keyboard focus. - public bool IsKeyboardFocused { - get => (bool) GetValue(IsKeyboardFocusedProperty); - set => SetValue(IsKeyboardFocusedProperty, value); - } - - #endregion - - #region Override Methods - - /// Attaches the focus events. - protected override void OnAttached() { - base.OnAttached(); - AssociatedObject.GotFocus += OnGotFocus; - AssociatedObject.LostFocus += OnLostFocus; - AssociatedObject.GotKeyboardFocus += OnGotKeyboardFocus; - AssociatedObject.LostKeyboardFocus += OnLostKeyboardFocus; - } - - /// Detaches the focus events. - protected override void OnDetaching() { - base.OnDetaching(); - if (AssociatedObject != null) { - AssociatedObject.GotFocus -= OnGotFocus; - AssociatedObject.LostFocus -= OnLostFocus; - AssociatedObject.GotKeyboardFocus -= OnGotKeyboardFocus; - AssociatedObject.LostKeyboardFocus -= OnLostKeyboardFocus; - } - } - - #endregion - - #region Event Handlers - - /// Called when the control receives standard focus. - private void OnGotFocus(object sender, RoutedEventArgs e) { - Debug.WriteLine("GotFocus"); - IsFocused = true; - } - /// Called when the control loses standard focus. - private void OnLostFocus(object sender, RoutedEventArgs e) { - Debug.WriteLine("LostFocus"); - IsFocused = false; - } - - /// Called when the control receives keyboard focus. - private void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { - Debug.WriteLine("GotKeyboardFocus"); - IsKeyboardFocused = true; - } - /// Called when the control loses keyboard focus. - private void OnLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { - Debug.WriteLine("LostKeyboardFocus"); - IsKeyboardFocused = false; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Controls/FocusExtension.cs b/WinDirStat.Net.Wpf/Controls/FocusExtension.cs deleted file mode 100644 index 6dd4d42..0000000 --- a/WinDirStat.Net.Wpf/Controls/FocusExtension.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; - -namespace WinDirStat.Net.Wpf.Controls { - public static class FocusExtension { - - - private static readonly DependencyPropertyKey IsFocusedPropertyKey = - DependencyProperty.RegisterAttachedReadOnly( - "IsFocused", typeof(bool?), typeof(FocusExtension), - new FrameworkPropertyMetadata(null, OnIsFocusedPropertyChanged)); - - public static readonly DependencyProperty IsFocusedProperty = - IsFocusedPropertyKey.DependencyProperty; - - /// Gets if the control has focus. - public static bool? GetIsFocused(DependencyObject obj) { - return (bool?) obj.GetValue(IsFocusedProperty); - } - - private static void SetIsFocused(DependencyObject obj, bool? value) { - obj.SetValue(IsFocusedPropertyKey, value); - } - - - private static readonly DependencyPropertyKey IsKeyboardFocusedPropertyKey = - DependencyProperty.RegisterAttachedReadOnly( - "IsKeyboardFocused", typeof(bool?), typeof(FocusExtension), - new FrameworkPropertyMetadata(null, OnIsKeyboardFocusedPropertyChanged)); - - public static readonly DependencyProperty IsKeyboardFocusedProperty = - IsKeyboardFocusedPropertyKey.DependencyProperty; - - public static bool? GetIsKeyboardFocused(DependencyObject obj) { - return (bool?) obj.GetValue(IsKeyboardFocusedProperty); - } - - private static void SetIsKeyboardFocused(DependencyObject obj, bool? value) { - obj.SetValue(IsKeyboardFocusedPropertyKey, value); - } - - private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - FrameworkElement element = (FrameworkElement) d; - if (e.OldValue == null) { - element.GotFocus += OnGotFocus; - element.LostFocus += OnLostFocus; - element.GotKeyboardFocus += OnGotKeyboardFocus; - element.LostKeyboardFocus += OnLostKeyboardFocus; - } - else if (e.NewValue == null) { - element.GotFocus -= OnGotFocus; - element.LostFocus -= OnLostFocus; - element.GotKeyboardFocus -= OnGotKeyboardFocus; - element.LostKeyboardFocus -= OnLostKeyboardFocus; - } - - /*if (((bool?) e.NewValue) ?? false) { - element.Focus(); // Don't care about false values. - //Keyboard.Focus(element); - }*/ - } - - private static void OnIsKeyboardFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - FrameworkElement element = (FrameworkElement) d; - if (e.OldValue == null) { - element.GotFocus += OnGotFocus; - element.LostFocus += OnLostFocus; - element.GotKeyboardFocus += OnGotKeyboardFocus; - element.LostKeyboardFocus += OnLostKeyboardFocus; - } - else if (e.NewValue == null) { - element.GotFocus -= OnGotFocus; - element.LostFocus -= OnLostFocus; - element.GotKeyboardFocus -= OnGotKeyboardFocus; - element.LostKeyboardFocus -= OnLostKeyboardFocus; - } - - /*if (((bool?) e.NewValue) ?? false) { - element.Focus(); // Don't care about false values. - //Keyboard.Focus(element); - }*/ - } - - private static void OnGotFocus(object sender, RoutedEventArgs e) { - FrameworkElement element = (FrameworkElement) sender; - Console.WriteLine("GotFocus"); - SetIsFocused(element, true); - } - private static void OnLostFocus(object sender, RoutedEventArgs e) { - FrameworkElement element = (FrameworkElement) sender; - Console.WriteLine("LostFocus"); - SetIsFocused(element, false); - } - - private static void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { - FrameworkElement element = (FrameworkElement) sender; - //SetIsFocused(element, true); - Console.WriteLine("LostKeyboardFocus"); - } - - private static void OnLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { - FrameworkElement element = (FrameworkElement) sender; - //SetIsFocused(element, false); - Console.WriteLine("GotKeyboardFocus"); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/GraphView.xaml b/WinDirStat.Net.Wpf/Controls/GraphView.xaml deleted file mode 100644 index 0cc39a5..0000000 --- a/WinDirStat.Net.Wpf/Controls/GraphView.xaml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - diff --git a/WinDirStat.Net.Wpf/Controls/GraphView.xaml.cs b/WinDirStat.Net.Wpf/Controls/GraphView.xaml.cs deleted file mode 100644 index 739a531..0000000 --- a/WinDirStat.Net.Wpf/Controls/GraphView.xaml.cs +++ /dev/null @@ -1,506 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using System.Windows.Threading; -using WinDirStat.Net.Utils; -//using Bitmap = System.Drawing.Bitmap; -//using Graphics = System.Drawing.Graphics; -using Brush = System.Drawing.Brush; -using Pen = System.Drawing.Pen; -using Color = System.Drawing.Color; -using Rectangle = System.Drawing.Rectangle; -using WinDirStat.Net.Model.Files; -using WinDirStat.Net.Structures; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Services; -using WinDirStat.Net.Wpf.ViewModel; -using WinDirStat.Net.ViewModel; -using WinDirStat.Net.Wpf.Utils; - -namespace WinDirStat.Net.Wpf.Controls { - public class GraphViewHoverEventArgs : RoutedEventArgs { - - public FileItemBase Hover; - - public GraphViewHoverEventArgs(RoutedEvent routedEvent, FileItemBase hover) - : base(routedEvent) - { - Hover = hover; - } - } - - public delegate void GraphViewHoverEventHandler(object sender, GraphViewHoverEventArgs e); - - - /// - /// Interaction logic for WpfGraphView.xaml - /// - public partial class GraphView : UserControl { - - public enum HighlightMode { - None, - Extension, - Selection, - } - - public static readonly DependencyProperty RootProperty = - DependencyProperty.Register("Root", typeof(FileItemBase), typeof(GraphView), - new FrameworkPropertyMetadata(null, OnRootChanged)); - - private static void OnRootChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is GraphView graphView) { - FileItemBase root = graphView.Root; - if (root == null) { - graphView.AbortRender(); - } - - graphView.root = root; - graphView.HighlightNone(); - graphView.Hover = null; - if (root != null) { - //lock (graphView.drawBitmapLock) - graphView.RenderAsync(); - } - else { - graphView.Clear(); - } - - } - } - - public FileItemBase Root { - get => (FileItemBase) GetValue(RootProperty); - set => SetValue(RootProperty, value); - } - - private static readonly DependencyPropertyKey HoverPropertyKey = - DependencyProperty.RegisterReadOnly("Hover", typeof(FileItemBase), typeof(GraphView), - new FrameworkPropertyMetadata(null, OnHoverChanged)); - - public static readonly DependencyProperty HoverProperty = - HoverPropertyKey.DependencyProperty; - - private static void OnHoverChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is GraphView graphView) { - FileItemBase hover = e.NewValue as FileItemBase; - graphView.HasHover = hover != null; - graphView.RaiseEvent(new GraphViewHoverEventArgs(HoverChangedEvent, hover)); - } - } - - public FileItemBase Hover { - get => (FileItemBase) GetValue(HoverProperty); - private set => SetValue(HoverPropertyKey, value); - } - - private static readonly DependencyPropertyKey HasHoverPropertyKey = - DependencyProperty.RegisterReadOnly("HasHover", typeof(bool), typeof(GraphView), - new FrameworkPropertyMetadata(false)); - - public static readonly DependencyProperty HasHoverProperty = - HasHoverPropertyKey.DependencyProperty; - - public bool HasHover { - get => (bool) GetValue(HasHoverProperty); - private set => SetValue(HasHoverPropertyKey, value); - } - - public static readonly RoutedEvent HoverChangedEvent = - EventManager.RegisterRoutedEvent("HoverChanged", RoutingStrategy.Bubble, - typeof(GraphViewHoverEventHandler), typeof(GraphView)); - - public event GraphViewHoverEventHandler HoverChanged { - add => AddHandler(HoverChangedEvent, value); - remove => RemoveHandler(HoverChangedEvent, value); - } - - private static readonly DependencyProperty RenderPriorityProperty = - DependencyProperty.Register("RenderPriority", typeof(ThreadPriority), typeof(GraphView), - new FrameworkPropertyMetadata(ThreadPriority.BelowNormal)); - - public ThreadPriority RenderPriority { - get => (ThreadPriority) GetValue(RenderPriorityProperty); - set => SetValue(RenderPriorityProperty, value); - } - - /*private static readonly DependencyProperty ForceDimmedProperty = - DependencyProperty.Register("ForceDimmed", typeof(bool), typeof(GraphView), - new FrameworkPropertyMetadata(false, OnForceDimmedChanged)); - - public bool ForceDimmed { - get => (bool) GetValue(ForceDimmedProperty); - set => SetValue(ForceDimmedProperty, value); - } - - private static void OnForceDimmedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is GraphView graphView) { - graphView.UpdateDimmed(); - if (graphView.ForceDimmed) { - graphView.AbortRender(); - graphView.disabledTreemap = graphView.treemap; - graphView.disabledHighlight = graphView.highlight; - graphView.imageTreemap.Source = graphView.disabledTreemap; - graphView.imageHighlight.Source = graphView.disabledHighlight; - } - else { - graphView.disabledTreemap = null; - // GraphView will render if (!ForceDimmed and Root != null) - graphView.RenderAsync(); - } - } - }*/ - - private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is GraphView graphView) { - graphView.UpdateDimmed(); - if (!graphView.IsEnabled) { - graphView.AbortRender(); - graphView.disabledTreemap = graphView.treemap; - graphView.disabledHighlight = graphView.highlight; - graphView.imageTreemap.Source = graphView.disabledTreemap; - graphView.imageHighlight.Source = graphView.disabledHighlight; - } - else { - graphView.disabledTreemap = null; - graphView.disabledHighlight = null; - // GraphView will render if (!IsEnabled and Root != null) - graphView.RenderAsync(); - } - } - } - - private void UpdateDimmed() { - IsDimmed = IsRenderingTreemap || resizing || !IsEnabled; - } - - private static readonly DependencyPropertyKey IsDimmedPropertyKey = - DependencyProperty.RegisterReadOnly("IsDimmed", typeof(bool), typeof(GraphView), - new FrameworkPropertyMetadata(false, OnIsDimmedChanged)); - - private static void OnIsDimmedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - GraphView graphView = (GraphView) d; - - if (graphView.IsDimmed) - graphView.Hover = null; - else if (graphView.IsMouseOver) - graphView.UpdateHover(); - } - - public static readonly DependencyProperty IsDimmedProperty = - IsDimmedPropertyKey.DependencyProperty; - - public bool IsDimmed { - get => (bool) GetValue(IsDimmedProperty); - private set => SetValue(IsDimmedPropertyKey, value); - } - - private static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - GraphView graphView = (GraphView) d; - MainViewModel oldViewModel = e.OldValue as MainViewModel; - MainViewModel newViewModel = e.NewValue as MainViewModel; - - if (oldViewModel != null) - oldViewModel.Settings.PropertyChanged -= graphView.OnSettingsChanged; - if (graphView.IsLoaded && newViewModel != null) - newViewModel.Settings.PropertyChanged += graphView.OnSettingsChanged; - graphView.ViewModel = newViewModel; - } - - private void OnSettingsChanged(object sender, PropertyChangedEventArgs e) { - switch (e.PropertyName) { - case nameof(SettingsService.TreemapOptions): - case nameof(SettingsService.FilePalette): - RenderAsync(); - break; - case nameof(SettingsService.HighlightColor): - if (highlightMode != HighlightMode.None) - RenderHighlight(treemapSize); - break; - } - } - - private Point2I treemapSize; - private WriteableBitmap treemap; - private Point2I highlightSize; - private WriteableBitmap highlight; - private Bitmap highlightGdi; - private WriteableBitmap disabledTreemap; - private WriteableBitmap disabledHighlight; - private readonly DispatcherTimer resizeTimer; - private Thread renderThread; - private FileItemBase root; - private bool resizing; - /// Check if the running render thread has finished rendering the treemap. - private volatile bool treemapRendered; - private volatile bool fullRender; - //private TreemapOptions options; - - private readonly object renderLock = new object(); - private readonly object drawBitmapLock = new object(); - private FileItemBase[] selection; - private string extension; - private HighlightMode highlightMode; - - static GraphView() { - DataContextProperty.AddOwner(typeof(GraphView), - new FrameworkPropertyMetadata(OnDataContextChanged)); - IsEnabledProperty.AddOwner(typeof(GraphView), - new FrameworkPropertyMetadata(OnIsEnabledChanged)); - } - - public GraphView() { - if (!this.DesignerInitializeComponent("Controls")) - InitializeComponent(); - - resizeTimer = new DispatcherTimer( - TimeSpan.FromMilliseconds(50), - DispatcherPriority.Normal, - OnResizeTimerTick, - Dispatcher); - resizeTimer.Stop(); - treemapSize = Point2I.Zero; - highlightSize = Point2I.Zero; - highlightMode = HighlightMode.None; - treemapRendered = true; - } - - public void HighlightNone() { - highlightMode = HighlightMode.None; - extension = null; - selection = null; - imageHighlight.Source = null; - } - - public void HighlightExtension(string extension) { - if (this.extension == extension) - return; - - highlightMode = HighlightMode.Extension; - this.extension = extension; - selection = null; - if (IsRendering) { - RenderHighlightAsync(); - } - else if (!IsDimmed && Root != null) { - RenderHighlight(treemapSize); - if (imageHighlight.Source != highlight) - imageHighlight.Source = highlight; - } - //RenderHighlightAsync(ThreadPriority.Normal); - //Render(true); - } - - public void HighlightSelection(IEnumerable selection) { - if (this.selection != null && this.selection.Intersect(selection.Cast()).Count() == this.selection.Length) - return; - - highlightMode = HighlightMode.Selection; - this.selection = selection.Cast().ToArray(); - extension = null; - if (IsRendering) { - RenderHighlightAsync(); - } - else if (!IsDimmed && Root != null) { - RenderHighlight(treemapSize); - if (imageHighlight.Source != highlight) - imageHighlight.Source = highlight; - } - //RenderHighlightAsync(ThreadPriority.Normal); - //Render(true); - } - - private void OnLoaded(object sender, RoutedEventArgs e) { - resizeTimer.Start(); - } - - private void OnUnloaded(object sender, RoutedEventArgs e) { - resizeTimer.Stop(); - AbortRender(); - } - - private void OnSizeChanged(object sender, SizeChangedEventArgs e) { - resizing = true; - IsDimmed = true; - // Restart the timer by stopping it first - resizeTimer.Stop(); - resizeTimer.Start(); - } - - private void OnResizeTimerTick(object sender, EventArgs e) { - resizing = false; - UpdateDimmed(); - resizeTimer.Stop(); - RenderAsync(); - } - - - - /// Gets if anything is in the process of being rendered. - private bool IsRendering => renderThread?.IsAlive ?? false; - - /// Gets if the treemap is in the process of being rendered. - private bool IsRenderingTreemap => renderThread?.IsAlive ?? false && fullRender; - - /// A link to the view model that can be accessed outside of the UI thread. - private MainViewModel ViewModel { get; set; } - private SettingsService Settings => ViewModel.Settings; - private TreemapRenderer Treemap => ViewModel.Treemap; - - private TreemapOptions Options { - get => Settings.TreemapOptions; - } - private Rgba32Color HighlightColor { - get => Settings.HighlightColor; - } - - private void Clear() { - AbortRender(); - treemap = null; - highlight = null; - treemapSize = Point2I.Zero; - highlightSize = Point2I.Zero; - } - - public void AbortRender(bool waitForExit = true) { - if (renderThread != null) { - renderThread.Abort(); - renderThread = null; - UpdateDimmed(); - } - } - - public void RenderHighlightAsync(ThreadPriority? priority = null) { - fullRender = !treemapRendered; - RenderAsyncFinal(priority); - } - - public void RenderAsync(ThreadPriority? priority = null) { - fullRender = true; - RenderAsyncFinal(priority); - } - - private void RenderAsyncFinal(ThreadPriority? priority = null) { - if (IsEnabled && Root != null) { - AbortRender(); - treemapRendered = false; - //IsDimmed = true; - Point2I size = new Point2I((int) ActualWidth, (int) ActualHeight); - renderThread = new Thread(() => RenderThread(size)) { - Priority = priority ?? RenderPriority, - Name = "GraphView Render", - }; - renderThread.Start(); - UpdateDimmed(); - } - } - - private void RenderThread(Point2I size) { - try { - if (size.X != 0 && size.Y != 0) { - if (fullRender) { - RenderTreemap(size); - } - treemapRendered = true; - if (highlightMode != HighlightMode.None) { - RenderHighlight(size); - } - } - Dispatcher.Invoke(() => { - // Let the control know we're not rendering anymore - renderThread = null; - imageTreemap.Source = treemap; - if (highlightMode != HighlightMode.None) - imageHighlight.Source = highlight; - UpdateDimmed(); - }); - } - catch (ThreadAbortException) { } - catch (Exception ex) { - Stopwatch sw = Stopwatch.StartNew(); - Dispatcher.Invoke(() => { - Console.WriteLine(ex.ToString()); - renderThread = null; - UpdateDimmed(); - UpdateHover(); - }); - Console.WriteLine($"Took {sw.ElapsedMilliseconds}ms to invoke EXCEPTION Dispatcher"); - } - } - - private void RenderTreemap(Point2I size) { - Stopwatch sw = Stopwatch.StartNew(); - if (treemap == null || treemapSize.X != size.X || treemapSize.Y != size.Y) { - treemapSize = size; - Application.Current.Dispatcher.Invoke(() => { - treemap = new WriteableBitmap(size.X, size.Y, 96, 96, PixelFormats.Bgra32, null); - }); - } - Treemap.DrawTreemap(treemap, new Rectangle2I(size), root); - //Treemap.DrawTreemap(treemap, new Rectangle2I(size), fileRoot, options); - Console.WriteLine($"Took {sw.ElapsedMilliseconds}ms to render treemap"); - } - private void RenderHighlight(Point2I size) { - Stopwatch sw = Stopwatch.StartNew(); - if (highlight == null || highlightSize.X != size.X || highlightSize.Y != size.Y) { - highlightSize = size; - Application.Current.Dispatcher.Invoke(() => { - highlight = new WriteableBitmap(size.X, size.Y, 96, 96, PixelFormats.Bgra32, null); - }); - highlightGdi?.Dispose(); - highlightGdi = new Bitmap(size.X, size.Y, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - Trace.WriteLine($"Took {sw.ElapsedMilliseconds}ms to setup highlight bitmap"); - } - sw.Restart(); - if (highlightMode == HighlightMode.Extension) { - Treemap.HighlightExtensions(highlight, new Rectangle2I(size), root, Settings.HighlightColor, extension); - } - else if (highlightMode == HighlightMode.Selection) { - Treemap.HighlightItems(highlight, new Rectangle2I(size), Settings.HighlightColor, selection); - } - Trace.WriteLine($"Took {sw.ElapsedMilliseconds}ms to render highlight"); - Trace.WriteLine(""); - } - - private void OnMouseMove(object sender, MouseEventArgs e) { - UpdateHover(e.GetPosition(this).ToPoint2I()); - } - - private void OnMouseLeave(object sender, MouseEventArgs e) { - Hover = null; - } - - private void UpdateHover() { - UpdateHover(Mouse.GetPosition(this).ToPoint2I()); - } - - private void UpdateHover(Point2I point) { - if (root == null) { - Hover = null; - return; - } - if (Hover != null) { - Rectangle2I rc = ((ITreemapItem) Hover).Rectangle; - if (rc.Contains(point)) - return; // Hover is the same - } - Hover = (FileItemBase) TreemapRenderer.FindItemAtPoint(root, point); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/ImageButton.cs b/WinDirStat.Net.Wpf/Controls/ImageButton.cs deleted file mode 100644 index dca7c21..0000000 --- a/WinDirStat.Net.Wpf/Controls/ImageButton.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using WinDirStat.Net.Utils; -using WinDirStat.Net.Wpf.Utils; - -namespace WinDirStat.Net.Wpf.Controls { - public class ImageButton : Button { - - /// The dependency property for the button's image. - public static readonly DependencyProperty SourceProperty = - DependencyProperty.RegisterAttached("Source", typeof(ImageSource), typeof(ImageButton), - new FrameworkPropertyMetadata(OnSourceChanged)); - - /// Gets or sets the source of the button's image. - [Category("Common")] - public ImageSource Source { - get => (ImageSource) GetValue(SourceProperty); - set => SetValue(SourceProperty, value); - } - - /// Called when the source property for the button is changed. - private static void OnSourceChanged(object sender, DependencyPropertyChangedEventArgs e) { - ImageButton button = (ImageButton) sender; - button.image.Source = button.Source; - - button.CoerceValue(ContentProperty); - } - - private static object CoerceContent(DependencyObject d, object value) { - ImageButton button = (ImageButton) d; - - if (button.IsValueUnsetAndNull(ContentProperty, value)) { - return button.image; - } - return value; - } - - /// The image that contains the buttons's icon. - private Image image; - - /// Initializes the image buttons default style. - static ImageButton() { - //DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), - // new FrameworkPropertyMetadata(typeof(ImageButton))); - ContentProperty.OverrideMetadata(typeof(ImageButton), - new FrameworkPropertyMetadata(null, CoerceContent)); - } - - /// Constructs an empty buttons. - public ImageButton() { - image = new Image() { - Stretch = Stretch.None, - }; - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/ImageMenuItem.cs b/WinDirStat.Net.Wpf/Controls/ImageMenuItem.cs deleted file mode 100644 index 0bd83d0..0000000 --- a/WinDirStat.Net.Wpf/Controls/ImageMenuItem.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using WinDirStat.Net.Utils; -using WinDirStat.Net.Wpf.Utils; - -namespace WinDirStat.Net.Wpf.Controls { - /// A menu item with easy access for setting its icon. - public class ImageMenuItem : MenuItem { - - /// The dependency property for the menu item's image. - public static readonly DependencyProperty SourceProperty = - DependencyProperty.RegisterAttached("Source", typeof(ImageSource), typeof(ImageMenuItem), - new FrameworkPropertyMetadata(OnSourceChanged)); - - /// Gets or sets the source of the menu item's image. - [Category("Common")] - public ImageSource Source { - get => (ImageSource) GetValue(SourceProperty); - set => SetValue(SourceProperty, value); - } - - /// Called when the source property for the menu item is changed. - private static void OnSourceChanged(object sender, DependencyPropertyChangedEventArgs e) { - ImageMenuItem menuItem = (ImageMenuItem) sender; - menuItem.image.Source = menuItem.Source; - } - - private static object CoerceIcon(DependencyObject d, object value) { - ImageMenuItem menuItem = (ImageMenuItem) d; - - if (menuItem.IsValueUnsetAndNull(IconProperty, value)) { - return menuItem.image; - } - return value; - } - - /// The image that contains the menu item's icon. - private Image image; - - /// Initializes the image menu item default style. - static ImageMenuItem() { - //DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageMenuItem), - // new FrameworkPropertyMetadata(typeof(ImageMenuItem))); - IconProperty.OverrideMetadata(typeof(ImageMenuItem), - new FrameworkPropertyMetadata(null, CoerceIcon)); - } - - /// Constructs an empty menu item. - public ImageMenuItem() { - image = new Image() { - Stretch = Stretch.None, - }; - Icon = image; - } - - /// Constructs an menu item with an image and name. - public ImageMenuItem(ImageSource source, string header) { - image = new Image() { - Stretch = Stretch.None, - Source = source, - }; - Icon = image; - Header = header; - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/ListSettings.cs b/WinDirStat.Net.Wpf/Controls/ListSettings.cs deleted file mode 100644 index cc089cd..0000000 --- a/WinDirStat.Net.Wpf/Controls/ListSettings.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; - -namespace WinDirStat.Net.Wpf.Controls { - public static class ListSettings { - - public static readonly DependencyProperty InactiveSelectionProperty = - DependencyProperty.RegisterAttached("InactiveSelection", typeof(bool), typeof(ListSettings), - new FrameworkPropertyMetadata(true)); - - public static bool GetInactiveSelection(DependencyObject d) { - return (bool) d.GetValue(InactiveSelectionProperty); - } - - public static void SetInactiveSelection(DependencyObject d, bool value) { - d.SetValue(InactiveSelectionProperty, value); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/PercentageBar.cs b/WinDirStat.Net.Wpf/Controls/PercentageBar.cs deleted file mode 100644 index ed4d326..0000000 --- a/WinDirStat.Net.Wpf/Controls/PercentageBar.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Shapes; - -namespace WinDirStat.Net.Wpf.Controls { - public class PercentageBar : Control { - - public static readonly DependencyProperty FillProperty = - Rectangle.FillProperty.AddOwner(typeof(PercentageBar), - new FrameworkPropertyMetadata(Brushes.LimeGreen)); - - public static readonly DependencyProperty PercentageProperty = - DependencyProperty.Register("Percentage", typeof(double), typeof(PercentageBar), - new FrameworkPropertyMetadata(0d, OnPercentageChanged, CoercePercentage)); - - private static void OnPercentageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is PercentageBar percentageBar) { - percentageBar.UpdatePercentage(); - } - } - - private static object CoercePercentage(DependencyObject d, object baseValue) { - return Math.Max(0d, Math.Min(1d, (double) baseValue)); - } - - public Brush Fill { - get => (Brush) GetValue(FillProperty); - set => SetValue(FillProperty, value); - } - - public double Percentage { - get => (double) GetValue(PercentageProperty); - set => SetValue(PercentageProperty, value); - } - - static PercentageBar() { - DefaultStyleKeyProperty.OverrideMetadata(typeof(PercentageBar), - new FrameworkPropertyMetadata(typeof(PercentageBar))); - SnapsToDevicePixelsProperty.OverrideMetadata(typeof(PercentageBar), - new FrameworkPropertyMetadata(true)); - } - - private ColumnDefinition PART_FillColoumn; - private ColumnDefinition PART_EmptyColoumn; - - public override void OnApplyTemplate() { - base.OnApplyTemplate(); - PART_FillColoumn = GetTemplateChild("PART_FillColoumn") as ColumnDefinition; - PART_EmptyColoumn = GetTemplateChild("PART_EmptyColoumn") as ColumnDefinition; - UpdatePercentage(); - } - - private void UpdatePercentage() { - if (Template != null) { - PART_FillColoumn.Width = new GridLength(Percentage, GridUnitType.Star); - PART_EmptyColoumn.Width = new GridLength(1d - Percentage, GridUnitType.Star); - } - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/RelayUIBinding.cs b/WinDirStat.Net.Wpf/Controls/RelayUIBinding.cs deleted file mode 100644 index 1bdbdd6..0000000 --- a/WinDirStat.Net.Wpf/Controls/RelayUIBinding.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; -using WinDirStat.Net.ViewModel; -using WinDirStat.Net.Wpf.Services.Structures; - -namespace WinDirStat.Net.Wpf.Controls { - public class RelayUIBinding : KeyBinding { - - private static void OnCommandChanged(object sender, DependencyPropertyChangedEventArgs e) { - ((RelayUIBinding) sender).OnCommandChanged(e); - } - - private void OnCommandChanged(DependencyPropertyChangedEventArgs e) { - base.Gesture = RelayUICommand?.InputGesture; - } - - static RelayUIBinding() { - CommandProperty.AddOwner(typeof(RelayUIBinding), - new UIPropertyMetadata(OnCommandChanged)); - } - - public IWpfRelayCommand RelayUICommand { - get => Command as IWpfRelayCommand; - } - - public override InputGesture Gesture { - get => base.Gesture; - set => throw new NotSupportedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/SortList/SortListView.cs b/WinDirStat.Net.Wpf/Controls/SortList/SortListView.cs deleted file mode 100644 index f419048..0000000 --- a/WinDirStat.Net.Wpf/Controls/SortList/SortListView.cs +++ /dev/null @@ -1,352 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - -namespace WinDirStat.Net.Wpf.Controls.SortList { - public class SortViewEventArgs : RoutedEventArgs { - - public object Mode { get; } - public ListSortDirection Direction { get; } - public bool IsDescending { - get => Direction == ListSortDirection.Descending; - } - - public TEnum ParseMode() { - return (TEnum) Enum.Parse(typeof(TEnum), Mode as string); - } - - public SortViewEventArgs(RoutedEvent routedEvent, object mode, ListSortDirection direction) - : base(routedEvent) - { - Mode = mode; - Direction = direction; - } - } - - public delegate void SortViewEventHandler(object sender, SortViewEventArgs e); - - public class SortListView : ListView { - private struct ColumnPair { - public SortViewColumn Column { get; } - public GridViewColumnHeader Header { get; } - - public ColumnPair(SortViewColumn column, GridViewColumnHeader header) { - Column = column; - Header = header; - } - } - - - //public static ResourceKey CellTemplateKey { get; } = - // new ComponentResourceKey(typeof(SortListView), "CellTemplateKey"); - //public static ResourceKey ColumnHeaderContainerStyleKey { get; } = - // new ComponentResourceKey(typeof(SortListView), "ColumnHeaderContainerStyleKey"); - /*internal static readonly DependencyPropertyKey HeaderSortDirectionPropertyKey = - DependencyProperty.RegisterAttachedReadOnly("HeaderSortDirection", typeof(ListSortDirection?), typeof(SortListView), - new FrameworkPropertyMetadata(null));*/ - - public static readonly DependencyProperty CellTemplateProperty = - GridViewColumn.CellTemplateProperty.AddOwner(typeof(SortListView)); - - public DataTemplate CellTemplate { - get => (DataTemplate) GetValue(CellTemplateProperty); - set => SetValue(CellTemplateProperty, value); - } - - public static readonly DependencyProperty HeaderContainerStyleProperty = - GridViewColumn.HeaderContainerStyleProperty.AddOwner(typeof(SortListView)); - - public Style HeaderContainerStyle { - get => (Style) GetValue(HeaderContainerStyleProperty); - set => SetValue(HeaderContainerStyleProperty, value); - } - - public static readonly RoutedEvent SortEvent = - EventManager.RegisterRoutedEvent("Sort", RoutingStrategy.Bubble, typeof(SortViewEventHandler), typeof(SortListView)); - - public event SortViewEventHandler Sort { - add => AddHandler(SortEvent, value); - remove => RemoveHandler(SortEvent, value); - } - - - internal static readonly DependencyPropertyKey ColumnSortDirectionPropertyKey = - DependencyProperty.RegisterAttachedReadOnly("ColumnSortDirection", typeof(ListSortDirection?), typeof(SortListView), - new FrameworkPropertyMetadata(null)); - - public static readonly DependencyProperty ColumnSortDirectionProperty = - ColumnSortDirectionPropertyKey.DependencyProperty; - - public static ListSortDirection? GetColumnSortDirection(DependencyObject d) { - return (ListSortDirection?) d.GetValue(ColumnSortDirectionProperty); - } - - internal static void SetColumnSortDirection(DependencyObject d, ListSortDirection? value) { - d.SetValue(ColumnSortDirectionPropertyKey, value); - } - - internal static readonly DependencyPropertyKey ColumnHeaderTextAlignmentPropertyKey = - DependencyProperty.RegisterAttachedReadOnly("ColumnHeaderTextAlignment", typeof(TextAlignment), typeof(SortListView), - new FrameworkPropertyMetadata(TextAlignment.Left)); - - public static readonly DependencyProperty ColumnHeaderTextAlignmentProperty = - ColumnHeaderTextAlignmentPropertyKey.DependencyProperty; - - public static TextAlignment GetColumnHeaderTextAlignment(DependencyObject d) { - return (TextAlignment) d.GetValue(ColumnHeaderTextAlignmentProperty); - } - - internal static void SetColumnHeaderTextAlignment(DependencyObject d, TextAlignment value) { - d.SetValue(ColumnHeaderTextAlignmentPropertyKey, value); - } - - public static readonly DependencyProperty SortDirectionProperty = - DependencyProperty.Register("SortDirection", typeof(ListSortDirection), typeof(SortListView), - new FrameworkPropertyMetadata(ListSortDirection.Ascending, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSortChanged)); - - public ListSortDirection SortDirection { - get => (ListSortDirection) GetValue(SortDirectionProperty); - set => SetValue(SortDirectionProperty, value); - } - - public static readonly DependencyProperty SortModeProperty = - DependencyProperty.Register("SortMode", typeof(string), typeof(SortListView), - new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); - - public string SortMode { - get => (string) GetValue(SortModeProperty); - set => SetValue(SortModeProperty, value); - } - - private static void OnSortChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is SortListView listView && !listView.supressSortEvent) { - listView.UpdateColumns(); - listView.OnSort(); - } - } - - private static void OnViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is SortListView listView) { - if (e.OldValue is SortView oldSortView) { - oldSortView.Columns.CollectionChanged -= listView.OnColumnsChanged; - } - if (e.NewValue is SortView newSortView) { - newSortView.Columns.CollectionChanged += listView.OnColumnsChanged; - //listView.Style = (Style) listView.FindResource(typeof(SortListView)); - } - else if (e.NewValue != null) { - throw new InvalidOperationException($"View is not a {nameof(SortView)}!"); - } - listView.UpdateColumns(); - } - } - - public override void OnApplyTemplate() { - base.OnApplyTemplate(); - UpdateColumns(); - } - - private void UpdateColumns() { - if (!IsLoaded) - return; - object mode = SortMode; - ListSortDirection sortDirection = SortDirection; - foreach (ColumnPair pair in ColumnsPairs) { - if (mode == null || !object.Equals(mode, pair.Column.SortMode)) { - SetColumnSortDirection(pair.Column, null); - SetColumnSortDirection(pair.Header, null); - } - else { - SetColumnSortDirection(pair.Column, sortDirection); - SetColumnSortDirection(pair.Header, sortDirection); - } - } - } - - private void OnColumnsChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (e.Action == NotifyCollectionChangedAction.Move) - return; - - object mode = SortMode; - ListSortDirection sortDirection = SortDirection; - if (!IsLoaded) - return; - if (e.NewItems != null) { - var presenter = Presenter; - if (presenter == null) - return; - - for (int i = 0; i < e.NewItems.Count; i++) { - ColumnPair pair = GetColumnPairAt(presenter, i + e.NewStartingIndex); - if (mode == null || !object.Equals(mode, pair.Column.SortMode)) { - SetColumnSortDirection(pair.Column, null); - SetColumnSortDirection(pair.Header, null); - } - else { - SetColumnSortDirection(pair.Column, sortDirection); - SetColumnSortDirection(pair.Header, sortDirection); - } - } - } - } - - static SortListView() { - DefaultStyleKeyProperty.OverrideMetadata(typeof(SortListView), - new FrameworkPropertyMetadata(typeof(SortListView))); - ViewProperty.OverrideMetadata(typeof(SortListView), - new FrameworkPropertyMetadata(null, OnViewChanged)); - VirtualizingStackPanel.VirtualizationModeProperty.OverrideMetadata(typeof(SortListView), - new FrameworkPropertyMetadata(VirtualizationMode.Recycling)); - Grid.IsSharedSizeScopeProperty.OverrideMetadata(typeof(SortListView), - new FrameworkPropertyMetadata(true)); - - - EventManager.RegisterClassHandler(typeof(SortListView), - GridViewColumnHeader.ClickEvent, new RoutedEventHandler(OnGridViewColumnHeaderClick)); - } - - private static void OnGridViewColumnHeaderClick(object sender, RoutedEventArgs e) { - if (e.OriginalSource is GridViewColumnHeader header && sender is SortListView listView) { - if (!(header.Column is SortViewColumn column)) - return; - - string oldSortMode = listView.SortMode; - string newSortMode = column.SortMode; - - if (!object.Equals(oldSortMode, newSortMode)) { - listView.SetSort(newSortMode, column.DefaultSortDirection); - } - else if (newSortMode != null) { - listView.ToggleSortDirection(); - } - } - - e.Handled = true; - } - - private bool supressSortEvent; - - - public void ToggleSortDirection() { - if (SortDirection == ListSortDirection.Ascending) - SortDirection = ListSortDirection.Descending; - else - SortDirection = ListSortDirection.Ascending; - } - - public SortListView() { - Loaded += OnLoaded; - } - - private void OnLoaded(object sender, RoutedEventArgs e) { - UpdateColumns(); - } - - public void SetSort(string mode, ListSortDirection direction) { - // Do all this extra work to avoid triggering a sort 'only' once, if needed - bool newMode = !object.Equals(mode, SortMode); - bool newDirection = direction != SortDirection; - if (newMode) { - supressSortEvent = true; - if (newDirection) { - SortDirection = direction; - } - SortMode = mode; - supressSortEvent = false; - UpdateColumns(); - OnSort(); - } - else if (newDirection) { - supressSortEvent = true; - SortDirection = direction; - supressSortEvent = false; - UpdateColumns(); - OnSort(); - } - } - - protected virtual void OnSort() { - RaiseEvent(new SortViewEventArgs(SortEvent, SortMode, SortDirection)); - } - - private SortView SortView { - get => View as SortView; - } - - /*private IEnumerable SortColumns { - get { - if (View is SortView sortView) { - return sortView.Columns.Cast(); - } - return Enumerable.Empty(); - } - }*/ - - private GridViewHeaderRowPresenter Presenter { - get => GetDescendantByType(); - } - - private IEnumerable ColumnsPairs { - get { - if (View is SortView sortView) { - var presenter = Presenter; - if (presenter == null) - yield break; - - for (int i = 0; i < sortView.Columns.Count; i++) - yield return GetColumnPairAt(sortView, presenter, i); - } - } - } - - private ColumnPair GetColumnPairAt(GridViewHeaderRowPresenter presenter, int index) { - return new ColumnPair(GetColumnAt(index), GetHeader(SortView, presenter, index)); - } - - private ColumnPair GetColumnPairAt(SortView sortView, GridViewHeaderRowPresenter presenter, int index) { - return new ColumnPair(GetColumnAt(sortView, index), GetHeader(sortView, presenter, index)); - } - - private SortViewColumn GetColumnAt(int index) { - return (SortViewColumn) SortView.Columns[index]; - } - - private SortViewColumn GetColumnAt(SortView sortView, int index) { - return (SortViewColumn) sortView.Columns[index]; - } - - private GridViewColumnHeader GetHeader(SortView sortView, GridViewHeaderRowPresenter presenter, int index) { - return (GridViewColumnHeader) VisualTreeHelper.GetChild(presenter, sortView.Columns.Count - index); - } - - private T GetDescendantByType() where T : Visual { - return GetDescendantByType(this); - } - - private static T GetDescendantByType(Visual element) where T : Visual { - if (element == null) - return null; - if (element is T t) - return t; - - T foundElement = null; - if (element is FrameworkElement frameworkElement) - frameworkElement.ApplyTemplate(); - - for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++) { - Visual visual = VisualTreeHelper.GetChild(element, i) as Visual; - foundElement = GetDescendantByType(visual); - if (foundElement != null) - break; - } - return foundElement; - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/SortList/SortView.cs b/WinDirStat.Net.Wpf/Controls/SortList/SortView.cs deleted file mode 100644 index f1b3b22..0000000 --- a/WinDirStat.Net.Wpf/Controls/SortList/SortView.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - -namespace WinDirStat.Net.Wpf.Controls.SortList { - public class SortView : GridView { - - static SortView() { - ColumnHeaderContainerStyleProperty.OverrideMetadata(typeof(SortView), - new FrameworkPropertyMetadata(SortViewKeys.HeaderContainerLeftAlignStyle)); - } - - protected override object DefaultStyleKey { - get => SortViewStyleKey; - } - - protected override object ItemContainerDefaultStyleKey { - get => SortViewItemContainerStyleKey; - } - - public static ResourceKey SortViewStyleKey { get; } = - new ComponentResourceKey(typeof(SortView), "SortViewStyleKey"); - - public static ResourceKey SortViewItemContainerStyleKey { get; } = - new ComponentResourceKey(typeof(SortView), "SortViewItemContainerStyleKey"); - - public SortView() { - Columns.CollectionChanged += OnColumnsChanged; - } - - private void OnColumnsChanged(object sender, NotifyCollectionChangedEventArgs e) { - // Nothing needs to be changed if moving columns around - if (e.Action == NotifyCollectionChangedAction.Move) - return; - - if (e.NewItems != null) { - foreach (object item in e.NewItems) { - //if (item is SortViewColumn column) - // column.HeaderContainerStyle = SortViewKeys.HeaderContainerLeftAlignStyle; - if (!(item is SortViewColumn)) - throw new InvalidOperationException($"Column is not a {nameof(SortViewColumn)}!"); - } - } - } - - protected override void AddChild(object column) { - if (column is SortViewColumn c) - Columns.Add(c); - else - throw new InvalidOperationException($"column is not a {nameof(SortViewColumn)}!"); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/SortList/SortViewColumn.cs b/WinDirStat.Net.Wpf/Controls/SortList/SortViewColumn.cs deleted file mode 100644 index 36eb52b..0000000 --- a/WinDirStat.Net.Wpf/Controls/SortList/SortViewColumn.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; - -namespace WinDirStat.Net.Wpf.Controls.SortList { - public class SortViewColumn : GridViewColumn { - - public static readonly DependencyProperty TextAlignmentProperty = - TextBlock.TextAlignmentProperty.AddOwner(typeof(SortViewColumn), - new FrameworkPropertyMetadata(TextAlignment.Left, OnTextAlignmentChanged)); - - private static void OnTextAlignmentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is SortViewColumn column) { - switch (column.TextAlignment) { - case TextAlignment.Left: - column.HeaderContainerStyle = SortViewKeys.HeaderContainerLeftAlignStyle; - break; - case TextAlignment.Right: - column.HeaderContainerStyle = SortViewKeys.HeaderContainerRightAlignStyle; - break; - default: - column.HeaderContainerStyle = SortViewKeys.HeaderContainerCenterAlignStyle; - break; - } - if (column.cellBinding != null) - column.RebuildCellTemplate(); - } - } - - public TextAlignment TextAlignment { - get => (TextAlignment) GetValue(TextAlignmentProperty); - set => SetValue(TextAlignmentProperty, value); - } - - public static readonly DependencyProperty DefaultSortDirectionProperty = - DependencyProperty.Register("DefaultSortDirection", typeof(ListSortDirection), typeof(SortViewColumn), - new FrameworkPropertyMetadata(ListSortDirection.Ascending)); - - public ListSortDirection DefaultSortDirection { - get => (ListSortDirection) GetValue(DefaultSortDirectionProperty); - set => SetValue(DefaultSortDirectionProperty, value); - } - - public static readonly DependencyProperty SortModeProperty = - DependencyProperty.Register("SortMode", typeof(string), typeof(SortViewColumn), - new FrameworkPropertyMetadata(null)); - - public string SortMode { - get => (string) GetValue(SortModeProperty); - set => SetValue(SortModeProperty, value); - } - - public ListSortDirection? SortDirection { - get => SortListView.GetColumnSortDirection(this); - //internal set => SetValue(SortDirectionPropertyKey, value); - } - - public static readonly DependencyProperty CellDataTemplateProperty = - DependencyProperty.Register("CellDataTemplate", typeof(DataTemplate), typeof(SortViewColumn), - new FrameworkPropertyMetadata(OnCellDataTemplateChanged)); - - public DataTemplate CellDataTemplate { - get => (DataTemplate) GetValue(CellDataTemplateProperty); - set => SetValue(CellDataTemplateProperty, value); - } - - static SortViewColumn() { - //HeaderContainerStyleProperty.OverrideMetadata(typeof(SortViewColumn), - // new FrameworkPropertyMetadata(Application.Current.FindResource(SortListView.ColumnHeaderContainerStyleKey))); - //CellTemplateProperty.OverrideMetadata(typeof(SortViewColumn), - // new FrameworkPropertyMetadata(SortListView.CellTemplateKey)); - //HeaderContainerStyleProperty.OverrideMetadata(typeof(SortViewColumn), - // new FrameworkPropertyMetadata(SortViewKeys.HeaderContainerLeftAlignStyle)); - /*CellTemplateProperty.OverrideMetadata(typeof(SortViewColumn), - new FrameworkPropertyMetadata(typeof(SortViewColumn)));*/ - } - - public SortViewColumn() { - HeaderContainerStyle = SortViewKeys.HeaderContainerLeftAlignStyle; - //if (SortViewKeys.HeaderContainerLeftAlignStyle == null) - // throw new InvalidOperationException("HALP!"); - /*SetValue(HeaderContainerStyleProperty, - Activator.CreateInstance(Type.GetType( - "System.Windows.ResourceReferenceExpression, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"), - SortViewKeys.HeaderContainerLeftAlignStyleKey));*/ - } - - /*private static Style headerContainerLeftAlignStyle; - private static Style headerContainerCenterAlignStyle; - private static Style headerContainerRightAlignStyle; - - private static ResourceDictionary resourceDictionary; - - private static ResourceDictionary ResourceDictionary { - get { - if (resourceDictionary == null) { - resourceDictionary = new ResourceDictionary(); - resourceDictionary.Source = new Uri("/WinDirStat.Net;component/Themes/Generic.xaml", UriKind.RelativeOrAbsolute); - } - return resourceDictionary; - } - } - - public static Style HeaderContainerLeftAlignStyle { - get { - if (headerContainerLeftAlignStyle == null) - headerContainerLeftAlignStyle = (Style) ResourceDictionary[HeaderContainerLeftAlignStyleKey]; - return headerContainerLeftAlignStyle; - } - } - - public static Style HeaderContainerCenterAlignStyle { - get { - if (headerContainerCenterAlignStyle == null) - headerContainerCenterAlignStyle = (Style) ResourceDictionary[HeaderContainerCenterAlignStyleKey]; - return headerContainerCenterAlignStyle; - } - } - - public static Style HeaderContainerRightAlignStyle { - get { - if (headerContainerRightAlignStyle == null) - headerContainerRightAlignStyle = (Style) ResourceDictionary[HeaderContainerRightAlignStyleKey]; - return headerContainerRightAlignStyle; - } - } - - public static ResourceKey HeaderContainerLeftAlignStyleKey { get; } = - new ComponentResourceKey(typeof(SortViewColumn), "HeaderContainerLeftAlignStyleKey"); - - public static ResourceKey HeaderContainerCenterAlignStyleKey { get; } = - new ComponentResourceKey(typeof(SortViewColumn), "HeaderContainerCenterAlignStyleKey"); - - public static ResourceKey HeaderContainerRightAlignStyleKey { get; } = - new ComponentResourceKey(typeof(SortViewColumn), "HeaderContainerRightAlignStyleKey");*/ - - private static void OnCellDataTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is SortViewColumn column) { - if (column.cellBinding == null) { - column.CellTemplate = column.CellDataTemplate; - } - } - } - - private void RebuildCellTemplate() { - var factory = new FrameworkElementFactory(typeof(TextBlock)); - factory.SetValue(TextBlock.TextAlignmentProperty, TextAlignment); - factory.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); - factory.SetBinding(TextBlock.TextProperty, cellBinding); - DataTemplate template = new DataTemplate { - VisualTree = factory, - }; - CellTemplate = template; - } - - public BindingBase CellBinding { - get => cellBinding; - set { - if (cellBinding != value) { - cellBinding = value; - if (cellBinding == null) { - CellTemplate = CellDataTemplate; - } - else { - RebuildCellTemplate(); - } - OnPropertyChanged(new PropertyChangedEventArgs(nameof(CellBinding))); - } - } - } - - private BindingBase cellBinding; - } -} diff --git a/WinDirStat.Net.Wpf/Controls/SortList/SortViewKeys.cs b/WinDirStat.Net.Wpf/Controls/SortList/SortViewKeys.cs deleted file mode 100644 index 8c6dd23..0000000 --- a/WinDirStat.Net.Wpf/Controls/SortList/SortViewKeys.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; - -namespace WinDirStat.Net.Wpf.Controls.SortList { - public class SortViewKeys { - private static Style headerContainerLeftAlignStyle; - private static Style headerContainerCenterAlignStyle; - private static Style headerContainerRightAlignStyle; - - public static Style HeaderContainerLeftAlignStyle { - get { - if (headerContainerLeftAlignStyle == null) - headerContainerLeftAlignStyle = (Style) Application.Current.FindResource(HeaderContainerLeftAlignStyleKey); - return headerContainerLeftAlignStyle; - } - } - - public static Style HeaderContainerCenterAlignStyle { - get { - if (headerContainerCenterAlignStyle == null) - headerContainerCenterAlignStyle = (Style) Application.Current.FindResource(HeaderContainerCenterAlignStyleKey); - return headerContainerCenterAlignStyle; - } - } - - public static Style HeaderContainerRightAlignStyle { - get { - if (headerContainerRightAlignStyle == null) - headerContainerRightAlignStyle = (Style) Application.Current.FindResource(HeaderContainerRightAlignStyleKey); - return headerContainerRightAlignStyle; - } - } - - public static ResourceKey HeaderContainerLeftAlignStyleKey { get; } = - new ComponentResourceKey(typeof(SortViewKeys), "HeaderContainerLeftAlignStyleKey"); - - public static ResourceKey HeaderContainerCenterAlignStyleKey { get; } = - new ComponentResourceKey(typeof(SortViewKeys), "HeaderContainerCenterAlignStyleKey"); - - public static ResourceKey HeaderContainerRightAlignStyleKey { get; } = - new ComponentResourceKey(typeof(SortViewKeys), "HeaderContainerRightAlignStyleKey"); - } -} diff --git a/WinDirStat.Net.Wpf/Controls/SubtreePercentage.cs b/WinDirStat.Net.Wpf/Controls/SubtreePercentage.cs deleted file mode 100644 index 427dbe8..0000000 --- a/WinDirStat.Net.Wpf/Controls/SubtreePercentage.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Shapes; -using WinDirStat.Net.ViewModel.Files; -using WinDirStat.Net.Wpf.Utils; -using WinDirStat.Net.Wpf.ViewModel; -//using WinDirStat.Net.Wpf.Controls.FileList; - -namespace WinDirStat.Net.Wpf.Controls { - public class SubtreePercentage : Control { - - public static readonly DependencyProperty FillProperty = - Rectangle.FillProperty.AddOwner(typeof(SubtreePercentage)); - - public static readonly DependencyProperty PercentageProperty = - DependencyProperty.Register("Percentage", typeof(double), typeof(SubtreePercentage), - new FrameworkPropertyMetadata(0d, OnPercentageChanged, CoercePercentage)); - - private static void OnPercentageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - if (d is SubtreePercentage subtreePercentage) { - subtreePercentage.UpdatePercentage(); - } - } - - private static object CoercePercentage(DependencyObject d, object baseValue) { - return Math.Max(0d, Math.Min(1d, (double) baseValue)); - } - - public Brush Fill { - get => (Brush) GetValue(FillProperty); - set => SetValue(FillProperty, value); - } - - public double Percentage { - get => (double) GetValue(PercentageProperty); - set => SetValue(PercentageProperty, value); - } - - static SubtreePercentage() { - DefaultStyleKeyProperty.OverrideMetadata(typeof(SubtreePercentage), - new FrameworkPropertyMetadata(typeof(SubtreePercentage))); - SnapsToDevicePixelsProperty.OverrideMetadata(typeof(SubtreePercentage), - new FrameworkPropertyMetadata(true)); - } - - private ColumnDefinition PART_FillColoumn; - private ColumnDefinition PART_EmptyColoumn; - - public override void OnApplyTemplate() { - base.OnApplyTemplate(); - PART_FillColoumn = GetTemplateChild("PART_FillColoumn") as ColumnDefinition; - PART_EmptyColoumn = GetTemplateChild("PART_EmptyColoumn") as ColumnDefinition; - UpdatePercentage(); - UpdateTemplate(); - } - - private void UpdatePercentage() { - if (Template != null) { - PART_FillColoumn.Width = new GridLength(Percentage, GridUnitType.Star); - PART_EmptyColoumn.Width = new GridLength(1d - Percentage, GridUnitType.Star); - } - } - - public FileItemViewModel Item { - get => ((FileItemViewModel) DataContext); - } - - /*public FileTreeViewItem ParentItem { get; private set; } - - public FileTreeView ParentTreeView { - get { return ParentItem.ParentTreeView; } - } - - protected override void OnVisualParentChanged(DependencyObject oldParent) { - base.OnVisualParentChanged(oldParent); - ParentItem = this.FindAncestor(); - }*/ - - protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { - base.OnPropertyChanged(e); - if (e.Property == DataContextProperty) { - UpdateDataContext(e.OldValue as FileItemViewModel, e.NewValue as FileItemViewModel); - } - } - - void UpdateDataContext(FileItemViewModel oldNode, FileItemViewModel newNode) { - if (newNode != null && Template != null) { - UpdateTemplate(); - } - } - - void UpdateTemplate() { - var spacer = GetTemplateChild("PART_SpacerColumn") as ColumnDefinition; - var filler = GetTemplateChild("PART_BarColumn") as ColumnDefinition; - int level = Item.Level; - double intent = CalculateIndent(level); - spacer.Width = new GridLength(1d - intent, GridUnitType.Star); - filler.Width = new GridLength(intent, GridUnitType.Star); - Fill = new SolidColorBrush(Item.ViewModel.Settings.GetSubtreePaletteColor(level).ToWpfColor()); - } - - private const double IndentRatio = 9d / 10d; - - internal double CalculateIndent(int level) { - if (Item == null || level == 0) - return 1d; - return Math.Max(0d, Math.Min(1d, Math.Pow(IndentRatio, level))); - } - } -} diff --git a/WinDirStat.Net.Wpf/Controls/VisibleColumnDefinition.cs b/WinDirStat.Net.Wpf/Controls/VisibleColumnDefinition.cs deleted file mode 100644 index 9ff87a1..0000000 --- a/WinDirStat.Net.Wpf/Controls/VisibleColumnDefinition.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; - -namespace WinDirStat.Net.Wpf.Controls { - public class VisibleColumnDefinition : ColumnDefinition { - - public static readonly DependencyProperty VisibleProperty = - DependencyProperty.Register("Visible", typeof(bool), typeof(VisibleColumnDefinition), - new PropertyMetadata(true, OnVisibleChanged)); - - private static void OnVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - VisibleColumnDefinition col = (VisibleColumnDefinition) d; - - if (col.Visible) { - col.visibleChanging = true; - col.Width = col.storedWidth; - col.MinWidth = col.storedMinWidth; - col.MaxWidth = col.storedMaxWidth; - col.visibleChanging = false; - } - else { - col.visibleChanging = true; - col.storedWidth = col.Width; - col.storedMinWidth = col.MinWidth; - col.storedMaxWidth = col.MaxWidth; - col.MinWidth = 0d; - col.Width = new GridLength(0); - col.MaxWidth = 0d; - col.visibleChanging = false; - } - } - - private static void OnWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - VisibleColumnDefinition col = (VisibleColumnDefinition) d; - if (!col.Visible && !col.visibleChanging) { - col.storedWidth = (GridLength) e.NewValue; - col.Width = new GridLength(0); - } - } - - private static void OnMinWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - VisibleColumnDefinition col = (VisibleColumnDefinition) d; - if (!col.Visible && !col.visibleChanging) { - col.storedMinWidth = (double) e.NewValue; - col.MinWidth = 0; - } - } - - private static void OnMaxWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - VisibleColumnDefinition col = (VisibleColumnDefinition) d; - if (!col.Visible && !col.visibleChanging) { - col.storedMaxWidth = (double) e.NewValue; - col.MaxWidth = 0; - } - } - - static VisibleColumnDefinition() { - WidthProperty.AddOwner(typeof(VisibleColumnDefinition), - new FrameworkPropertyMetadata(WidthProperty.DefaultMetadata.DefaultValue, OnWidthChanged)); - MinWidthProperty.AddOwner(typeof(VisibleColumnDefinition), - new FrameworkPropertyMetadata(MinWidthProperty.DefaultMetadata.DefaultValue, OnMinWidthChanged)); - MaxWidthProperty.AddOwner(typeof(VisibleColumnDefinition), - new FrameworkPropertyMetadata(MaxWidthProperty.DefaultMetadata.DefaultValue, OnMaxWidthChanged)); - } - - public bool Visible { - get => (bool) GetValue(VisibleProperty); - set => SetValue(VisibleProperty, value); - } - - private bool visibleChanging = false; - private GridLength storedWidth = (GridLength) WidthProperty.DefaultMetadata.DefaultValue; - private double storedMinWidth = (double) MinWidthProperty.DefaultMetadata.DefaultValue; - private double storedMaxWidth = (double) MaxWidthProperty.DefaultMetadata.DefaultValue; - } -} diff --git a/WinDirStat.Net.Wpf/Controls/VisibleRowDefinition.cs b/WinDirStat.Net.Wpf/Controls/VisibleRowDefinition.cs deleted file mode 100644 index 159a59f..0000000 --- a/WinDirStat.Net.Wpf/Controls/VisibleRowDefinition.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; - -namespace WinDirStat.Net.Wpf.Controls { - public class VisibleRowDefinition : RowDefinition { - - public static readonly DependencyProperty VisibleProperty = - DependencyProperty.Register("Visible", typeof(bool), typeof(VisibleRowDefinition), - new PropertyMetadata(true, OnVisibleChanged)); - - private static void OnVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - VisibleRowDefinition row = (VisibleRowDefinition) d; - - if (row.Visible) { - row.visibleChanging = true; - row.Height = row.storedHeight; - row.MinHeight = row.storedMinHeight; - row.MaxHeight = row.storedMaxHeight; - row.visibleChanging = false; - } - else { - row.visibleChanging = true; - row.storedHeight = row.Height; - row.storedMinHeight = row.MinHeight; - row.storedMaxHeight = row.MaxHeight; - row.MinHeight = 0d; - row.Height = new GridLength(0); - row.MaxHeight = 0d; - row.visibleChanging = false; - } - } - - private static void OnHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - VisibleRowDefinition row = (VisibleRowDefinition) d; - if (!row.Visible && !row.visibleChanging) { - row.storedHeight = (GridLength) e.NewValue; - row.Height = new GridLength(0); - } - } - - private static void OnMinHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - VisibleRowDefinition row = (VisibleRowDefinition) d; - if (!row.Visible && !row.visibleChanging) { - row.storedMinHeight = (double) e.NewValue; - row.MinHeight = 0; - } - } - - private static void OnMaxHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - VisibleRowDefinition row = (VisibleRowDefinition) d; - if (!row.Visible && !row.visibleChanging) { - row.storedMaxHeight = (double) e.NewValue; - row.MaxHeight = 0; - } - } - - static VisibleRowDefinition() { - HeightProperty.AddOwner(typeof(VisibleRowDefinition), - new FrameworkPropertyMetadata(HeightProperty.DefaultMetadata.DefaultValue, OnHeightChanged)); - MinHeightProperty.AddOwner(typeof(VisibleRowDefinition), - new FrameworkPropertyMetadata(MinHeightProperty.DefaultMetadata.DefaultValue, OnMinHeightChanged)); - MaxHeightProperty.AddOwner(typeof(VisibleRowDefinition), - new FrameworkPropertyMetadata(MaxHeightProperty.DefaultMetadata.DefaultValue, OnMaxHeightChanged)); - } - - public bool Visible { - get => (bool) GetValue(VisibleProperty); - set => SetValue(VisibleProperty, value); - } - - private bool visibleChanging = false; - private GridLength storedHeight = (GridLength) HeightProperty.DefaultMetadata.DefaultValue; - private double storedMinHeight = (double) MinHeightProperty.DefaultMetadata.DefaultValue; - private double storedMaxHeight = (double) MaxHeightProperty.DefaultMetadata.DefaultValue; - } -} diff --git a/WinDirStat.Net.Wpf/Converters/AttributesFormatter.cs b/WinDirStat.Net.Wpf/Converters/AttributesFormatter.cs deleted file mode 100644 index 3375e51..0000000 --- a/WinDirStat.Net.Wpf/Converters/AttributesFormatter.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Globalization; -using System.IO; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class AttributesFormatter : MarkupExtension, IValueConverter { - public static AttributesFormatter Instance = new AttributesFormatter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - if (value is FileAttributes attr) { - string s = ""; - if (attr.HasFlag(FileAttributes.ReadOnly)) s += "R"; - if (attr.HasFlag(FileAttributes.Hidden)) s += "H"; - if (attr.HasFlag(FileAttributes.System)) s += "S"; - if (attr.HasFlag(FileAttributes.Archive)) s += "A"; - if (attr.HasFlag(FileAttributes.Compressed)) s += "C"; - if (attr.HasFlag(FileAttributes.Encrypted)) s += "E"; - return s; - } - return null; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/ByteFormatter.cs b/WinDirStat.Net.Wpf/Converters/ByteFormatter.cs deleted file mode 100644 index 9cba909..0000000 --- a/WinDirStat.Net.Wpf/Converters/ByteFormatter.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Markup; -using WinDirStat.Net.Utils; - -namespace WinDirStat.Net.Wpf.Converters { - public class ByteFormatter : MarkupExtension, IValueConverter { - public static ByteFormatter Instance = new ByteFormatter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - try { - return FormatBytes.Format(System.Convert.ToDouble(value)); - } - catch { - return null; - } - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/CollapsedWhenBoolean.cs b/WinDirStat.Net.Wpf/Converters/CollapsedWhenBoolean.cs deleted file mode 100644 index a8c1717..0000000 --- a/WinDirStat.Net.Wpf/Converters/CollapsedWhenBoolean.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class CollapsedWhenFalse : MarkupExtension, IValueConverter { - public static CollapsedWhenFalse Instance = new CollapsedWhenFalse(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return (bool) value ? Visibility.Visible : Visibility.Collapsed; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } - - public class CollapsedWhenTrue : MarkupExtension, IValueConverter { - public static CollapsedWhenTrue Instance = new CollapsedWhenTrue(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return (bool) value ? Visibility.Collapsed : Visibility.Visible; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/DirectoryExistsToBoolean.cs b/WinDirStat.Net.Wpf/Converters/DirectoryExistsToBoolean.cs deleted file mode 100644 index dce9d56..0000000 --- a/WinDirStat.Net.Wpf/Converters/DirectoryExistsToBoolean.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class DirectoryExistsToBoolean : MarkupExtension, IValueConverter { - public static DirectoryExistsToBoolean Instance = new DirectoryExistsToBoolean(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - try { - string fullPath = Path.GetFullPath(value.ToString()); - return Directory.Exists(fullPath); - } - catch { - // Path must be invalid - return false; - } - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/FileTimeFormatter.cs b/WinDirStat.Net.Wpf/Converters/FileTimeFormatter.cs deleted file mode 100644 index a895b0f..0000000 --- a/WinDirStat.Net.Wpf/Converters/FileTimeFormatter.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class FileTimeFormatter : MarkupExtension, IValueConverter { - public static FileTimeFormatter Instance = new FileTimeFormatter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - try { - DateTime dt = (DateTime) value; - if (dt == DateTime.MinValue) - return ""; - string shortDateFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern; - string dtFormatted = dt.ToString(shortDateFormat.Replace("yyyy", "yy")); - return $"{dtFormatted} {dt.ToShortTimeString()}"; - } - catch { - return null; - } - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/InverseBoolean.cs b/WinDirStat.Net.Wpf/Converters/InverseBoolean.cs deleted file mode 100644 index 640018a..0000000 --- a/WinDirStat.Net.Wpf/Converters/InverseBoolean.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class InverseBoolean : MarkupExtension, IValueConverter { - public static InverseBoolean Instance = new InverseBoolean(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return !(bool) value; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - return !(bool) value; - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/ItemCountFormatter.cs b/WinDirStat.Net.Wpf/Converters/ItemCountFormatter.cs deleted file mode 100644 index 774f754..0000000 --- a/WinDirStat.Net.Wpf/Converters/ItemCountFormatter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class ItemCountFormatter : MarkupExtension, IValueConverter { - public static ItemCountFormatter Instance = new ItemCountFormatter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - try { - long l = System.Convert.ToInt64(value); - if (l == -1) - return ""; - return l.ToString("N0"); - } - catch { - return null; - } - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/RadioButtonConverter.cs b/WinDirStat.Net.Wpf/Converters/RadioButtonConverter.cs deleted file mode 100644 index 35bcb54..0000000 --- a/WinDirStat.Net.Wpf/Converters/RadioButtonConverter.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class RadioButtonConverter : MarkupExtension, IValueConverter { - public static RadioButtonConverter Instance = new RadioButtonConverter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return (parameter?.ToString() == value?.ToString()); - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - if ((bool) value) { - if (targetType == typeof(string)) - return parameter.ToString(); - else if (targetType.IsEnum) - return Enum.Parse(targetType, parameter.ToString()); - else - return System.Convert.ChangeType(parameter, targetType); - } - return Binding.DoNothing; - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/ScaleConverter.cs b/WinDirStat.Net.Wpf/Converters/ScaleConverter.cs deleted file mode 100644 index bb406b1..0000000 --- a/WinDirStat.Net.Wpf/Converters/ScaleConverter.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class ScaleConverter : MarkupExtension, IValueConverter { - public static ScaleConverter Instance = new ScaleConverter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - if (targetType == typeof(float)) - return System.Convert.ToSingle(value) * System.Convert.ToSingle(parameter); - else if (targetType == typeof(double)) - return System.Convert.ToDouble(value) * System.Convert.ToDouble(parameter); - else if (targetType == typeof(decimal)) - return System.Convert.ToDecimal(value) * System.Convert.ToDecimal(parameter); - return null; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - if (targetType == typeof(float)) - return System.Convert.ToSingle(value) / System.Convert.ToSingle(parameter); - else if (targetType == typeof(double)) - return System.Convert.ToDouble(value) / System.Convert.ToDouble(parameter); - else if (targetType == typeof(decimal)) - return System.Convert.ToDecimal(value) / System.Convert.ToDecimal(parameter); - return null; - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/ScanTimeFormatter.cs b/WinDirStat.Net.Wpf/Converters/ScanTimeFormatter.cs deleted file mode 100644 index 7319adc..0000000 --- a/WinDirStat.Net.Wpf/Converters/ScanTimeFormatter.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class ScanTimeFormatter : MarkupExtension, IValueConverter { - public static ScanTimeFormatter Instance = new ScanTimeFormatter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - if (value is TimeSpan time) { - // Time - //TimeSpan time = node.Document.ScanTime; - string s = $"{time.Seconds:00}"; - string m = $"{time.Minutes}:"; - string h = ""; - if (time.TotalHours >= 1) { - m = m.PadLeft(2, '0'); - h = $"{time.TotalHours:N0}:"; - } - return $"[ {h}{m}{s} s ]"; - } - return null; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/TextToHorizontalAlignment.cs b/WinDirStat.Net.Wpf/Converters/TextToHorizontalAlignment.cs deleted file mode 100644 index 930d3e3..0000000 --- a/WinDirStat.Net.Wpf/Converters/TextToHorizontalAlignment.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class TextToHorizontalAlignment : MarkupExtension, IValueConverter { - public static TextToHorizontalAlignment Instance = new TextToHorizontalAlignment(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - if (value is TextAlignment textAlignment) { - switch (textAlignment) { - case TextAlignment.Left: return HorizontalAlignment.Left; - case TextAlignment.Center: return HorizontalAlignment.Center; - case TextAlignment.Right: return HorizontalAlignment.Right; - case TextAlignment.Justify: return HorizontalAlignment.Stretch; - } - } - return null; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - if (value is HorizontalAlignment horizontalAlignment) { - switch (horizontalAlignment) { - case HorizontalAlignment.Left: return TextAlignment.Left; - case HorizontalAlignment.Center: return TextAlignment.Center; - case HorizontalAlignment.Right: return TextAlignment.Right; - case HorizontalAlignment.Stretch: return TextAlignment.Justify; - } - } - return null; - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/ZeroGridLengthWhenBoolean.cs b/WinDirStat.Net.Wpf/Converters/ZeroGridLengthWhenBoolean.cs deleted file mode 100644 index c87bbcd..0000000 --- a/WinDirStat.Net.Wpf/Converters/ZeroGridLengthWhenBoolean.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Globalization; -using System.Windows; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class ZeroGridLengthWhenFalse : MarkupExtension, IValueConverter { - public static ZeroGridLengthWhenFalse Instance = new ZeroGridLengthWhenFalse(); - - private GridLengthConverter converter = new GridLengthConverter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return (bool) value ? converter.ConvertFrom(parameter) : new GridLength(0); - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } - public class ZeroGridLengthWhenTrue : MarkupExtension, IValueConverter { - public static ZeroGridLengthWhenTrue Instance = new ZeroGridLengthWhenTrue(); - - private GridLengthConverter converter = new GridLengthConverter(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return (bool) value ? new GridLength(0) : converter.ConvertFrom(parameter); - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/Converters/ZeroWhenBoolean.cs b/WinDirStat.Net.Wpf/Converters/ZeroWhenBoolean.cs deleted file mode 100644 index 2fcb026..0000000 --- a/WinDirStat.Net.Wpf/Converters/ZeroWhenBoolean.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Markup; - -namespace WinDirStat.Net.Wpf.Converters { - public class ZeroWhenFalse : MarkupExtension, IValueConverter { - public static ZeroWhenFalse Instance = new ZeroWhenFalse(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return (bool) value ? parameter : 0; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } - public class ZeroWhenTrue : MarkupExtension, IValueConverter { - public static ZeroWhenTrue Instance = new ZeroWhenTrue(); - - public override object ProvideValue(IServiceProvider serviceProvider) { - return Instance; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return (bool) value ? 0 : parameter; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - throw new NotImplementedException(); - } - } -} diff --git a/WinDirStat.Net.Wpf/MainWindow.xaml b/WinDirStat.Net.Wpf/MainWindow.xaml deleted file mode 100644 index 7fe84f7..0000000 --- a/WinDirStat.Net.Wpf/MainWindow.xaml +++ /dev/null @@ -1,555 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WinDirStat.Net.Wpf/MainWindow.xaml.cs b/WinDirStat.Net.Wpf/MainWindow.xaml.cs deleted file mode 100644 index f1356a2..0000000 --- a/WinDirStat.Net.Wpf/MainWindow.xaml.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using WinDirStat.Net.ViewModel; -using WinDirStat.Net.ViewModel.Extensions; -using WinDirStat.Net.ViewModel.Files; -using WinDirStat.Net.Wpf.Services.Structures; - -namespace WinDirStat.Net.Wpf { - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class MainWindow : Window { - - #region Constructors - - /// Constructs the . - public MainWindow() { - InitializeComponent(); - } - - #endregion - - #region Properties - - /// Gets the . - public MainViewModel ViewModel => DataContext as MainViewModel; - - #endregion - - #region Event Handlers - - private void OnLoaded(object sender, RoutedEventArgs e) { - ViewModel.WindowOwner = new WpfWindow(this); - } - - private void OnFileSelectionChanged(object sender, SelectionChangedEventArgs e) { - OnFileTreeGotFocus(sender, e); - } - - private void OnExtensionSelectionChanged(object sender, SelectionChangedEventArgs e) { - OnExtensionListGotFocus(sender, e); - } - - private void OnFileTreeGotFocus(object sender, RoutedEventArgs e) { - if (tree.SelectedItems.Count > 0 && ViewModel.IsOpen) { - graphView.HighlightSelection(tree.SelectedItems.Cast().Select(v => v.Model)); - } - } - - private void OnExtensionListGotFocus(object sender, RoutedEventArgs e) { - if (extensionList.SelectedItem != null && ViewModel.IsOpen) { - graphView.HighlightExtension(((ExtensionItemViewModel) extensionList.SelectedItem).Extension); - } - } - private void OnGraphFileSelected(object sender, MouseButtonEventArgs e) { - if (graphView.HasHover) { - FileItemViewModel view = ViewModel.RootItem.FindView(graphView.Hover, true); - tree.FocusNode(view); - tree.SelectedItem = view; - //tree.Focus(); - //Keyboard.Focus(tree); - } - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Properties/App.manifest b/WinDirStat.Net.Wpf/Properties/App.manifest deleted file mode 100644 index a002935..0000000 --- a/WinDirStat.Net.Wpf/Properties/App.manifest +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WinDirStat.Net.Wpf/Properties/AssemblyInfo.cs b/WinDirStat.Net.Wpf/Properties/AssemblyInfo.cs deleted file mode 100644 index 39a043f..0000000 --- a/WinDirStat.Net.Wpf/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("WinDirStat.Net")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Trigger's Tools & Games")] -[assembly: AssemblyProduct("WinDirStat.Net")] -[assembly: AssemblyCopyright("Copyright © Robert Jordan {YEAR}")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] -[assembly: NeutralResourcesLanguage("en-US")] - diff --git a/WinDirStat.Net.Wpf/Resources/FileIcons/FileCollection.png b/WinDirStat.Net.Wpf/Resources/FileIcons/FileCollection.png deleted file mode 100644 index e03dc10b45a577fad06b18be74fed62cbb131aa9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 488 zcmVP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00CG@L_t(IPlb|QQ-VMghWSbTXU$AXEdoqa z5h46SrF)z4)*A=>hKrLgw(iDK?aVu8FL<7_oLz;86t=KO=D`QeW^o3sr2ITubEf$~D>)GpeyM2-T*HHv*+ot7mdEPIm)9I|Q z0>DXK0?(bPR;y9-wRt%@1paiE0*AxlM<7_ORuYJBO~d4Z@x=dC04NK_aZLJ) z&IQBaC|7{&_j?IM)t)sjz|ispfRQYS`c$uT0VbXmFnG7yN#N;pqUvLn3vgYcK!ms3 ztppyAM|x0IE;v7ot3U*i&1NHksFm_P7j(N;Dqx*OIEo?(L@k%@xBz#|1gtxQ!!VRU zoU~ND<$_l0EfwU!Odx_tu~6Uw_DC=+1pf?(B@2QPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00C%8L_t(IPkoa;OT$nUhVu&q5d^grK{vtO z$x(54krvd&(TWx)e}I#dIJmg!QWfGL)e;E^eql3+qM$g~+F~_nwH-t_p7-WPNbYS8 zJdif$d2i0mjS;QR_466VVkjWFaYYOHCu?Z=FeTg6;>H1{2%&rXo_cbx)O%1Cj2Egj zxBu{Kq;_1!X8NV(mz3SEO^5o-DkYD-5R11h8eOv+Mtb*+pv07Ah#kn7S-UcrEjDRl>!vB?06YoCnMQzxnRW8WX`Ql8oe~+d76~Y^ z{LYvN5F4fon7aO^^xor-BKuUtQy>649hCm=tm9GU z0#LT=By}Z;C1rt33 zJtM=93Yk-ZiZ*$=IEGmGCrhxJF#P}j-=6=7LV=u?iw#4TS4Cm=|Nlp4^89x+>ENHL z#K&NI=l<3A3}y^2%|8M(4>6=jpZV5(`H5#a>j|?7Yj?k5{nxx>_p6_sK)%?Fx96|F zXy&ch7u8=8-jLIH^WXakvNsy)*>gIISx=Pgc*?HrvDJt4la`Go@G^DXZI& zHsQnmztgTe~DWM4fC2Dw2 diff --git a/WinDirStat.Net.Wpf/Resources/FileIcons/Shortcut.png b/WinDirStat.Net.Wpf/Resources/FileIcons/Shortcut.png deleted file mode 100644 index 4145e999d3b033d68c1c9e36dd3fc8340db4c354..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucLCF%=h?3y^w370~qEv>0#LT=By}Z;C1rt33 zJtM=93Yk-ZiY|D%IEGmGzYR3xI^-a5X0gkL%^N>T3Oa7^nx_yEk(IevVlk(oqMMV6 zi<8QcI2P_)*7^xWDSVeTzcY%r-L_6kFMmFz{!eqD2xh_XPs86dIp`fYrxGu(zr{ql_g+v#e)Rq6+y!q|Ew<|ne1DFm;(JWE-hsKE za+2y-u4ry4Y)PxvyJyy?EWRL7rMyk<)-R_g(|-rg*_L{e^@Z8V_RqYp4hUAZZrwSF s`@`xNX1tHj$;_S`nIqNa;t+W6+R^i_YnNoX1O3L}>FVdQ&MBb@00!@bivR!s diff --git a/WinDirStat.Net.Wpf/Resources/FileIcons/UnknownSpace.png b/WinDirStat.Net.Wpf/Resources/FileIcons/UnknownSpace.png deleted file mode 100644 index d2f37587b70e325754e9b3bfc4fd0370001dd3c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 542 zcmV+(0^$9MP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00E9kL_t(IPnDCqN&`_4hR-f6Ay#>$EyR=t zK}0JNiAhW}AWH0f05K2XWglTX1uX)ixoBXqu!+SMYGa`&XeEsEpUY-*5(Ni-*xj?= ze`e;)5q3;XZ~3f%6|+bS&-mu+-^PO%bF46%-z9G;Ah&cuV)K@DLvHb$yu}mB<{K~z z@vp{IXgJEuHOZ;9Nz?%-C-6=ezsFo{M?_$34^>iq=XJA04uo@%;zo=1W6Aa03X=7&%kB%}zn}kRWLxOWQFdBxMb=u>X gDIL7{kLxVN4^+n75cX&YwEzGB07*qoM6N<$f_!<~2LJ#7 diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Close.png b/WinDirStat.Net.Wpf/Resources/Icons/Close.png deleted file mode 100644 index a360f9af7bd45d1798d89f16a118318646f4988b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 570 zcmV-A0>%A_P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00F8=L_t(IPmPkxE<;fmh4%wAZK(tU18*Ra zNQBO4i+TVN&tM`FV?&K1LWt5ZsDaCrR6=j6ieiYSC3;S;+8UZH|9_k+N70?E?3|N) z>%Z(JD(CfP80Bj_$}u}itSdW;mqQ=A7{W_*P*LHW6d8!ASoJWB+!kq*B8i^!kVFyOZ9fgvv-SJQxIt_OxZk6hUH(}0&%4-DCf z?CGxt|HF`Ge=(q^(!y_d4n%F;C?8FI!jK$DxXsuT#{FGkG^)4|{KneK45vgRF7>S_ zc_$UPO9k6^i;CR-8dFD#n3_sBwr0<9IUX1~z z>o1twPC7>rpxF~-bfPn1TNtW4;COz8Ar%GOaPe>)c%H_+s|S94voexL7^<(p z@#KIg3R#f}T9G>F!?C#?acWogTOj)^kbM1$$w6mZ(IX7Tci{eKTG;q=rvLx|07*qo IM6N<$g8Sd{Bme*a diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Cmd.png b/WinDirStat.Net.Wpf/Resources/Icons/Cmd.png deleted file mode 100644 index 0a653e55c5495512534f1e6fd8be71a6c909bb4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucLCF%=h?3y^w370~qEv>0#LT=By}Z;C1rt33 zJtM=93Yk-ZimrLOIEGmGADs}%b;v=$W%K*r`vjdhcCM6fS}yc4YN_mtlRN%&G_ks- zIo+E*PvigjhZTp+|3(z-i;!pde&3rE3VXeK--QgS{;>yv)FzPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00D_fL_t(IPsNc-O9D|ChL1Ad#_{fWM+Oz$ zwM`PdEJ9kfm__9xbCD%svWCwp;#=2NF;(#D1=}z2*2MCuh*+X4u=Can++C=Wh#ir<2s~;LvFVl zk|aSCMcT7ktq=qOX0sWS&o>olN95s0)F8Xvu0uQ~lZimBx`0p1<#MRh_OM$oBb`nY z$S3h=fN`x0T03pbEw>SBT!8I7VSHD>uv^5@c9Fh|5#TjSNU*up0&71L%vvLiZx=AW z$zyyyPbV<~-wMR$6~V0esKc+lJPC~O=aOLm;1In|MW4(XL$LY)ih4@F@GDR&3HW7W zeHAag0!`+yvvvt}txhk@>O{m?sZ^3`>SBM?EkIs5M|nx@^F4a_(@X%NTCJY&^7Z@n bj4<{Fr#^(#eA%>u00000NkvXXu0mjfBjMTK diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Copy.png b/WinDirStat.Net.Wpf/Resources/Icons/Copy.png deleted file mode 100644 index 5e88bb2537d12e39473df2d8a27271f3449e7b61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445 zcmV;u0Yd(XP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00AvYL_t(IPnD2CQiDJcMLCl9@)81!Y-Ap6{2s z)m&H`lRv)&GYDMQWtMj<(yivg%~*Sw-UvZ;^M{ljxwlKZ0D(d9p{6rmf<^`V6a-4p zQKP4VQNb!BNhQE!@U9pY?8fu>)~as)8G=1c1Y-?Wt-}J)O3920c6GmIBOVtwF3qnO z92f+{2FE~vKKUuRh;B945UgnfoH)Ch+XbdztE#3S1q9Q}nO$HC_L#}V n)Gjaui?uNspU=)GO5ixZEQLAVK5r;U00000NkvXXu0mjfJRP$^ diff --git a/WinDirStat.Net.Wpf/Resources/Icons/CopyPath.png b/WinDirStat.Net.Wpf/Resources/Icons/CopyPath.png deleted file mode 100644 index 891b7d4743d09dfae86defa79f2b9d702f253d40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmV<40U`d0P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00B-(L_t(IPwkOON&`_Cgx@K2<080pAue4C zohiXH2?qr07*qoM6N<$fk diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Cut.png b/WinDirStat.Net.Wpf/Resources/Icons/Cut.png deleted file mode 100644 index 6208549c99aa4faa8d83dea858cdc435558bfdef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 555 zcmV+`0@VG9P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00EmxL_t(IPnA-;P69y`-BKb3M0OjSjbFeg zY+++!L1UseZl#SHC`_~h2`Cz53lj?xLohaI426$GKt>@;Hfr49tK}2s6UH-}0Y&8D zNltdoojqsn++FE6N~Mx5mR;D09rfI6qgt(!a=9E8vJIH^p#qAJNT}dcDrOa11bJ!NKjfz}q)XlT|7eZdAqTy4W5LxI)&l zEEY>07eqkEOa=m71b9IH;*y&SqWnKx-0#LT=By}Z;C1rt33 zJtM=93Yk-Zik^A8IEGmGubmXhb;v=$)WS&i#a|-eF(gNyvV*zcv9nftxc1^E4eQE;B~Kv#m2?xgKPHc=2+W$9(z}#50MAl z{)zq(Ie9?6G5)Yd)!XK4LBF3ZXMOaa$EW!Dr(?U7*0oIpGSffps(hyuc~?zx#xp-% z`74iHCH&QNRwt@3U%oSOPu9KH3WoE1BEq(NvVFT;r))TnPjyoLPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00D$aL_t(IPmPm1Pr^_X$IswuLKs+F7#tmN z@Kq29N=VeGlVX&IK~y5L_?V5G36q0~F+PYc7!wv3gNljZbAS)vcVKYu@tpQnXm2(A zlYc_)J-=Uj+X8lpL?S_Ig^Hs5+atFB4h^}f=L`+ZuA?hiz}iU=chcjAi1*xLycJsH zE7W<&KNZEE#4$ql17YJG)h8d-i+6_sjL(G)5zkfxt_iSr@c^AG*9e;g3K%jh@S<8# z^gfPY+LXw)OBE+lMH?zxvlE5`Vl8s-*QR&Q9 zxO?G7yE-!h*Fy{SOe`#&xgCbsGb)pDhU)@rg%&;3W_~O53-fu~VR7qCo)wrmhGZ`r z!tYxlAh>I(jQ!KO|6wDBgg@KHse;bv75XRUJA;kTpo41tH#)?2=OKvSj`?Yu0`LPt WV}jzKLM%i80000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00Mx`~nCQ)$7fl9-aWEbh6$~qLvNscf0cBx}a~lJ7ya^p$R~VzTjLHb(wWYje zY*L>>b!5i7-{hC4d6Lg3zvr7m|3_e0KWZ|W>xg}^jv)5V*bt;{vmtdW7>m``uvn~( zg#}B)3}$ZrL-W-e&8UQT1q2bP@_ema;j1iH;aQgB*)m&UOJ$BNmRK%dC~>)bfy?Id zTrh;z&k9B?R-~9rrQ=kRAxUbV+#_i+x|c{0(Rc#e*`-1lK?On>z3C6phS@n52u38l zBaj0#LT=By}Z;C1rt33 zJtM=93Yk-Zid;Qi978PplNWGV$O(LyFT-=yPKURFF{VbME$jF@rjiC<-Vp0N{R0eU zmI7^A%O^6vV3;knqD+ca$xvcdZG?n_T|xo_LrCk_2c|Ohtv~}AJYD@<);T3K0RV4$ BJKz8S diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Expand.png b/WinDirStat.Net.Wpf/Resources/Icons/Expand.png deleted file mode 100644 index 3fb1d4347089c7873fbb32a92f9db0fd5db4e0c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 339 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucLCF%=h?3y^w370~qEv>0#LT=By}Z;C1rt33 zJtM=93Yk-ZiVl0aIEGmGCpR?qi`V?Cw|M^f|KG^>|KIyn|E;gS^w}n)%Yxz3pZ{0? z{Qn<+?$`hSN4NaX_pA8V?j^|XV0PH#|Bl#y|GyUU3-~p739~7rH=F#gx8uy%{r>;@ z>zn@Xw|ezaPRmz<;V;j%KmUQoPItfCSn?f6-RbG+f88oCwKC)07@&6;JYD@<);T3K0RT6@i*f(} diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Explore.png b/WinDirStat.Net.Wpf/Resources/Icons/Explore.png deleted file mode 100644 index b38a9353299d17981b34097f8d923a595971ce7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 265 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucLCF%=h?3y^w370~qEv>0#LT=By}Z;C1rt33 zJtM=93Yk-ZiYh%_978PplNU(*+4rJ=vEzU8LFtAFhE+V~44T_+{d!|>svz9zIMva7}ym0mCN#<|_)X9Ss>~v*k!c^1tPA z5Ie5!F3PNTz+#8U!-=~Yd@l$ztl`jNVgK<&gMo*KVRC-!<(=KzHv%2O;OXk;vd$@? F2>>Q~TDAZH diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Open.png b/WinDirStat.Net.Wpf/Resources/Icons/Open.png deleted file mode 100644 index f3cb889a1970700eec43077542be5c5887c8aaab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 519 zcmV+i0{H!jP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00DPNL_t(IPmPkXP69y`MfVf@3uC2{7(%QC z5sa<>U}a)uqJ>11sEA@9AP8t}Z)Z?Z5f$wyC>M5FP{a@L`rhsUfn9WOax>MrGjHCN zy83=!MCZ+qPT7wy_NyQ57oXv0A3jS9x<8)CMQ>SPeKCyY1^Jwu1+)w~O-=!gBsl@7 zadHf;q89?|i*L3ALp?$3(ISAKZ3l*OjHYD(&1?sTa)jo?yg7hB%MJ|X5Ze97fd66C z!y^J{Rd!(1_n{R$<^bODU+`v%#v}Mg-a+HegGRwKCQw6qzzBHbEC*+(L;-tLs%2W^ z5{Fz1)DSn!3SLj=;EGl;n~>p*RC;yPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00ELoL_t(IPlc1qN5gT<1uPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00J{fL_t(IPtB73OH*MK$M2u8etphj!aw4h{Yi zoS_2pMHRVx5ss^A4etK~?$+RgozG#FHv>YT;>6QHL!d-$Z-WbU+}J|Cpi=I@aV3Rn z_tGxh^;*FEtRF7eg#dk2?86#t^?gCDH-oNFR*b?$jGfOw7pucBU_3b`I;!{oFi`b4 z&7Xj6=o`UbQRn@P_UlbWPAo6r+xHZdw~f)N-U#^bkb{pw3>Pp60df}YI*pdg zDI9S}u-`HH+bGl>+J<6i9f+dU8$nagIQF#M-JPEYZ6Hi*B71U+CWJ-Jo)u>CtTOtM p+m(@-C^P!G&Zv5`j{ozJq+h05;)eS{9*F<|002ovPDHLkV1kV_M%@4a diff --git a/WinDirStat.Net.Wpf/Resources/Icons/PowerShellElevated.png b/WinDirStat.Net.Wpf/Resources/Icons/PowerShellElevated.png deleted file mode 100644 index 3dda9abae07f33a5bb6c62118eb0b11d46e21798..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 767 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00M7GL_t(IPtB6cPg6k@#_z(Fy68sN{tGS? zl!Wpsr3Il-jerXv#u6x`g2f^rSX5|1Kz6WDX;&s)AR)nkm?1nY;-k@kq9|&uJQ{3- zR6q>(^UT~EV5dt@ax!yg=J%cR-5KfsiTH9>sJk-Fc&668VX3umDQB6!?mg3AonvYB zA1LRUq2UuVT>H$7&LB&_vDmBPl0-nj+$qD|FT>UM8>U-7k>y^+spb`A++0R_V+aI- zgh0ZeLgHJ%R9!=gFyG$B^j8@?ItSJX{;t5+ztQ0@1b>9S?j6B1NO8P^u`v`-1x8F+ zEo;bW-$I3V1JO+xYtc=VbuTHfa}Qjjz{yoFkm>%>Ap{aDCp&UFwy5oOa3R~>RYW&r z%59W&Eh4R9eiyEOEnq%ow{4h&0Br_LZ3>*}iXfvYjB4+Su);->s-A;>tO~zG(xoZU zQFi+;4ORDR4E1v`mU?j9Y(r&nCeGP=FdK{tfvK4gP89bm@MQ%~sCYuw78L&}Io3Nz z&p2?n$OFmx6!J(MCc5L{vKwJ_v>@g}FM$D(N%m(*tnfo?8|CdQ{&l$yzf?XYV5wvh zGCK+RaV+HF801-9@D7LJd9(!2&;oh}Lpa|;U62r6x$3{bwYcB%P{5MKzXOMSv9LS4 zgpIx7_Kbrb78lS6fwYSQ@VOIrDoaHZkP60e#N3LMQXfiMM`39mf~9E?xwU;bR&;;Y zKM%TrUQ?bW67X4cWk%HtRa^Dm| x_mE&PkMT8i``?0qeR{p##gos~<-dd^{Q)cP-5t=bT_^wm002ovPDHLkV1jrOQ$qj% diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Properties.png b/WinDirStat.Net.Wpf/Resources/Icons/Properties.png deleted file mode 100644 index 512d9fda752f5d4eaf6c219fbdccf9e3e251e287..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 581 zcmV-L0=oT)P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00Fg0L_t(IPlb{@Pr^_bhWn2&(ZR(ZqLZ_1 z3=D+H#29B2F^+tee0WDWW1nZ`zIyh*Ep#n;Qn!NTqDFQi)C;684JkNJK!rpqUAJkP-cLBPMu3+Q>0px^IfZP|tP zLjs?TC)P7TgP{5NeLK7$9*ZLyi6R^hLpqUge00R7O#`Ezscgzju+QtY1cLAl91fy= TZo16M00000NkvXXu0mjfy14u0 diff --git a/WinDirStat.Net.Wpf/Resources/Icons/RecycleBin.png b/WinDirStat.Net.Wpf/Resources/Icons/RecycleBin.png deleted file mode 100644 index ea0f449e50737331bb7b210940aab5d93134a0fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 854 zcmV-c1F8IpP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00PEIL_t(IPi>M*PZLoXhWiId+#2^T!Hw?F zg@3?>OBSxh_ycSWmW9zM46RBF;Zh4odcTBVxmJ5`r?+W4rBiyP0!3&kmo`E}Ur(n) zs>U~Yb517beZDi_`9yzeR=4~}yR`Yl7h&zGOfkRe2;>u7o^l7{_6>KCDwOu`2uJ@G zfEzA4HXCKPkuU9m?BVc7`860zVa-Kj(-TH0&K<8gX)0gZr-W!n3WZXv(dt@eixn1P zli32J$qa+h#9MDLLZ>(I*6Q?7&o5wfOePlM9RL%Hw~lKksGXdmQmx^rdd&NXmq>S7Q{yu4@Z34|FIPG6{fgW9KYH-)|&u& zhJ8HX=4(IffjB&YaMkIhvy@EU5Mo^^loO41^?dOMURV-Xp;K7)vyfUDjDBTcbu(=M z9G(FF3m`Y}`U2tBygSWTz4tMMxX{Sk@BHYI`mpYc!nS5_1AIcPD*~{2{6RdN2=joa z8V2qt2dy)K2jevV?fGH=OSbh>0$34ZT@k>sD6JlKvK>wFTO?5k4C}(oT3VF^7Y2YscXh!2( z=VS_ZeRL!{HKVE#KzE3)C6T=BlS+p#W%3VaGP(R*Cga^8hZ__%Rv)3L`uh>8J~Z^I gDHePx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00E;(L_t(IPn}a+PQpMGWeF~UAC#B0JViug zDJ;PiC=@6`B}75=L(?U=1U@GXX^3e|j3LlZ{8nx!{|uNk6#Xox-ePMqXuUHAdvJC00IqX3Fm4o>f9s62W> zl?ETsS~ik~SR@*vMt7eAP_z|_rU+BOFZErNhco0m6J%EI$abeFKX}kO4(N`|wTpwx zb%Bnsiropyqd8RkKI2y@P)!+PoMM8~$V0yWjr&49NzJe@l9LyelE`#Js?YW4i6k2q9jW9 z$im1^2Z-+4&39XULod*4lj@vVemL%a15Z#nYA@j3ah zy50_qZp9ilqIFxYZc2gRXW9weyG8dY1vZdFp--4WA`kJ9d6EDC002ovPDHLkV1jp3 B?f?J) diff --git a/WinDirStat.Net.Wpf/Resources/Icons/RefreshSelected.png b/WinDirStat.Net.Wpf/Resources/Icons/RefreshSelected.png deleted file mode 100644 index 330765fff18b90b3734e31a3bd093ba2e8ef3351..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DjSK$uZf!>a)(C|2ScQ4*Y=R#Ki=l*&+$n3-3imzP?iV4`Q}^Zw|6po%O{7sn6_ z|73~21&?+y2$(Z`WLNmde^jB2Ipm-HjANWy>*5=-SL}GlaMXa=v8aN_LBph>OM$_I z=b6?VhMOx-Fgz6HkUP>aAviIyMcBbah|A@SK@)QaPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00GoVL_t(IPsLNqPQp+S?H@>DR3sV+0mH)w zimf7u|DvKq1?nq`4@8Y<+*HL!e5Jd)(eB(ytO<)QT(D(9QWh-S@d@MHQnV<>#EmC8 zNi)+q_s-li%wN$oK}7wt9_}cyx)vnSz45Gib`)@@6mTS-)y_FdY@a4p`cF$l5-m$l zpcNR=8za0ol>_#o4BXXQ9fvUH*vx@B@*wvMMX+rt^#c8I!m~$t@LyxWSqXZQFBR8% zR(2+kn=cg>V>DNzJ!uda;E9#p%R%54PeKvrJQ2F*h)GW~9W%t#IeV|te2tE6gMe>E z5<}Nz2ws-J6D5Kk{(v5s&0{$B`h|b~j67)7Q66Si+d1#&_yk1%byRQIyQiQ(62id#R*vd3Ut=uy8rI^CE y^#tDKYERlSVgHSm$s9IZ+X&yn53Bhr80H<`2tI7j7NCOw00000#LT=By}Z;C1rt33 zJtM=93Yk-Zik^A8IEGmGZ=K+qb=W|_t+wTo(4|>B%0zCj`V*|}=M;Ub`b&xBfirsS zGit@GE;xtpTqI#LF0jcavlfo&V2m+{r`*nyZ_xZ{qaz znscWzg~dGhRCFXqEGeUIiRk9sBRjtDl@eRC(N_NC%87SEo0lb6x>iehuKfMtOsL<& zXPVdA1zlS;majKzo0P1>&uqBY^UWql^@NJ1XJ5E3x_P_Y<#%_xJ=4YSEw5v7$IqYc zdya6II!`}goMLnA%eKPvGlV1$_PDRelmBkB?&>>E;r)f@nfLwbZ|7{Xzj1xzmz&K$ Rc!54<@O1TaS?83{1OVjgm}vk2 diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Save.png b/WinDirStat.Net.Wpf/Resources/Icons/Save.png deleted file mode 100644 index 5c5c63b0a58327940534a96e8605f95167be5437..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 499 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00Co3L_t(IPmR;fYQjJihT(IQf{T=f(lRE- zzbjBtucMnnp-?E)O0ZH1B8Uj0q9mv&ir4YAXW)!6-Hh-ppEr|HsaC6jSFKh-K?L%D zK;AbF2FT@ddV+5P zd|bwkPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00Ev!L_t(IPqmWUO9DX@#{H*y3yO#!2)fYy zA{#_^ETZj#iH2@LipFkbWx6)qFtaQ#We}B*W?7qML1_;~(OV!rb~+2&leu8f2R|5? z@0)YZ%qad<+o5BMBd*wzXa95F?N6KSB*weFl(a1`vJ>D<#GUrV-xIzRoUGh~#~6Oy z7@i^boO7L*Y`;saY{YQ*e=NB-NA!+NC}e9_=QRh zYdhumwd~KR8e{nOJ{oEoS}3uK*ecGOWQprhT+3D-Vl4ci!3<43wERc;O+R6(U!8k+ wV0`ND;mSs;P}!;aTlhy6^~yqNnWGenZ+UkSX&W(eV*mgE07*qoM6N<$g4Q?huK)l5 diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Settings.png b/WinDirStat.Net.Wpf/Resources/Icons/Settings.png deleted file mode 100644 index f1992b8eec22860015fc497859310dbc92d5c007..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 zcmV+j0{8uiP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00DSOL_t(IPmNK_O2beP%_sN?eu5hxf8e$& z5f>8N3L+v{Ul7#VS|YY;Ax01ig1QjwqOOFLAQlk}DO4;dks>BWa3OBYX3V)HdJU<~ zz~SCIbLKE}t`LpMscCU`ZeH`xo*;!>-?FrdTq;O)4)vf+Mzck0*}MS}U}ZgL-90?f z)=o(aXq^KjkgsnWl;12^#gbw{FtLDK*fv0p18M>7H?S9!0TA^1O>8rO8aUu$Rliph zU`~{Xk#`l<9v3I1kV3L;v7VZ!n~QJ91$i{)8qo0xmEsBrGg0 zrCEWCOg1OA?NT2`^C8 zT^iVP=%VScw`rOTi3MEOrFzRD`^9E&9P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00CG@L_t(IPlb|QQ-VMghWSbTXU$AXEdoqa z5h46SrF)z4)*A=>hKrLgw(iDK?aVu8FL<7_oLz;86t=KO=D`QeW^o3sr2ITubEf$~D>)GpeyM2-T*HHv*+ot7mdEPIm)9I|Q z0>DXK0?(bPR;y9-wRt%@1paiE0*AxlM<7_ORuYJBO~d4Z@x=dC04NK_aZLJ) z&IQBaC|7{&_j?IM)t)sjz|ispfRQYS`c$uT0VbXmFnG7yN#N;pqUvLn3vgYcK!ms3 ztppyAM|x0IE;v7ot3U*i&1NHksFm_P7j(N;Dqx*OIEo?(L@k%@xBz#|1gtxQ!!VRU zoU~ND<$_l0EfwU!Odx_tu~6Uw_DC=+1pf?(B@2QPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00DSOL_t(IPvucLPXa+0-Je2bZ6O5(4HXqy z&|zV1WoKdO53sQ$5jjN>)F^_>C4`vZ1`@gNQ&Blq5Q%}}xw9E0CW^+``I48+eDl5c zy_sSD5df?RbO`hd+!83EN8f`8b>TXewK0+FhiUYNV_vAw)0WvFQ|C7PSlqrAN!F{z zxKM_Jw#)`GU{ft3Ao0r+6SAi*3{$GqCB<@$&lju67RpHHib!S(NThNYybSTw>m!{l zqC0rS!e&TJ^3kB$@Cyd`%%InQMkZep#gpkY(UK^x)Na?x)ds#YAd?^4UGedV*dA?S zG#XFuA4_C;tL+GueLGB68w{2M=*?E_n)aYGSg@lvqj~@E{sTAhB!X8QPvs2bxeP<2 z(Lk+ML#0wdsZ>ItP(Uu1Lnf0!DwTrcI1*We*XxB=X9Si1+=-nZCjA!7y)sKcYVk-I`zk0000< KMNUMnLSTYIde_GQ diff --git a/WinDirStat.Net.Wpf/Resources/Icons/ShowTreemap.png b/WinDirStat.Net.Wpf/Resources/Icons/ShowTreemap.png deleted file mode 100644 index 79e1b8b75e2fe0599ce3348c3aac44ef6c9c52aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 785 zcmV+s1Md8ZP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02XvbSaefwW^{L9 za%BK;VQFr3E^cLXAT%y9Oz*}20007nNkl)@m`F&TH3_3MjTOT*GdK6%-@UhoTghz33&y0bd%H#wFKpg)|C8>k+s8S-@70jA zo$dSke$V-w&-tA5!@uSW!{HCX>U@W2#|y+By++ImBI*vpat*_g2%ByF5hQg-;CH^k zbdwV-*agZp7iWS^o#36Ppf`xPX9PZtHCYMMi@+EnXWPL2=fLL2V1B6qNM8!Nhrx^$ z=6taOv_=s53#5Mxeho@rVv-8Vz*__0>6_r5Q()&?bFW_8WL%kOE(RyyXb)ie$Q5w; zYH-e6u&@Gr@(moA04q;`T@i4zfUe00TYbW^-Uf|ZA!I9nwP8EBG8cUI!?;r_o{{Rx zDl;4G{|ZWrc54UDgIPJ?j)V5Qg~9KLR$lYKtp=0kfv)$`f;?J{_rdaG;KNs7l_;!$I&%f^g-mj9BH1It zCZ~YwisT%G2Z7IU+~`GI$EQ7OwLbBUiA7S%zbki*8Vxk|np?&=Bx6*Q0AIy%lc4mp zYR(q(-4-x=pd-~}z0*mFfL_hDP1n*NMx?yXplb`odrh#ewr-x%);CRdk6`q_|ARLS zUyFr!$v&|DwgE^ P00000NkvXXu0mjfFT-RT diff --git a/WinDirStat.Net.Wpf/Resources/Icons/Undo.png b/WinDirStat.Net.Wpf/Resources/Icons/Undo.png deleted file mode 100644 index 52123a26ee982eddb952069fd46c428ac03ba01c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 572 zcmV-C0>k}@P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;2FkAZe8V00FE?L_t(IPo0uoN&;~d#a)6+=%EkIY({4q zORQWDspWJHD1fdLsgzq#k!n^I+J zVvm0OR|J@B0?F4Uy;_%=-4Ih~2%M(C4Fqd}+rc2{8E}f^!~2kBe)a&CD`wJ?~sILg8$37qgkU(m8I# zWNEfeW8~_gZe%vIihwi$y-Y1c)(`c(XE%R}fHY(DGW*lasniE0ZXv~o7Bgo60000< KMNUMnLSTY^?CT5w diff --git a/WinDirStat.Net.Wpf/Resources/ImageResources.cs b/WinDirStat.Net.Wpf/Resources/ImageResources.cs deleted file mode 100644 index d206c66..0000000 --- a/WinDirStat.Net.Wpf/Resources/ImageResources.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Wpf.Resources { - public static class ImageResources { - - } -} diff --git a/WinDirStat.Net.Wpf/Services/ResourceImagesService.cs b/WinDirStat.Net.Wpf/Services/ResourceImagesService.cs deleted file mode 100644 index ea978dd..0000000 --- a/WinDirStat.Net.Wpf/Services/ResourceImagesService.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.IO; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Wpf.Services { - /// A service for image references. - public class ResourceImagesService : ImagesServiceBase { - - #region Constructors - - /// Constructs the . - public ResourceImagesService(IBitmapFactory bitmapFactory, - IUIService ui) - : base(bitmapFactory, - ui) - { - } - - #endregion - - #region ImagesServiceBase Implementation - - /// Loads the image resource with the specified path. - /// - /// The path of the image resource. - private IImage Load(string path) { - return BitmapFactory.FromResource(Path.Combine("Resources", path)); - } - - /// Loads the icon with the specified name. - /// - /// The name of the icon. - protected override IImage LoadIcon(string name) { - return Load(Path.Combine("Icons", name + ".png")); - } - - /// Loads the file icon with the specified name. - /// - /// The name of the file icon. - protected override IImage LoadFileIcon(string name) { - return Load(Path.Combine("FileIcons", name + ".png")); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/Structures/IWpfRelayCommand.cs b/WinDirStat.Net.Wpf/Services/Structures/IWpfRelayCommand.cs deleted file mode 100644 index 23abe96..0000000 --- a/WinDirStat.Net.Wpf/Services/Structures/IWpfRelayCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; -using System.Windows.Media; -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Wpf.Services.Structures { - public interface IWpfRelayCommand : IRelayUICommand { - - KeyGesture InputGesture { get; } - - ImageSource ImageSource { get; } - - } -} diff --git a/WinDirStat.Net.Wpf/Services/Structures/WpfImage.cs b/WinDirStat.Net.Wpf/Services/Structures/WpfImage.cs deleted file mode 100644 index aea080e..0000000 --- a/WinDirStat.Net.Wpf/Services/Structures/WpfImage.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Structures; -using WinDirStat.Net.Wpf.Utils; - -namespace WinDirStat.Net.Wpf.Services.Structures { - /// An implementation for a UI-independent WPF image. - public class WpfImage : IImage { - - #region Fields - - /// Gets the actual image object. - public ImageSource Source { get; } - - #endregion - - #region Constructors - - /// Constructs the . - public WpfImage(ImageSource source) { - Source = source; - } - - #endregion - - #region Properties - - /// Gets the actual image object. - object IImage.Source => Source; - - #endregion - } - - /// An implementation for a UI-independent WPF bitmap. - public class WpfBitmap : IBitmap { - - #region Fields - - /// Gets the actual bitmap object. - public BitmapSource Source { get; } - /// Gets the width of the bitmap. - public int Width { get; } - /// Gets the height of the bitmap. - public int Height { get; } - - #endregion - - #region Constructors - - /// Constructs the . - public WpfBitmap(BitmapSource source) { - Source = source; - Width = source.PixelWidth; - Height = source.PixelHeight; - } - - #endregion - - #region Properties - - /// Gets the size of the bitmap. - public Point2I Size => new Point2I(Width, Height); - /// Gets the bounds of the bitmap. - public Rectangle2I Bounds => new Rectangle2I(Width, Height); - /// Gets the actual image object. - object IImage.Source => Source; - - #endregion - } - - /// An implementation for a UI-independent WPF bitmap with writeable pixels. - public class WpfWriteableBitmap : IWriteableBitmap { - - #region Fields - - /// Gets the actual bitmap object. - public WriteableBitmap Source { get; } - /// Gets the width of the bitmap. - public int Width { get; } - /// Gets the height of the bitmap. - public int Height { get; } - /// Gets the service for invoking UI actions. - protected readonly IUIService ui; - - #endregion - - #region Constructors - - /// Constructs the . - public WpfWriteableBitmap(IUIService ui, WriteableBitmap source) { - Source = source; - Width = source.PixelWidth; - Height = source.PixelHeight; - this.ui = ui; - } - - #endregion - - #region Pixels - - /// Creates a new array of pixels for populating the bitmap. - public Rgba32Color[] CreatePixels() { - return new Rgba32Color[Width * Height * 4]; - } - /// Gets the bitmap's pixels. - public Rgba32Color[] GetPixels() { - Rgba32Color[] pixels = CreatePixels(); - ui.Invoke(() => Source.CopyPixels(pixels, Width * 4, 0)); - return pixels; - } - /// Sets the bitmap's pixels. - public void SetPixels(Rgba32Color[] pixels) { - ui.Invoke(() => Source.WritePixels(Bounds.ToWpfInt32Rect(), pixels, Stride, 0)); - } - /// Sets the bitmap's pixels. - public unsafe void SetPixels(Rgba32Color* pixels) { - ui.Invoke(() => Source.WritePixels(Bounds.ToWpfInt32Rect(), (IntPtr) pixels, BufferSize, Stride)); - } - - #endregion - - #region Properties - - /// Gets the stride for the bitmap. - public int Stride => Width * 4; - /// Gets the buffer size for the bitmap. - public int BufferSize => Width * Height * 4; - /// Gets the size of the bitmap. - public Point2I Size => new Point2I(Width, Height); - /// Gets the bounds of the bitmap. - public Rectangle2I Bounds => new Rectangle2I(Width, Height); - /// Gets the actual image object. - object IImage.Source => Source; - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/Structures/WpfRelayCommand.cs b/WinDirStat.Net.Wpf/Services/Structures/WpfRelayCommand.cs deleted file mode 100644 index 030cf9e..0000000 --- a/WinDirStat.Net.Wpf/Services/Structures/WpfRelayCommand.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using GalaSoft.MvvmLight.CommandWpf; -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Wpf.Services.Structures { - public class WpfRelayCommand : RelayCommand, IWpfRelayUICommand, IRelayCommand { - - #region Constructors - - /// Constructs the . - /// - /// - /// The execution logic. IMPORTANT: If the action causes a closure, you must set to true to avoid side effects. - /// - /// - /// If true, the target of the Action will be kept as a hard reference, which might cause a memory - /// leak. You should only set this parameter to true if the action is causing a closures. - /// See http://galasoft.ch/s/mvvmweakaction. - /// - /// - /// is null. - public WpfRelayCommand(Action execute, bool keepTargetAlive = false) - : base(execute, null, keepTargetAlive) - { - } - - /// Constructs the . - /// - /// - /// The execution logic. IMPORTANT: If the action causes a closure, you must set to true to avoid side effects. - /// - /// - /// The execution status logic. IMPORTANT: If the func causes a closure, you must set to true to avoid side effects. - /// - /// - /// If true, the target of the Action will be kept as a hard reference, which might cause a memory - /// leak. You should only set this parameter to true if the action is causing a closures. - /// See http://galasoft.ch/s/mvvmweakaction. - /// - /// - /// is null. - public WpfRelayCommand(Action execute, Func canExecute, bool keepTargetAlive = false) - : base(execute, canExecute, keepTargetAlive) - { - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/Structures/WpfRelayCommandInfo.cs b/WinDirStat.Net.Wpf/Services/Structures/WpfRelayCommandInfo.cs deleted file mode 100644 index 9279d98..0000000 --- a/WinDirStat.Net.Wpf/Services/Structures/WpfRelayCommandInfo.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Wpf.Services.Structures { - public class WpfRelayCommandInfo : IRelayCommandInfo { - - } -} diff --git a/WinDirStat.Net.Wpf/Services/Structures/WpfRelayUICommand.cs b/WinDirStat.Net.Wpf/Services/Structures/WpfRelayUICommand.cs deleted file mode 100644 index fcda4d1..0000000 --- a/WinDirStat.Net.Wpf/Services/Structures/WpfRelayUICommand.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; -using System.Windows.Media; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.ViewModel; - -namespace WinDirStat.Net.Wpf.Services.Structures { - public class WpfRelayUICommand : WpfRelayCommand, IWpfRelayCommand { - - #region Fields - - public string Text { get; } - public WpfImage Icon { get; } - public WpfShortcut Shortcut { get; } - - #endregion - - #region Constructors - - public WpfRelayUICommand(IRelayUICommandInfo info, Action execute, bool keepTargetAlive = false) - : this(info, execute, null, keepTargetAlive) - { - } - public WpfRelayUICommand(IRelayUICommandInfo info, Action execute, Func canExecute, - bool keepTargetAlive = false) - : base(execute, canExecute, keepTargetAlive) - { - Text = info.Text; - Icon = (WpfImage) info.Icon; - Shortcut = (WpfShortcut) info.Shortcut; - } - - #endregion - - #region Properties - - public KeyGesture InputGesture => Shortcut.Shortcut; - public ImageSource ImageSource => Icon.Source; - - IImage IRelayUICommand.Icon => Icon; - IShortcut IRelayUICommand.Shortcut => Shortcut; - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/Structures/WpfShortcut.cs b/WinDirStat.Net.Wpf/Services/Structures/WpfShortcut.cs deleted file mode 100644 index c3841ee..0000000 --- a/WinDirStat.Net.Wpf/Services/Structures/WpfShortcut.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Wpf.Services.Structures { - public class WpfShortcut : IShortcut { - - #region Fields - - /// The actual shortcut object. - public KeyGesture Shortcut { get; } - - #endregion - - #region Constructors - - public WpfShortcut(Key key) : this(key, ModifierKeys.None) { } - public WpfShortcut(Key key, string displayString) : this(key, ModifierKeys.None, displayString) { } - public WpfShortcut(Key key, ModifierKeys modifiers) { - Shortcut = new KeyGesture(key, modifiers); - } - public WpfShortcut(Key key, ModifierKeys modifiers, string displayString) { - Shortcut = new KeyGesture(key, modifiers, displayString); - } - - #endregion - - /// The actual shortcut object. - object IShortcut.Shortcut => Shortcut; - - /// Gets the display text for the shortcut. - public string DisplayText => Shortcut.GetDisplayStringForCulture(CultureInfo.CurrentCulture); - - /// Gets the display image for the shortcut. - public IImage DisplayImage => null; - } -} diff --git a/WinDirStat.Net.Wpf/Services/Structures/WpfUITimer.cs b/WinDirStat.Net.Wpf/Services/Structures/WpfUITimer.cs deleted file mode 100644 index 85ac84e..0000000 --- a/WinDirStat.Net.Wpf/Services/Structures/WpfUITimer.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Threading; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Wpf.Services.Structures { - /// A timer that runs its callbacks on the UI thread. - public class WpfUITimer : IUITimer { - - #region Fields - - /// The wrapped dispatcher timer. - private readonly DispatcherTimer dispatcherTimer; - /// The event handler callback constructed from the action. - private EventHandler handlerCallback; - /// The action used for the callback. - private Action callback; - - #endregion - - #region Constructors - - /// Constructs the see . - /// - /// The interval for the timer. - /// True if the timer runs at normal priority. - /// The callback on the timer tick event. - /// True if the timer should start running. - public WpfUITimer(TimeSpan interval, bool normalPriority, Action callback, bool start) { - this.callback = callback ?? throw new ArgumentNullException(nameof(callback)); - handlerCallback = (o, s) => callback(); - dispatcherTimer = new DispatcherTimer( - interval, - WpfUIService.GetPriority(normalPriority), - handlerCallback, - Application.Current.Dispatcher); - if (!start) - dispatcherTimer.Stop(); - } - - #endregion - - #region Properties - - /// Gets or sets the callback method for the timer. - public Action Callback { - get => callback; - set { - if (callback != value) { - callback = value ?? throw new ArgumentNullException(nameof(Callback)); - dispatcherTimer.Tick -= handlerCallback; - handlerCallback = (o, s) => callback(); - dispatcherTimer.Tick += handlerCallback; - } - } - } - /// Gets or sets the interval for the timer. - public TimeSpan Interval { - get => dispatcherTimer.Interval; - set => dispatcherTimer.Interval = value; - } - /// Gets or sets if the timer is running. - public bool IsRunning { - get => dispatcherTimer.IsEnabled; - set { - if (dispatcherTimer.IsEnabled != value) { - if (value) - dispatcherTimer.Start(); - else - dispatcherTimer.Stop(); - } - } - } - - #endregion - - #region Start/Stop - - /// Starts the timer. - public void Start() { - dispatcherTimer.Start(); - } - /// Stops the timer. - public void Stop() { - dispatcherTimer.Stop(); - } - /// Restarts the timer. - public void Restart() { - dispatcherTimer.Stop(); - dispatcherTimer.Start(); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/Structures/WpfWindow.cs b/WinDirStat.Net.Wpf/Services/Structures/WpfWindow.cs deleted file mode 100644 index c2710f3..0000000 --- a/WinDirStat.Net.Wpf/Services/Structures/WpfWindow.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Linq; -using System.Windows; -using System.Windows.Interop; -using WinDirStat.Net.Services.Structures; - -namespace WinDirStat.Net.Wpf.Services.Structures { - /// A WPF implementation of . - public class WpfWindow : IWindow { - - #region Fields - - /// Gets the actual Wpf window. - public Window Window { get; } - - #endregion - - #region Constructors - - /// Constructs the from a . - public WpfWindow(Window window) { - Window = window ?? throw new ArgumentNullException(nameof(window)); - } - - #endregion - - #region Properties - - /// Gets the window that owns this window. - public IWindow Owner { - get => Invoke(() => (Window.Owner != null ? new WpfWindow(Window.Owner) : null)); - } - /// Gets the children owned by this window. - IWindow[] IWindow.Children { - get => Invoke(() => Window.OwnedWindows.Cast().Select(w => (IWindow) new WpfWindow(w)).ToArray()); - } - /// Gets or sets the dialog result. - public bool DialogResult { - get => Invoke(() => Window.DialogResult.HasValue && Window.DialogResult.Value); - set => Invoke(() => Window.DialogResult = value); - } - /// Gets the handle for the window. - public IntPtr Handle => Invoke(() => new WindowInteropHelper(Window).Handle); - /// Gets the actual Wpf window. - object IWindow.Window => Window; - - #endregion - - #region Private Helpers - - /// Invokes the action on the dispatcher thread. - private void Invoke(Action callback) { - Window.Dispatcher.Invoke(callback); - } - - /// Gets the values from the dispatcher thread. - private T Invoke(Func callback) { - return Window.Dispatcher.Invoke(callback); - } - - #endregion - - #region Close - - /// Closes the window. - public void Close() { - Invoke(Window.Close); - } - - /// Called when the window is closed. - public event EventHandler Closed { - add => Invoke(() => Window.Closed += value); - remove => Invoke(() => Window.Closed -= value); - } - - #endregion - - #region Equals - - /// Gets if the two windows are referencing the same window. - /// - /// The window wrapper to compare. - /// True if the interfaces are referencing the same window. - public bool Equals(IWindow window) { - return Window == window?.Window; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/WpfBitmapFactory.cs b/WinDirStat.Net.Wpf/Services/WpfBitmapFactory.cs deleted file mode 100644 index 10ec3fe..0000000 --- a/WinDirStat.Net.Wpf/Services/WpfBitmapFactory.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.IO; -using System.Reflection; -using System.Windows; -using System.Windows.Interop; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Structures; -using WinDirStat.Net.Wpf.Services.Structures; -using WinDirStat.Net.Wpf.Utils; - -namespace WinDirStat.Net.Wpf.Services { - /// An service for creating and loading bitmaps. - public class WpfBitmapFactory : IBitmapFactory { - - #region Fields - - /// The service for performing UI actions such as dispatcher invoking. - private readonly IUIService ui; - - #endregion - - #region Constructors - - /// Constructs the . - public WpfBitmapFactory(IUIService ui) { - this.ui = ui; - } - - #endregion - - #region Create - - /// Creates a new writeable bitmap. - /// - /// The size of the bitmap. - /// The new writeable bitmap. - public IWriteableBitmap CreateBitmap(Point2I size) { - return ui.Invoke(() => new WpfWriteableBitmap(ui, - new WriteableBitmap(size.X, size.Y, 96, 96, PixelFormats.Bgra32, null))); - } - - #endregion - - #region From Source - - /// Loads a bitmap from the specified resource path. - /// - /// The resource path to load the bitmap from. - /// The assembly to load teh embedded resource from. - /// The loaded bitmap. - public IBitmap FromResource(string resourcePath, Assembly assembly = null) { - assembly = assembly ?? Assembly.GetCallingAssembly(); - return ui.Invoke(() => { - BitmapImage bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.UriSource = WpfUtils.MakePackUri(resourcePath, assembly); - bitmapImage.EndInit(); - bitmapImage.Freeze(); - return new WpfBitmap(bitmapImage); - }); - } - - /// Loads a bitmap from the specified file path. - /// - /// The file path to load the bitmap from. - /// The loaded bitmap. - public IBitmap FromFile(string filePath) { - return ui.Invoke(() => { - BitmapImage bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.UriSource = new Uri(filePath); - bitmapImage.EndInit(); - bitmapImage.Freeze(); - return new WpfBitmap(bitmapImage); - }); - } - - /// Loads a bitmap from the specified stream. - /// - /// The stream to load the bitmap from. - /// The loaded bitmap. - public IBitmap FromStream(Stream stream) { - return ui.Invoke(() => { - BitmapImage bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.StreamSource = stream; - bitmapImage.EndInit(); - bitmapImage.Freeze(); - return new WpfBitmap(bitmapImage); - }); - } - - /// Loads a bitmap from the specified icon handle. - /// - /// The handle of the icon to load. - /// The loaded bitmap. - public IBitmap FromHIcon(IntPtr hIcon) { - return ui.Invoke(() => { - return new WpfBitmap( - Imaging.CreateBitmapSourceFromHIcon( - hIcon, - Int32Rect.Empty, - BitmapSizeOptions.FromEmptyOptions())); - }); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/WpfClipboardService.cs b/WinDirStat.Net.Wpf/Services/WpfClipboardService.cs deleted file mode 100644 index 267b73a..0000000 --- a/WinDirStat.Net.Wpf/Services/WpfClipboardService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Windows; -using WinDirStat.Net.Services; - -namespace WinDirStat.Net.Wpf.Services { - /// The service for managing the clipboard state. - public class WpfClipboardService : IClipboardService { - - #region Text - - /// Gets the text assigned to the clipboard. - /// - /// A string if the clipboard has text assigned to it. - public string GetText() { - return Clipboard.GetText(); - } - /// Assigns text to the clipboard. - /// - /// The new text to assign to the clipboard. - public void SetText(string text) { - Clipboard.SetText(text); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/WpfUIService.cs b/WinDirStat.Net.Wpf/Services/WpfUIService.cs deleted file mode 100644 index df7cd3e..0000000 --- a/WinDirStat.Net.Wpf/Services/WpfUIService.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Threading; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Wpf.Services.Structures; - -namespace WinDirStat.Net.Wpf.Services { - /// A service for UI interactions. - public class WpfUIService : IUIService { - - #region Fields - - /// The UI dispatcher. - public Dispatcher Dispatcher { get; } - - #endregion - - #region Constructors - - /// Constructs the . - public WpfUIService() { - Dispatcher = Application.Current.Dispatcher; - } - - #endregion - - #region Dispatcher - - /// Invokes the action on the UI thread. - /// - /// The action to invoke. - public void Invoke(Action action) { - try { - Dispatcher.Invoke(action); - } - catch (TaskCanceledException) { } - } - - /// Invokes the function on the UI thread. - /// - /// The function to invoke. - /// The result of the function. - public T Invoke(Func action) { - return Dispatcher.Invoke(action); - } - - /// Invokes the action asynchronously on the UI thread. - /// - /// The action to invoke. - /// True if the action should use normal priority. - public void BeginInvoke(Action action, bool normalPriority) { - Dispatcher.BeginInvoke(action, GetPriority(normalPriority)); - } - - /// Checks if the current thread is the UI thread. - /// - /// True if the current thread is the UI thread. - public bool CheckAccess() { - return Dispatcher.CheckAccess(); - } - - #endregion - - #region Shutdown - - /// Shuts down the application. - public void Shutdown() { - Dispatcher.InvokeShutdown(); - } - - public event EventHandler ShuttingDown { - add => Dispatcher.ShutdownStarted += value; - remove => Dispatcher.ShutdownStarted -= value; - } - - #endregion - - #region Create Timer - - /// Creates a new stopped UI timer. - /// - /// The interval for the timer. - /// True if the timer runs at normal priority. - /// The callback on the timer tick event. - /// The newly created timer. - public IUITimer CreateTimer(TimeSpan interval, bool normalPriority, Action callback) { - return new WpfUITimer(interval, normalPriority, callback, false); - } - /// Creates a new running UI timer. - /// - /// The interval for the timer. - /// True if the timer runs at normal priority. - /// The callback on the timer tick event. - /// The newly created timer. - public IUITimer StartTimer(TimeSpan interval, bool normalPriority, Action callback) { - return new WpfUITimer(interval, normalPriority, callback, true); - } - - #endregion - - #region Static Helpers - - /// Gets the priorty as a . - public static DispatcherPriority GetPriority(bool normalPriority) { - return (normalPriority ? DispatcherPriority.Normal : DispatcherPriority.Background); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Services/WpfWindowDialogService.cs b/WinDirStat.Net.Wpf/Services/WpfWindowDialogService.cs deleted file mode 100644 index aeb5d57..0000000 --- a/WinDirStat.Net.Wpf/Services/WpfWindowDialogService.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System.Media; -using System.Windows; -using WinDirStat.Net.Model.Drives; -using WinDirStat.Net.Services; -using WinDirStat.Net.Services.Structures; -using WinDirStat.Net.Wpf.Windows; - -namespace WinDirStat.Net.Wpf.Services { - /// A service for launching dialogs and showing messages. - public class WpfWindowDialogService : IWindowDialogService { - - #region Fields - - /// The service for performing UI actions such as dispatcher invoking. - private readonly IUIService ui; - - #endregion - - #region Constructors - - /// Constructs the . - public WpfWindowDialogService(IUIService ui) { - this.ui = ui; - } - - #endregion - - #region Dialogs - - /// Shows the dialog for selecting paths to scan. - /// - /// The owner window for this dialog. - /// The selected root paths on success, otherwise null. - public DriveSelectResult ShowDriveSelect(IWindow owner) { - return ui.Invoke(() => { - return DriveSelectDialog.ShowDialog((Window) owner.Window); - }); - } - - /// Shows the folder browser dialog to select a folder. - /// - /// The owner window for this dialog. - /// The description to display. - /// True if the new folder button is present. - /// The currently selected path. Use an empty string for nothing. - /// The selected path on success, otherwise null. - public string ShowFolderBrowser(IWindow owner, string description, bool showNewFolder, string selectedPath = "") { - return ui.Invoke(() => { - FolderBrowserDialog dialog = new FolderBrowserDialog() { - Description = description, - ShowNewFolderButton = showNewFolder, - SelectedPath = selectedPath, - }; - bool? result = dialog.ShowDialog((Window) owner.Window); - if (result ?? false) { - return dialog.SelectedPath; - } - return null; - }); - } - - #endregion - - #region Messages - - /// Shows a message with no icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - public MessageResult ShowMessage(IWindow owner, string message, string title, MessageButton button = MessageButton.OK) { - return ui.Invoke(() => { - return (MessageResult) MessageBox.Show((Window) owner.Window, message, title, (MessageBoxButton) button); - }); - } - - /// Shows a message with an information icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - public MessageResult ShowInformation(IWindow owner, string message, string title, MessageButton button = MessageButton.OK) { - return ui.Invoke(() => { - SystemSounds.Asterisk.Play(); - return (MessageResult) MessageBox.Show((Window) owner.Window, message, title, (MessageBoxButton) button, MessageBoxImage.Information); - }); - } - - /// Shows a message with a question icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - public MessageResult ShowQuestion(IWindow owner, string message, string title, MessageButton button = MessageButton.OK) { - return ui.Invoke(() => { - SystemSounds.Asterisk.Play(); - return (MessageResult) MessageBox.Show((Window) owner.Window, message, title, (MessageBoxButton) button, MessageBoxImage.Question); - }); - } - - /// Shows a message with a warning icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - public MessageResult ShowWarning(IWindow owner, string message, string title, MessageButton button = MessageButton.OK) { - return ui.Invoke(() => { - SystemSounds.Exclamation.Play(); - return (MessageResult) MessageBox.Show((Window) owner.Window, message, title, (MessageBoxButton) button, MessageBoxImage.Warning); - }); - } - - /// Shows a message with an error icon. - /// - /// The owner window for this dialog message. - /// The text message. - /// The message window title. - /// The message buttons to display. - public MessageResult ShowError(IWindow owner, string message, string title, MessageButton button = MessageButton.OK) { - return ui.Invoke(() => { - SystemSounds.Hand.Play(); - return (MessageResult) MessageBox.Show((Window) owner.Window, message, title, (MessageBoxButton) button, MessageBoxImage.Error); - }); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Themes/Generic.xaml b/WinDirStat.Net.Wpf/Themes/Generic.xaml deleted file mode 100644 index 8756492..0000000 --- a/WinDirStat.Net.Wpf/Themes/Generic.xaml +++ /dev/null @@ -1,751 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/WinDirStat.Net.Wpf/Themes/SortView.xaml b/WinDirStat.Net.Wpf/Themes/SortView.xaml deleted file mode 100644 index 1cde7ed..0000000 --- a/WinDirStat.Net.Wpf/Themes/SortView.xaml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/WinDirStat.Net.Wpf/Utils/DependencyObjectExtensions.cs b/WinDirStat.Net.Wpf/Utils/DependencyObjectExtensions.cs deleted file mode 100644 index 7ee2051..0000000 --- a/WinDirStat.Net.Wpf/Utils/DependencyObjectExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; - -namespace WinDirStat.Net.Wpf.Utils { - public static class DependencyObjectExtensions { - - - public static bool IsValueUnset(this DependencyObject d, DependencyProperty dp) { - return d.ReadLocalValue(dp) == DependencyProperty.UnsetValue; - } - - public static bool IsValueUnsetAndNull(this DependencyObject d, DependencyProperty dp, object value) { - if (d.ReadLocalValue(dp) == DependencyProperty.UnsetValue) { - return (value == null || (value is string str && string.IsNullOrEmpty(str))); - } - return false; - } - } -} diff --git a/WinDirStat.Net.Wpf/Utils/WindowExtensions.cs b/WinDirStat.Net.Wpf/Utils/WindowExtensions.cs deleted file mode 100644 index 918940c..0000000 --- a/WinDirStat.Net.Wpf/Utils/WindowExtensions.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Interop; -using static WinDirStat.Net.Windows.Native.Win32; - -namespace WinDirStat.Net.Wpf.Utils { - public static class WindowExtensions { - - public static void ShowMaximizeMinimize(this Window window, bool maximize, bool minimize) { - IntPtr hwnd = new WindowInteropHelper(window).Handle; - WindowStyles styles = (WindowStyles) GetWindowLong(hwnd, WindowLongs.Style); - if (maximize) - styles |= WindowStyles.MaximizeBox; - else - styles &= ~WindowStyles.MaximizeBox; - if (minimize) - styles |= WindowStyles.MinimizeBox; - else - styles &= ~WindowStyles.MinimizeBox; - SetWindowLong(hwnd, WindowLongs.Style, (uint) styles); - } - - public static void ShowMaximize(this Window window, bool enabled) { - IntPtr hwnd = new WindowInteropHelper(window).Handle; - WindowStyles styles = (WindowStyles) GetWindowLong(hwnd, WindowLongs.Style); - if (enabled) - styles |= WindowStyles.MaximizeBox; - else - styles &= ~WindowStyles.MaximizeBox; - SetWindowLong(hwnd, WindowLongs.Style, (uint) styles); - } - - public static void ShowMinimize(this Window window, bool enabled) { - IntPtr hwnd = new WindowInteropHelper(window).Handle; - WindowStyles styles = (WindowStyles) GetWindowLong(hwnd, WindowLongs.Style); - if (enabled) - styles |= WindowStyles.MinimizeBox; - else - styles &= ~WindowStyles.MinimizeBox; - SetWindowLong(hwnd, WindowLongs.Style, (uint) styles); - } - } -} diff --git a/WinDirStat.Net.Wpf/Utils/WpfCasting.cs b/WinDirStat.Net.Wpf/Utils/WpfCasting.cs deleted file mode 100644 index 0dd1dea..0000000 --- a/WinDirStat.Net.Wpf/Utils/WpfCasting.cs +++ /dev/null @@ -1,135 +0,0 @@ -using WinDirStat.Net.Structures; - -using WpfColor = System.Windows.Media.Color; -using WpfPoint = System.Windows.Point; -using WpfSize = System.Windows.Size; -using WpfRect = System.Windows.Rect; -using WpfInt32Rect = System.Windows.Int32Rect; - -namespace WinDirStat.Net.Wpf.Utils { - /// Static extensions for casting between Wpf and WinDirStat.Net values. - public static class WpfCasting { - - #region Color - - /// Casts the to a . - public static WpfColor ToWpfColor(this Rgb24Color color) { - return WpfColor.FromRgb(color.R, color.G, color.B); - } - - /// Casts the to a . - public static WpfColor ToWpfColor(this Rgba32Color color) { - return WpfColor.FromArgb(color.A, color.R, color.G, color.B); - } - - /// Casts the to an . - public static Rgb24Color ToRgb24Color(this WpfColor color) { - return new Rgb24Color(color.R, color.G, color.B); - } - - /// Casts the to an . - public static Rgba32Color ToRgba32Color(this WpfColor color) { - return new Rgba32Color(color.R, color.G, color.B, color.A); - } - - #endregion - - #region Point - - /// Casts the to a . - public static WpfPoint ToWpfPoint(this Point2I point) { - return new WpfPoint(point.X, point.Y); - } - - /// Casts the to a . - public static WpfPoint ToWpfPoint(this Point2F point) { - return new WpfPoint(point.X, point.Y); - } - - /// Casts the to a . - public static Point2I ToPoint2I(this WpfPoint point) { - return new Point2I((int) point.X, (int) point.Y); - } - - /// Casts the to a . - public static Point2F ToPoint2F(this WpfPoint point) { - return new Point2F((float) point.X, (float) point.Y); - } - - #endregion - - #region Size - - /// Casts the to a . - public static WpfSize ToWpfSize(this Point2I point) { - return new WpfSize(point.X, point.Y); - } - - /// Casts the to a . - public static WpfSize ToWpfSize(this Point2F point) { - return new WpfSize(point.X, point.Y); - } - - /// Casts the to a . - public static Point2I ToPoint2I(this WpfSize size) { - return new Point2I((int) size.Width, (int) size.Height); - } - - /// Casts the to a . - public static Point2F ToPoint2F(this WpfSize size) { - return new Point2F((float) size.Width, (float) size.Height); - } - - #endregion - - #region Rect - - /// Casts the to a . - public static WpfRect ToWpfRect(this Rectangle2S rect) { - return new WpfRect(rect.X, rect.Y, rect.Width, rect.Height); - } - - /// Casts the to a . - public static WpfRect ToWpfRect(this Rectangle2I rect) { - return new WpfRect(rect.X, rect.Y, rect.Width, rect.Height); - } - - /// Casts the to a . - public static Rectangle2S ToRectangle2S(this WpfRect rect) { - return new Rectangle2S((int) rect.X, (int) rect.Y, - (int) rect.Width, (int) rect.Height); - } - - /// Casts the to a . - public static Rectangle2I ToRectangle2I(this WpfRect rect) { - return new Rectangle2I((int) rect.X, (int) rect.Y, - (int) rect.Width, (int) rect.Height); - } - - #endregion - - #region Int32Rect - - /// Casts the to a . - public static WpfInt32Rect ToWpfInt32Rect(this Rectangle2S rect) { - return new WpfInt32Rect(rect.X, rect.Y, rect.Width, rect.Height); - } - - /// Casts the to a . - public static WpfInt32Rect ToWpfInt32Rect(this Rectangle2I rect) { - return new WpfInt32Rect(rect.X, rect.Y, rect.Width, rect.Height); - } - - /// Casts the to a . - public static Rectangle2S ToRectangle2S(this WpfInt32Rect rect) { - return new Rectangle2S(rect.X, rect.Y, rect.Width, rect.Height); - } - - /// Casts the to a . - public static Rectangle2I ToRectangle2I(this WpfInt32Rect rect) { - return new Rectangle2I(rect.X, rect.Y, rect.Width, rect.Height); - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Utils/WpfExtensions.cs b/WinDirStat.Net.Wpf/Utils/WpfExtensions.cs deleted file mode 100644 index 169d479..0000000 --- a/WinDirStat.Net.Wpf/Utils/WpfExtensions.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using System.Windows; -using System.Windows.Controls; -using System.Windows.Navigation; -using System.Reflection; -using System.IO.Packaging; -using System.Windows.Markup; -using System.IO; -using System.ComponentModel; - -namespace WinDirStat.Net.Wpf.Utils { - public static class WpfExtensions { - /*/// Fix the VS designer being a steaming pile of garbage. - /// - /// - /// - /// - /// - /// Source - /// - public static void LoadViewFromUri(this UserControl userControl, string baseUri) { - Uri resourceLocater = new Uri(baseUri, UriKind.Relative); - PackagePart exprCa = (PackagePart) typeof(Application).GetMethod("GetResourceOrContentPart", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { resourceLocater }); - Stream stream = exprCa.GetStream(); - Uri uri = new Uri((Uri) typeof(BaseUriHelper).GetProperty("PackAppBaseUri", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null, null), resourceLocater); - ParserContext parserContext = new ParserContext { - BaseUri = uri - }; - typeof(XamlReader).GetMethod("LoadBaml", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { stream, parserContext, userControl, true }); - }*/ - - /// Fix the VS designer being a steaming pile of garbage. - /// - /// - /// - /// True if the design uri was loaded - /// - /// - /// Improved From: - /// Source - /// - public static bool DesignerInitializeComponent(this UserControl userControl, string path) { - if (DesignerProperties.GetIsInDesignMode(userControl)) { - Type type = userControl.GetType(); - Assembly assembly = type.Assembly; - string baseUri = $"/{assembly.GetName().Name};component/{path}/{type.Name}.xaml"; - - Uri resourceLocater = new Uri(baseUri, UriKind.Relative); - PackagePart exprCa = (PackagePart) typeof(Application).GetMethod("GetResourceOrContentPart", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { resourceLocater }); - Stream stream = exprCa.GetStream(); - Uri uri = new Uri((Uri) typeof(BaseUriHelper).GetProperty("PackAppBaseUri", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null, null), resourceLocater); - ParserContext parserContext = new ParserContext { - BaseUri = uri, - }; - typeof(XamlReader).GetMethod("LoadBaml", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { stream, parserContext, userControl, true }); - return true; - } - return false; - } - } -} diff --git a/WinDirStat.Net.Wpf/Utils/WpfUtils.cs b/WinDirStat.Net.Wpf/Utils/WpfUtils.cs deleted file mode 100644 index 4e26232..0000000 --- a/WinDirStat.Net.Wpf/Utils/WpfUtils.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace WinDirStat.Net.Wpf.Utils { - public static class WpfUtils { - - /// Creates a pack Uri for loading resource images. - public static Uri MakePackUri(string resourcePath, Assembly assembly = null) { - assembly = assembly ?? Assembly.GetCallingAssembly(); - // Pull out the short name. - string assemblyShortName = assembly.ToString().Split(',')[0]; - string uriString = $"pack://application:,,,/{assemblyShortName};component/{resourcePath}"; - return new Uri(uriString); - } - } -} diff --git a/WinDirStat.Net.Wpf/ViewModel/ViewModelLocator.cs b/WinDirStat.Net.Wpf/ViewModel/ViewModelLocator.cs deleted file mode 100644 index 8fa0512..0000000 --- a/WinDirStat.Net.Wpf/ViewModel/ViewModelLocator.cs +++ /dev/null @@ -1,79 +0,0 @@ -/* - In App.xaml: - - - - - In the View: - DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}" - - You can also use Blend to do all this with the tool's support. - See http://www.galasoft.ch/mvvm -*/ - -using GalaSoft.MvvmLight; -using GalaSoft.MvvmLight.Ioc; -using CommonServiceLocator; -using WinDirStat.Net.ViewModel; -using WinDirStat.Net.Rendering; -using WinDirStat.Net.Services; -using WinDirStat.Net.Wpf.Services; -using WinDirStat.Net.Windows.Services; - -namespace WinDirStat.Net.Wpf.ViewModel { - /// - /// This class contains static references to all the view models in the - /// application and provides an entry point for the bindings. - /// - public class ViewModelLocator { - /// Initializes the ViewModelLocator class. - static ViewModelLocator() { - ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); - - ////if (ViewModelBase.IsInDesignModeStatic) - ////{ - //// // Create design time view services and models - //// SimpleIoc.Default.Register(); - ////} - ////else - ////{ - //// // Create run time view services and models - //// SimpleIoc.Default.Register(); - ////} - - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - SimpleIoc.Default.Register(); - } - - /// Initializes a new instance of the ViewModelLocator class. - public ViewModelLocator() { - - } - - public MainViewModel Main => ServiceLocator.Current.GetInstance(); - public DriveSelectViewModel DriveSelect => ServiceLocator.Current.GetInstance(); - public ConfigureViewModel Configure => ServiceLocator.Current.GetInstance(); - /*public TreemapRendererFactory TreemapFactory => ServiceLocator.Current.GetInstance(); - - public TreemapRenderer CreateTreemap() { - return TreemapFactory.Create(); - }*/ - - public static void Cleanup() { - ServiceLocator.Current.GetInstance().Dispose(); - } - } -} \ No newline at end of file diff --git a/WinDirStat.Net.Wpf/WinDirStat.Net.Wpf.csproj b/WinDirStat.Net.Wpf/WinDirStat.Net.Wpf.csproj deleted file mode 100644 index bb1b69c..0000000 --- a/WinDirStat.Net.Wpf/WinDirStat.Net.Wpf.csproj +++ /dev/null @@ -1,317 +0,0 @@ - - - - - Debug - AnyCPU - {BF8C1ACF-CCB6-4CAD-BDB9-A99475606605} - WinExe - WinDirStat.Net.Wpf - WinDirStat.Net - v4.6.2 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - true - true - - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - latest - true - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - latest - true - - - App.ico - - - Properties\App.manifest - - - - - - - - - - - - 4.0 - - - - - - - - - MSBuild:Compile - Designer - - - - - - - - - - - - - - - - - - GraphView.xaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DriveSelectDialog.xaml - - - - ConfigureDialog.xaml - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - App.xaml - Code - - - MainWindow.xaml - Code - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - - - Code - - - - - - - - - {7da5a107-b474-4ac0-b861-63a489db0c02} - FunctionalFun.UI.Behaviors - - - {0ed71f8b-0797-468b-8420-2e2879da2302} - WinDirStat.Net.Base - - - {6416aa44-0296-4ff8-b408-a39a6c80dc2b} - WinDirStat.Net.Windows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5.4.1.1 - - - 1.0.0 - - - 1.0.0 - - - 1.6.2 - - - - \ No newline at end of file diff --git a/WinDirStat.Net.Wpf/Windows/ConfigureDialog.xaml b/WinDirStat.Net.Wpf/Windows/ConfigureDialog.xaml deleted file mode 100644 index 1592433..0000000 --- a/WinDirStat.Net.Wpf/Windows/ConfigureDialog.xaml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/WinDirStat.Net.Wpf/Windows/ConfigureDialog.xaml.cs b/WinDirStat.Net.Wpf/Windows/ConfigureDialog.xaml.cs deleted file mode 100644 index 64d0a73..0000000 --- a/WinDirStat.Net.Wpf/Windows/ConfigureDialog.xaml.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; -using WinDirStat.Net.Wpf.Utils; - -namespace WinDirStat.Net.Wpf.Windows { - /// - /// Interaction logic for ConfigureDialog.xaml - /// - public partial class ConfigureDialog : Window { - public ConfigureDialog() { - InitializeComponent(); - } - - #region Properties - - /// Gets the . - //public ConfigureViewModel ViewModel => DataContext as ConfigureViewModel; - - #endregion - - #region Event Handlers - - private void OnLoaded(object sender, RoutedEventArgs e) { - //ViewModel.WindowOwner = this; - } - - private void OnSourceInitialized(object sender, EventArgs e) { - this.ShowMaximizeMinimize(false, false); - } - - private void OnOK(object sender, RoutedEventArgs e) { - DialogResult = true; - } - - #endregion - } -} diff --git a/WinDirStat.Net.Wpf/Windows/DriveSelectDialog.xaml b/WinDirStat.Net.Wpf/Windows/DriveSelectDialog.xaml deleted file mode 100644 index 462f817..0000000 --- a/WinDirStat.Net.Wpf/Windows/DriveSelectDialog.xaml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -