├── .gitattributes ├── .gitignore ├── AntDesignSample ├── AntDesignSample.csproj ├── App.xaml ├── App.xaml.cs ├── AssemblyInfo.cs ├── MainWindow.xaml └── MainWindow.xaml.cs ├── AntWpf.sln ├── AntWpf ├── AntWpf - Backup.csproj ├── AntWpf.csproj ├── Behaviors │ ├── PasswordBoxBehavior.cs │ ├── StylizedBehaviorCollection.cs │ ├── StylizedBehaviors.cs │ └── VisibilityBehavior.cs ├── ColorPalette.cs ├── Controls │ ├── AntIcon.cs │ ├── AntIconDataFactory.cs │ ├── AntIconKey.cs │ ├── Border.cs │ ├── BorderStyle.cs │ ├── Button.cs │ ├── Helpers │ │ ├── Control.cs │ │ ├── Input.cs │ │ ├── ProgressAssist.cs │ │ └── TreeHelper.cs │ ├── ISpinable.cs │ ├── Icon.cs │ ├── Shapes.cs │ ├── Sizes.cs │ ├── Switch.cs │ └── Utils │ │ ├── CornerRadiusUtil.cs │ │ ├── DoubleUtil.cs │ │ ├── DpiUtil.cs │ │ ├── RectUtil.cs │ │ ├── Spinner.cs │ │ ├── ThicknessUtil.cs │ │ └── UIElementUtil.cs ├── Converters │ ├── ArcEndPointConverter.cs │ ├── ArcSizeConverter.cs │ ├── ArithmeticConverter.cs │ ├── DoubleToCornerRadiusConverter.cs │ ├── DoubleToThicknessMultiConverter.cs │ ├── LessThanConverter.cs │ ├── LocalEx.cs │ ├── MathConverter.cs │ ├── StartPointConverter.cs │ ├── ThicknessReverseConverter.cs │ └── ThicknessToDoubleConverter.cs ├── LICENSE.txt ├── README.md ├── Styles │ ├── Animations.xaml │ ├── AntIcon.xaml │ ├── AntIcons.xaml │ ├── CheckBox.xaml │ ├── ComboBox.xaml │ ├── Control.xaml │ ├── Controls.xaml │ ├── Input.xaml │ ├── PasswordBox.xaml │ ├── ProgressBar.xaml │ ├── RadioButton.xaml │ ├── Slider.xaml │ ├── TextBox.xaml │ └── Theme.xaml ├── Themes │ ├── Button.xaml │ └── Switch.xaml ├── ant_wpf.ico ├── images │ ├── buttons.png │ ├── check_radios.png │ ├── icons.png │ ├── inputs.png │ ├── logos_ant-design.png │ └── progress_bar.png └── logos_ant-design.png ├── README.md └── logos_ant-design.png /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /AntDesignSample/AntDesignSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net6.0-windows 6 | enable 7 | true 8 | AnyCPU;x86 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /AntDesignSample/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /AntDesignSample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace AntDesignSample 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AntDesignSample/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /AntDesignSample/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /AntDesignSample/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | using AntWpf.Controls; 18 | 19 | namespace AntDesignSample 20 | { 21 | /// 22 | /// Interaction logic for MainWindow.xaml 23 | /// 24 | public partial class MainWindow : Window 25 | { 26 | public MainWindow() 27 | { 28 | InitializeComponent(); 29 | } 30 | ObservableCollection iconsCollection = new(); 31 | public override void OnApplyTemplate() 32 | { 33 | base.OnApplyTemplate(); 34 | 35 | 36 | foreach (var animalValue in Enum.GetValues()) 37 | { 38 | iconsCollection.Add(animalValue); 39 | } 40 | iconsList.ItemsSource = iconsCollection; 41 | } 42 | 43 | 44 | private void iconSearchBox_TextChanged(object sender, TextChangedEventArgs e) 45 | { 46 | var key = iconSearchBox.Text; 47 | 48 | var view = CollectionViewSource.GetDefaultView(iconsCollection); 49 | 50 | view.Filter = (o) => 51 | { 52 | if (string.IsNullOrEmpty(key)) 53 | return true; 54 | 55 | if (o is AntIconKey iconKey) 56 | { 57 | return iconKey.ToString().ToLower().Contains(key.ToLower()); 58 | } 59 | return false; 60 | }; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /AntWpf.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33103.184 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntWpf", "AntWpf\AntWpf.csproj", "{3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntDesignSample", "AntDesignSample\AntDesignSample.csproj", "{E9120D98-63D7-4773-99C4-DFAB3F3D6450}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x86 = Debug|x86 14 | Release|Any CPU = Release|Any CPU 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}.Debug|x86.ActiveCfg = Debug|x86 21 | {3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}.Debug|x86.Build.0 = Debug|x86 22 | {3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}.Release|x86.ActiveCfg = Release|x86 25 | {3742B06E-2FF9-4E45-9E0F-E6A5481D02B0}.Release|x86.Build.0 = Release|x86 26 | {E9120D98-63D7-4773-99C4-DFAB3F3D6450}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {E9120D98-63D7-4773-99C4-DFAB3F3D6450}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {E9120D98-63D7-4773-99C4-DFAB3F3D6450}.Debug|x86.ActiveCfg = Debug|x86 29 | {E9120D98-63D7-4773-99C4-DFAB3F3D6450}.Debug|x86.Build.0 = Debug|x86 30 | {E9120D98-63D7-4773-99C4-DFAB3F3D6450}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {E9120D98-63D7-4773-99C4-DFAB3F3D6450}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {E9120D98-63D7-4773-99C4-DFAB3F3D6450}.Release|x86.ActiveCfg = Release|x86 33 | {E9120D98-63D7-4773-99C4-DFAB3F3D6450}.Release|x86.Build.0 = Release|x86 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {F33C3515-0B6F-4879-A59D-D3503A9A8C84} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /AntWpf/AntWpf - Backup.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0-windows 5 | enable 6 | true 7 | ant_wpf.ico 8 | True 9 | logos_ant-design.png 10 | https://github.com/Mumtozbekov/AntWpf 11 | MIT 12 | README.md 13 | 1.0.0.0 14 | 1.0.1 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | True 25 | \ 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /AntWpf/AntWpf.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 1.0.5 5 | AnyCPU;x86 6 | 7 | 8 | 9 | net6.0-windows 10 | enable 11 | true 12 | ant_wpf.ico 13 | True 14 | logos_ant-design.png 15 | https://github.com/Mumtozbekov/AntWpf 16 | README.md 17 | 1.0.2.0 18 | 1.0.2.0 19 | git 20 | MIT 21 | $(AssemblyName)Mumtozbekov 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | True 41 | \ 42 | 43 | 44 | True 45 | \ 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /AntWpf/Behaviors/PasswordBoxBehavior.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Behaviors 2 | { 3 | using AntWpf.Controls; 4 | 5 | using Microsoft.Xaml.Behaviors; 6 | 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Windows; 10 | using System.Windows.Controls; 11 | using System.Windows.Controls.Primitives; 12 | using System.Windows.Documents; 13 | 14 | [TemplatePart(Name = PART_TextBox, Type = typeof(TextBox))] 15 | [TemplatePart(Name = PART_Eye, Type = typeof(ToggleButton))] 16 | public class PasswordBoxBehavior : Behavior 17 | { 18 | #region Fields 19 | 20 | private const string PART_TextBox = "PART_TextBox"; 21 | 22 | private const string PART_Eye = "PART_Eye"; 23 | 24 | private static MethodInfo select; 25 | 26 | private static PropertyInfo selection; 27 | 28 | #endregion 29 | 30 | #region Private Attached Properties 31 | 32 | private static readonly DependencyProperty TextBoxProperty = 33 | DependencyProperty.RegisterAttached("TextBox", typeof(TextBox), typeof(PasswordBoxBehavior), new PropertyMetadata(null)); 34 | 35 | private static TextBox GetTextBox(DependencyObject obj) 36 | { 37 | return (TextBox)obj.GetValue(TextBoxProperty); 38 | } 39 | 40 | private static void SetTextBox(DependencyObject obj, TextBox value) 41 | { 42 | obj.SetValue(TextBoxProperty, value); 43 | } 44 | 45 | #endregion 46 | 47 | #region Constructors 48 | 49 | static PasswordBoxBehavior() 50 | { 51 | select = typeof(PasswordBox).GetMethod("Select", BindingFlags.Instance | BindingFlags.NonPublic); 52 | selection = typeof(PasswordBox).GetProperty("Selection", BindingFlags.NonPublic | BindingFlags.Instance); 53 | } 54 | 55 | #endregion 56 | 57 | #region Overrides 58 | 59 | protected override void OnAttached() 60 | { 61 | AssociatedObject.Loaded += OnLoaded; 62 | AssociatedObject.GotFocus += OnGotFocus; 63 | AssociatedObject.PasswordChanged += OnPasswordChanged; 64 | 65 | base.OnAttached(); 66 | } 67 | 68 | protected override void OnDetaching() 69 | { 70 | AssociatedObject.Loaded -= OnLoaded; 71 | AssociatedObject.GotFocus -= OnGotFocus; 72 | AssociatedObject.PasswordChanged -= OnPasswordChanged; 73 | 74 | if (Input.GetEyeable(AssociatedObject)) 75 | { 76 | AssociatedObject.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(OnEyeClick)); 77 | } 78 | 79 | base.OnDetaching(); 80 | } 81 | 82 | #endregion 83 | 84 | #region Private Methods 85 | 86 | /// 87 | /// Get the insertion position index of the caret. 88 | /// 89 | private static int GetCaretIndex(TextSelection selection) 90 | { 91 | if (selection == null) return 0; 92 | 93 | var tTextRange = selection.GetType().GetInterfaces().FirstOrDefault(i => i.Name == "ITextRange"); 94 | var oStart = tTextRange?.GetProperty("Start")?.GetGetMethod()?.Invoke(selection, null); 95 | var value = oStart?.GetType().GetProperty("Offset", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(oStart, null) as int?; 96 | 97 | return value.GetValueOrDefault(0); 98 | } 99 | 100 | /// 101 | /// Set the insertion position index of the caret. 102 | /// 103 | private static void SetCaretIndex(object obj, int index) 104 | { 105 | select.Invoke(obj, new object[] { index, 0 }); 106 | } 107 | 108 | private static void OnLoaded(object sender, RoutedEventArgs e) 109 | { 110 | var passwordBox = (PasswordBox)sender; 111 | var password = passwordBox.Password; 112 | 113 | if (!string.IsNullOrEmpty(password)) 114 | { 115 | Input.SetPassword(passwordBox, password); 116 | SetCaretIndex(passwordBox, password.Length); 117 | } 118 | 119 | if (Input.GetEyeable(passwordBox)) 120 | { 121 | SetTextBox(passwordBox, passwordBox.FindChild(PART_TextBox)); 122 | passwordBox.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(OnEyeClick)); 123 | } 124 | } 125 | 126 | private static void OnEyeClick(object sender, RoutedEventArgs e) 127 | { 128 | var passwordBox = (PasswordBox)sender; 129 | TextBox textBox; 130 | 131 | if (!(e.OriginalSource is ToggleButton button) || button.Name != PART_Eye || 132 | (textBox = GetTextBox(passwordBox)) == null) 133 | { 134 | return; 135 | } 136 | 137 | e.Handled = true; 138 | 139 | if (button.IsChecked.GetValueOrDefault()) 140 | { 141 | textBox.CaretIndex = GetCaretIndex(selection?.GetValue(passwordBox, null) as TextSelection); 142 | textBox.Focus(); 143 | } else 144 | { 145 | SetCaretIndex(passwordBox, textBox.CaretIndex); 146 | passwordBox.Focus(); 147 | } 148 | } 149 | 150 | private static void OnGotFocus(object sender, RoutedEventArgs e) 151 | { 152 | if (e.OriginalSource is PasswordBox passwordBox) 153 | { 154 | TextBox textBox; 155 | 156 | if (Input.GetEyeable(passwordBox) && 157 | (textBox = GetTextBox(passwordBox)) != null && 158 | textBox.Visibility == Visibility.Visible) 159 | { 160 | textBox.Focus(); 161 | } 162 | } 163 | } 164 | 165 | private static void OnPasswordChanged(object sender, RoutedEventArgs e) 166 | { 167 | var passwordBox = (PasswordBox)sender; 168 | var password = passwordBox.Password; 169 | 170 | // Sync password 171 | if (password != Input.GetPassword(passwordBox)) 172 | { 173 | Input.SetPassword(passwordBox, password); 174 | } 175 | } 176 | 177 | #endregion 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /AntWpf/Behaviors/StylizedBehaviorCollection.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Behaviors 2 | { 3 | using System.Windows; 4 | 5 | using Microsoft.Xaml.Behaviors; 6 | 7 | /// 8 | /// From https://github.com/MahApps/MahApps.Metro/tree/1.6.1/src/MahApps.Metro/Behaviours/StylizedBehaviorCollection.cs 9 | /// 10 | public class StylizedBehaviorCollection : FreezableCollection 11 | { 12 | protected override Freezable CreateInstanceCore() 13 | { 14 | return new StylizedBehaviorCollection(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AntWpf/Behaviors/StylizedBehaviors.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Behaviors 2 | { 3 | using System.Windows; 4 | 5 | using Microsoft.Xaml.Behaviors; 6 | 7 | /// 8 | /// From https://github.com/MahApps/MahApps.Metro/tree/1.6.1/src/MahApps.Metro/Behaviours/StylizedBehaviors.cs 9 | /// 10 | public class StylizedBehaviors 11 | { 12 | #region Properties 13 | 14 | public static readonly DependencyProperty BehaviorsProperty = DependencyProperty.RegisterAttached( 15 | "Behaviors", 16 | typeof(StylizedBehaviorCollection), 17 | typeof(StylizedBehaviors), 18 | new PropertyMetadata(null, OnBehaviorsChanged)); 19 | 20 | public static StylizedBehaviorCollection GetBehaviors(DependencyObject obj) 21 | { 22 | return (StylizedBehaviorCollection)obj.GetValue(BehaviorsProperty); 23 | } 24 | 25 | public static void SetBehaviors(DependencyObject obj, StylizedBehaviorCollection value) 26 | { 27 | obj.SetValue(BehaviorsProperty, value); 28 | } 29 | 30 | public static readonly DependencyProperty OriginalBehaviorProperty = DependencyProperty.RegisterAttached( 31 | "OriginalBehavior", 32 | typeof(Behavior), 33 | typeof(StylizedBehaviors), 34 | new UIPropertyMetadata(null)); 35 | 36 | public static Behavior GetOriginalBehavior(DependencyObject obj) 37 | { 38 | return (Behavior)obj.GetValue(OriginalBehaviorProperty); 39 | } 40 | 41 | public static void SetOriginalBehavior(DependencyObject obj, Behavior value) 42 | { 43 | obj.SetValue(OriginalBehaviorProperty, value); 44 | } 45 | 46 | #endregion 47 | 48 | #region Private Methods 49 | 50 | private static void OnBehaviorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 51 | { 52 | var fe = d as FrameworkElement; 53 | if (fe == null) return; 54 | 55 | var newVal = e.NewValue as StylizedBehaviorCollection; 56 | var oldVal = e.OldValue as StylizedBehaviorCollection; 57 | 58 | if (newVal == oldVal) return; 59 | 60 | var behaviors = Interaction.GetBehaviors(fe); 61 | fe.Unloaded -= OnUnloaded; 62 | 63 | 64 | if (oldVal != null) 65 | { 66 | foreach (var behavior in oldVal) 67 | { 68 | var index = GetIndexOf(behaviors, behavior); 69 | if (index >= 0) 70 | { 71 | behaviors.RemoveAt(index); 72 | } 73 | } 74 | } 75 | 76 | if (newVal != null) 77 | { 78 | foreach (var behavior in newVal) 79 | { 80 | var index = GetIndexOf(behaviors, behavior); 81 | if (index < 0) 82 | { 83 | var clone = (Behavior)behavior.Clone(); 84 | SetOriginalBehavior(clone, behavior); 85 | behaviors.Add(clone); 86 | } 87 | } 88 | } 89 | 90 | if (behaviors.Count > 0) 91 | { 92 | fe.Unloaded += OnUnloaded; 93 | } 94 | } 95 | 96 | private static void OnLoaded(object sender, RoutedEventArgs e) 97 | { 98 | var fe = sender as FrameworkElement; 99 | if (fe == null) return; 100 | 101 | fe.Loaded -= OnLoaded; 102 | var behaviors = Interaction.GetBehaviors(fe); 103 | 104 | foreach (var behavior in behaviors) 105 | { 106 | behavior.Attach(fe); 107 | } 108 | } 109 | 110 | private static void OnUnloaded(object sender, RoutedEventArgs e) 111 | { 112 | var fe = sender as FrameworkElement; 113 | if (fe == null) return; 114 | 115 | var behaviors = Interaction.GetBehaviors(fe); 116 | foreach (var behavior in behaviors) 117 | { 118 | behavior.Detach(); 119 | } 120 | 121 | fe.Loaded += OnLoaded; 122 | } 123 | 124 | private static int GetIndexOf(BehaviorCollection items, Behavior behavior) 125 | { 126 | int index = -1; 127 | var orignalBehavior = GetOriginalBehavior(behavior); 128 | 129 | for (int i = 0; i < items.Count; i++) 130 | { 131 | var currentBehavior = items[i]; 132 | if (currentBehavior == behavior || currentBehavior == orignalBehavior) 133 | { 134 | index = i; 135 | break; 136 | } 137 | 138 | var currentOrignalBehavior = GetOriginalBehavior(currentBehavior); 139 | if (currentOrignalBehavior == behavior || currentOrignalBehavior == orignalBehavior) 140 | { 141 | index = i; 142 | break; 143 | } 144 | } 145 | 146 | return index; 147 | } 148 | 149 | #endregion 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /AntWpf/Behaviors/VisibilityBehavior.cs: -------------------------------------------------------------------------------- 1 | namespace Antd.Behaviors 2 | { 3 | using System.Windows; 4 | using System.Windows.Media.Animation; 5 | 6 | using Microsoft.Xaml.Behaviors; 7 | 8 | /// 9 | /// Provides the ability to animate when changing the Visibility property for an element. 10 | /// 11 | public class VisibilityBehavior : Behavior 12 | { 13 | #region Fields 14 | 15 | private Visibility visibility; 16 | 17 | #endregion 18 | 19 | #region Properties 20 | 21 | public static readonly DependencyProperty AppearProperty = 22 | DependencyProperty.Register("Appear", typeof(Storyboard), typeof(VisibilityBehavior), new PropertyMetadata(null)); 23 | 24 | /// 25 | /// Gets/sets the storyboard when the element is visible. 26 | /// 27 | public Storyboard Appear 28 | { 29 | get { return (Storyboard)GetValue(AppearProperty); } 30 | set { SetValue(AppearProperty, value); } 31 | } 32 | 33 | public static readonly DependencyProperty LeaveProperty = 34 | DependencyProperty.Register("Leave", typeof(Storyboard), typeof(VisibilityBehavior), new PropertyMetadata(null)); 35 | 36 | /// 37 | /// Gets/sets the storyboard when the element is hidden. 38 | /// 39 | public Storyboard Leave 40 | { 41 | get { return (Storyboard)GetValue(LeaveProperty); } 42 | set { SetValue(LeaveProperty, value); } 43 | } 44 | 45 | #endregion 46 | 47 | #region Overrides 48 | 49 | protected override void OnAttached() 50 | { 51 | visibility = AssociatedObject.Visibility; 52 | AssociatedObject.IsVisibleChanged += OnVisibleChanged; 53 | 54 | base.OnAttached(); 55 | } 56 | 57 | private void OnLoaded(object sender, RoutedEventArgs e) 58 | { 59 | AssociatedObject.IsVisibleChanged += OnVisibleChanged; 60 | } 61 | 62 | protected override void OnDetaching() 63 | { 64 | AssociatedObject.IsVisibleChanged -= OnVisibleChanged; 65 | 66 | base.OnDetaching(); 67 | } 68 | 69 | #endregion 70 | 71 | #region Private Methods 72 | 73 | private void OnVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 74 | { 75 | if (visibility == AssociatedObject.Visibility) return; 76 | 77 | Storyboard storyboard; 78 | 79 | if (AssociatedObject.Visibility == Visibility.Visible) 80 | { 81 | if (Appear == null) return; 82 | 83 | storyboard = Appear; 84 | visibility = AssociatedObject.Visibility; 85 | 86 | } else 87 | { 88 | if (Leave == null) return; 89 | 90 | var cache = AssociatedObject.Visibility; 91 | AssociatedObject.SetCurrentValue(UIElement.VisibilityProperty, visibility = Visibility.Visible); 92 | 93 | storyboard = Leave.Clone(); 94 | storyboard.Completed += (s, a) => AssociatedObject.SetCurrentValue(UIElement.VisibilityProperty, visibility = cache); 95 | } 96 | 97 | AssociatedObject.BeginStoryboard(storyboard); 98 | } 99 | 100 | #endregion 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /AntWpf/ColorPalette.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf 2 | { 3 | using System; 4 | using System.Windows.Media; 5 | 6 | public static class ColorPalette 7 | { 8 | #region Fields 9 | 10 | private const int hueStep = 2; 11 | 12 | private const int saturationStep = 16; 13 | 14 | private const int saturationStep2 = 5; 15 | 16 | private const int brightnessStep1 = 5; 17 | 18 | private const int brightnessStep2 = 15; 19 | 20 | private const int lightColorCount = 5; 21 | 22 | private const int darkColorCount = 4; 23 | 24 | #endregion 25 | 26 | #region Public Methods 27 | 28 | public static Color Toning(Color color, int index) 29 | { 30 | bool isLight = index <= 6; 31 | 32 | HSV hsv = Color2Hsv(color); 33 | int i = isLight ? lightColorCount + 1 - index : index - lightColorCount - 1; 34 | 35 | return Hsv2Color(GetHue(hsv, i, isLight), GetSaturation(hsv, i, isLight), GetValue(hsv, i, isLight), color.A); 36 | } 37 | 38 | #endregion 39 | 40 | #region Private Methods 41 | 42 | private static double GetHue(HSV hsv, int i, bool isLight) 43 | { 44 | double hue; 45 | 46 | if (hsv.H >= 60 && hsv.H <= 240) 47 | { 48 | hue = isLight ? hsv.H - hueStep * i : hsv.H + hueStep * i; 49 | } 50 | else 51 | { 52 | hue = isLight ? hsv.H + hueStep * i : hsv.H - hueStep * i; 53 | } 54 | 55 | if (hue < 0) 56 | { 57 | hue += 360; 58 | } 59 | else if (hue >= 360) 60 | { 61 | hue -= 360; 62 | } 63 | 64 | return Math.Round(hue); 65 | } 66 | private static double GetSaturation(HSV hsv, int i, bool isLight) 67 | { 68 | double saturation; 69 | 70 | if (isLight) 71 | { 72 | saturation = Math.Round(hsv.S * 100) - saturationStep * i; 73 | } 74 | else if (i == darkColorCount) 75 | { 76 | saturation = Math.Round(hsv.S * 100) + saturationStep; 77 | } 78 | else 79 | { 80 | saturation = Math.Round(hsv.S * 100) + saturationStep2 * i; 81 | } 82 | 83 | if (saturation > 100) 84 | { 85 | saturation = 100; 86 | } 87 | 88 | if (isLight && i == lightColorCount && saturation > 10) 89 | { 90 | saturation = 10; 91 | } 92 | 93 | if (saturation < 6) 94 | { 95 | saturation = 6; 96 | } 97 | 98 | return Math.Round(saturation); 99 | } 100 | 101 | private static double GetValue(HSV hsv, int i, bool isLight) 102 | { 103 | if (isLight) 104 | { 105 | return Math.Round(hsv.V * 100) + brightnessStep1 * i; 106 | } 107 | return Math.Round(hsv.V * 100) - brightnessStep2 * i; 108 | } 109 | 110 | private static Color Hsv2Color(double h, double s, double v, byte a) 111 | { 112 | h = Bound(h, 360) * 6; 113 | s = Bound(s, 100); 114 | v = Bound(v, 100); 115 | 116 | double i = Math.Floor(h); 117 | double f = h - i; 118 | 119 | double p = v * (1 - s), 120 | q = v * (1 - f * s), 121 | t = v * (1 - (1 - f) * s); 122 | 123 | int mod = (int)(i % 6); 124 | double r = new double[6] { v, q, p, p, t, v }[mod], 125 | g = new double[6] { t, v, v, q, p, p }[mod], 126 | b = new double[6] { p, p, t, v, v, q }[mod]; 127 | 128 | r = Math.Min(255, Math.Max(0, r * 255)); 129 | g = Math.Min(255, Math.Max(0, g * 255)); 130 | b = Math.Min(255, Math.Max(0, b * 255)); 131 | 132 | return new Color() { R = (byte)Math.Round(r), G = (byte)Math.Round(g), B = (byte)Math.Round(b), A = a }; 133 | } 134 | 135 | private static HSV Color2Hsv(Color color) 136 | { 137 | double r = Bound(color.R, 255), 138 | g = Bound(color.G, 255), 139 | b = Bound(color.B, 255); 140 | 141 | double max = Math.Max(r, Math.Max(g, b)), 142 | min = Math.Min(r, Math.Min(g, b)); 143 | 144 | double h = 0, 145 | v = max, 146 | d = max - min; 147 | double s = max == 0 ? 0 : d / max; 148 | 149 | if (max != min) 150 | { 151 | if (max == r) 152 | { 153 | h = (g - b) / d + (g < b ? 6 : 0); 154 | } 155 | else if (max == g) 156 | { 157 | h = (b - r) / d + 2; 158 | } 159 | else if (max == b) 160 | { 161 | h = (r - g) / d + 4; 162 | } 163 | 164 | h /= 6; 165 | } 166 | 167 | return new HSV() { H = h * 360, S = s, V = v }; 168 | } 169 | 170 | /// 171 | /// Take input from [0, n] and return it as [0, 1] 172 | /// 173 | /// 174 | /// 175 | /// 176 | private static double Bound(double n, double max) 177 | { 178 | n = Math.Min(max, Math.Max(0, n)); 179 | 180 | // Handle floating point rounding errors 181 | if ((Math.Abs(n - max) < 0.000001)) 182 | { 183 | return 1; 184 | } 185 | 186 | // Convert into [0, 1] range if it isn't already 187 | return (n % max) / max; 188 | } 189 | 190 | #endregion 191 | } 192 | 193 | internal struct HSV 194 | { 195 | public double H; 196 | 197 | public double S; 198 | 199 | public double V; 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /AntWpf/Controls/AntIcon.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System; 3 | using System.Windows; 4 | using System.Windows.Markup; 5 | using System.ComponentModel; 6 | using System.Windows.Media; 7 | 8 | namespace AntWpf.Controls 9 | { 10 | public class AntIcon : System.Windows.Controls.Control 11 | { 12 | private static readonly Lazy> _dataList 13 | = new Lazy>(AntIconDataFactory.Create); 14 | 15 | static AntIcon() 16 | { 17 | DefaultStyleKeyProperty.OverrideMetadata(typeof(AntIcon), new FrameworkPropertyMetadata(typeof(AntIcon))); 18 | } 19 | 20 | public static readonly DependencyProperty KeyProperty 21 | = DependencyProperty.Register(nameof(Key), typeof(AntIconKey), typeof(AntIcon), new PropertyMetadata(default(AntIconKey), KeyPropertyChangedCallback)); 22 | 23 | private static void KeyPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 24 | => ((AntIcon)dependencyObject).UpdateData(); 25 | 26 | private static readonly DependencyPropertyKey DataPropertyKey 27 | = DependencyProperty.RegisterReadOnly(nameof(Data), typeof(string), typeof(AntIcon), new PropertyMetadata("")); 28 | 29 | // ReSharper disable once StaticMemberInGenericType 30 | public static readonly DependencyProperty DataProperty = DataPropertyKey.DependencyProperty; 31 | 32 | /// 33 | /// Gets or sets the icon to display. 34 | /// 35 | public AntIconKey Key 36 | { 37 | get => (AntIconKey)GetValue(KeyProperty); 38 | set => SetValue(KeyProperty, value); 39 | } 40 | 41 | 42 | /// 43 | /// Gets the icon path data for the current . 44 | /// 45 | [TypeConverter(typeof(GeometryConverter))] 46 | public string? Data 47 | { 48 | get => (string?)GetValue(DataProperty); 49 | private set => SetValue(DataPropertyKey, value); 50 | } 51 | public override void OnApplyTemplate() 52 | { 53 | base.OnApplyTemplate(); 54 | UpdateData(); 55 | } 56 | 57 | private void UpdateData() 58 | { 59 | string? data = null; 60 | _dataList.Value?.TryGetValue(Key, out data); 61 | Data = data; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /AntWpf/Controls/BorderStyle.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | public enum BorderStyle : byte 4 | { 5 | Solid, Dotted, Dashed 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /AntWpf/Controls/Button.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System; 4 | using System.Windows; 5 | using System.Windows.Media; 6 | using System.Windows.Media.Animation; 7 | using System.Windows.Shapes; 8 | using ButtonBase = System.Windows.Controls.Button; 9 | 10 | /// 11 | /// To trigger an operation. 12 | /// 13 | [TemplatePart(Name = PART_Border, Type = typeof(FrameworkElement))] 14 | [TemplateVisualState(Name = "Loaded", GroupName = "LoadStates")] 15 | [TemplateVisualState(Name = "Unloaded", GroupName = "LoadStates")] 16 | public class Button : ButtonBase 17 | { 18 | #region Fields 19 | 20 | private const string PART_Border = "PART_Border"; 21 | 22 | private FrameworkElement border; 23 | 24 | private VisualState mouseOverState; 25 | 26 | private VisualState pressedState; 27 | 28 | private VisualState focusedState; 29 | 30 | #endregion 31 | 32 | #region Properties 33 | 34 | public static readonly DependencyProperty GhostProperty = 35 | DependencyProperty.Register("Ghost", typeof(bool), typeof(Button), new PropertyMetadata(false, OnEffectBrushChanged)); 36 | 37 | /// 38 | /// Gets/sets whether to make the background transparent and invert text and border colors. 39 | /// 40 | public bool Ghost 41 | { 42 | get { return (bool)GetValue(GhostProperty); } 43 | set { SetValue(GhostProperty, value); } 44 | } 45 | 46 | public static readonly DependencyProperty IconProperty = 47 | DependencyProperty.Register("Icon", typeof(string), typeof(Button), new PropertyMetadata(null)); 48 | 49 | /// 50 | /// Gets/sets the icon type of the button. 51 | /// 52 | public string Icon 53 | { 54 | get { return (string)GetValue(IconProperty); } 55 | set { SetValue(IconProperty, value); } 56 | } 57 | 58 | public static readonly DependencyProperty LoadingProperty = 59 | DependencyProperty.Register("Loading", typeof(bool), typeof(Button), new PropertyMetadata(false, OnLoadingChanged)); 60 | 61 | /// 62 | /// Gets/sets the loading state of the button. 63 | /// 64 | public bool Loading 65 | { 66 | get { return (bool)GetValue(LoadingProperty); } 67 | set { SetValue(LoadingProperty, value); } 68 | } 69 | 70 | private static void OnLoadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 71 | { 72 | (d as Button).SetLoadVisualState(); 73 | } 74 | 75 | private void SetLoadVisualState() 76 | { 77 | VisualStateManager.GoToState(this, (Loading ? "Loaded" : "Unloaded"), true); 78 | } 79 | 80 | 81 | public static readonly DependencyProperty ShapeProperty = 82 | DependencyProperty.Register("Shape", typeof(Shapes), typeof(Button), new PropertyMetadata(Shapes.Square)); 83 | 84 | /// 85 | /// Gets/sets the shape of button. 86 | /// 87 | public Shapes Shape 88 | { 89 | get { return (Shapes)GetValue(ShapeProperty); } 90 | set { SetValue(ShapeProperty, value); } 91 | } 92 | 93 | public static readonly DependencyProperty SizeProperty = 94 | DependencyProperty.Register("Size", typeof(Sizes?), typeof(Button), new PropertyMetadata(null)); 95 | 96 | /// 97 | /// Gets/sets the size of the button. 98 | /// 99 | public Sizes? Size 100 | { 101 | get { return (Sizes?)GetValue(SizeProperty); } 102 | set { SetValue(SizeProperty, value); } 103 | } 104 | 105 | public static readonly DependencyProperty TypeProperty = 106 | DependencyProperty.Register("Type", typeof(ButtonType?), typeof(Button), new PropertyMetadata(null)); 107 | 108 | /// 109 | /// Gets/sets the type of the button. 110 | /// 111 | public ButtonType? Type 112 | { 113 | get { return (ButtonType?)GetValue(TypeProperty); } 114 | set { SetValue(TypeProperty, value); } 115 | } 116 | 117 | public static readonly DependencyProperty EffectBrushProperty = DependencyProperty.Register( 118 | "EffectBrush", 119 | typeof(Brush), 120 | typeof(Button), 121 | new FrameworkPropertyMetadata( 122 | Brushes.Transparent, 123 | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits, 124 | OnEffectBrushChanged)); 125 | 126 | /// 127 | /// Gets/sets the border effect brush of the button. 128 | /// 129 | public Brush EffectBrush 130 | { 131 | get { return (Brush)GetValue(EffectBrushProperty); } 132 | set { SetValue(EffectBrushProperty, value); } 133 | } 134 | 135 | private static void OnEffectBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 136 | { 137 | (d as Button).SetVisualStateAnimation(); 138 | } 139 | 140 | /// 141 | /// Force background transparent in Ghost state. 142 | /// 143 | private static object OnBackgroundCoerceValue(DependencyObject d, object baseValue) 144 | { 145 | var button = d as Button; 146 | 147 | if (button.Ghost) 148 | { 149 | return Brushes.Transparent; 150 | } 151 | 152 | return baseValue; 153 | } 154 | 155 | #endregion 156 | 157 | #region Constructors 158 | 159 | static Button() 160 | { 161 | DefaultStyleKeyProperty.OverrideMetadata(typeof(Button), new FrameworkPropertyMetadata(typeof(Button))); 162 | BackgroundProperty.OverrideMetadata(typeof(Button), new FrameworkPropertyMetadata { CoerceValueCallback = OnBackgroundCoerceValue }); 163 | } 164 | 165 | #endregion 166 | 167 | #region Overrides 168 | 169 | public override void OnApplyTemplate() 170 | { 171 | base.OnApplyTemplate(); 172 | 173 | border = GetTemplateChild(PART_Border) as FrameworkElement; 174 | mouseOverState = GetTemplateChild("MouseOver") as VisualState; 175 | 176 | focusedState = GetTemplateChild("Focused") as VisualState; 177 | pressedState = GetTemplateChild("Pressed") as VisualState; 178 | 179 | SetVisualStateAnimation(); 180 | SetLoadVisualState(); 181 | } 182 | 183 | #endregion 184 | 185 | #region Private Methods 186 | 187 | private void SetVisualStateAnimation() 188 | { 189 | // No initialization or no need for me to handle. 190 | if (border == null || mouseOverState == null && focusedState == null && pressedState == null) return; 191 | 192 | // Unable to extract color. 193 | if (EffectBrush is SolidColorBrush brush) 194 | { 195 | var isShape = border is Shape; 196 | Func func; 197 | 198 | if (!Type.HasValue || Type.Value == ButtonType.Dashed) 199 | { 200 | func = CreateDefaultStoryboard; 201 | } 202 | else if (Type.Value == ButtonType.Primary) 203 | { 204 | func = CreatePrimaryStoryboard; 205 | } 206 | else 207 | { 208 | // Danger 209 | func = CreateDangerStoryboard; 210 | } 211 | 212 | if (mouseOverState != null) 213 | { 214 | mouseOverState.Storyboard = func(this, brush.Color, 5, isShape, false, null); 215 | } 216 | 217 | if (focusedState != null) 218 | { 219 | focusedState.Storyboard = func(this, brush.Color, 5, isShape, true, null); 220 | } 221 | 222 | if (pressedState != null) 223 | { 224 | pressedState.Storyboard = func(this, brush.Color, 7, isShape, false, TimeSpan.FromSeconds(0)); 225 | } 226 | } 227 | } 228 | 229 | private static Storyboard CreateDefaultStoryboard(Button button, Color color, int index, bool IsShape, bool focused, Duration? duration = null) 230 | { 231 | var storyboard = new Storyboard(); 232 | var children = storyboard.Children; 233 | 234 | color = ColorPalette.Toning(color, index); 235 | children.Add(CreateForegroundAnimation(button, color, duration)); 236 | children.Add(CreateBorderAnimation(PART_Border, color, IsShape, duration)); 237 | 238 | return storyboard; 239 | } 240 | 241 | private static Storyboard CreatePrimaryStoryboard(Button button, Color color, int index, bool IsShape, bool focused, Duration? duration = null) 242 | { 243 | var storyboard = new Storyboard(); 244 | var children = storyboard.Children; 245 | 246 | color = ColorPalette.Toning(color, index); 247 | 248 | if (button.Ghost) 249 | { 250 | children.Add(CreateForegroundAnimation(button, color, duration)); 251 | } else 252 | { 253 | children.Add(CreateBackgroundAnimation(PART_Border, color, IsShape, duration)); 254 | } 255 | 256 | children.Add(CreateBorderAnimation(PART_Border, color, IsShape, duration)); 257 | 258 | return storyboard; 259 | } 260 | 261 | private static Storyboard CreateDangerStoryboard(Button button, Color color, int index, bool IsShape, bool focused, Duration? duration = null) 262 | { 263 | var storyboard = new Storyboard(); 264 | var children = storyboard.Children; 265 | 266 | Color foreground; 267 | color = ColorPalette.Toning(color, index); 268 | 269 | if (button.Ghost) 270 | { 271 | foreground = color; 272 | } else 273 | { 274 | Color background; 275 | 276 | if (focused) 277 | { 278 | foreground = color; 279 | background = Colors.White; 280 | } 281 | else 282 | { 283 | foreground = Colors.White; 284 | background = color; 285 | } 286 | 287 | children.Add(CreateBackgroundAnimation(PART_Border, background, IsShape, duration)); 288 | } 289 | 290 | children.Add(CreateForegroundAnimation(button, foreground, duration)); 291 | children.Add(CreateBorderAnimation(PART_Border, color, IsShape, duration)); 292 | 293 | return storyboard; 294 | } 295 | 296 | private static Timeline CreateForegroundAnimation(DependencyObject target, Color color, Duration? duration = null) 297 | { 298 | return CreateColorAnimation(target, "(Control.Foreground).(SolidColorBrush.Color)", color, duration); 299 | } 300 | 301 | private static Timeline CreateBackgroundAnimation(string target, Color color, bool IsShape, Duration? duration = null) 302 | { 303 | return CreateColorAnimation(target, (IsShape ? "Fill" : "Background") + ".Color", color, duration); 304 | } 305 | 306 | private static Timeline CreateBorderAnimation(string target, Color color, bool IsShape, Duration? duration = null) 307 | { 308 | return CreateColorAnimation(target, (IsShape ? "Stroke" : "BorderBrush") + ".Color", color, duration); 309 | } 310 | 311 | private static Timeline CreateColorAnimation(object target, string path, Color color, Duration? duration) 312 | { 313 | var animation = new ColorAnimation() { To = color }; 314 | 315 | if (duration.HasValue) 316 | { 317 | animation.Duration = duration.Value; 318 | } 319 | 320 | if (target is DependencyObject) 321 | { 322 | Storyboard.SetTarget(animation, (DependencyObject)target); 323 | } else 324 | { 325 | Storyboard.SetTargetName(animation, (string)target); 326 | } 327 | 328 | Storyboard.SetTargetProperty(animation, new PropertyPath(path)); 329 | 330 | return animation; 331 | } 332 | 333 | #endregion 334 | } 335 | 336 | public enum ButtonType : byte 337 | { 338 | Primary, Dashed, Danger 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /AntWpf/Controls/Helpers/Control.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System.ComponentModel; 4 | using System.Windows; 5 | using System.Windows.Media; 6 | 7 | /// 8 | /// A helper class that provides various controls. 9 | /// 10 | public static class Control 11 | { 12 | #region Border 13 | 14 | public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.RegisterAttached( 15 | "CornerRadius", 16 | typeof(CornerRadius), 17 | typeof(Control), 18 | new FrameworkPropertyMetadata( 19 | default(CornerRadius), 20 | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender 21 | )); 22 | 23 | /// 24 | /// Gets a value that represents the degree to which the corners of a control border are rounded. 25 | /// 26 | [Category("AntDesign")] 27 | public static CornerRadius GetCornerRadius(DependencyObject obj) 28 | { 29 | return (CornerRadius)obj.GetValue(CornerRadiusProperty); 30 | } 31 | 32 | /// 33 | /// Sets a value that represents the degree to which the corners of a control border are rounded. 34 | /// 35 | public static void SetCornerRadius(DependencyObject obj, CornerRadius value) 36 | { 37 | obj.SetValue(CornerRadiusProperty, value); 38 | } 39 | 40 | public static readonly DependencyProperty BorderStyleProperty = DependencyProperty.RegisterAttached( 41 | "BorderStyle", 42 | typeof(BorderStyle), 43 | typeof(Control), 44 | new PropertyMetadata(BorderStyle.Solid)); 45 | 46 | /// 47 | /// Gets the style of the control border. 48 | /// 49 | public static BorderStyle GetBorderStyle(DependencyObject obj) 50 | { 51 | return (BorderStyle)obj.GetValue(BorderStyleProperty); 52 | } 53 | 54 | /// 55 | /// Sets the style of the control border. 56 | /// 57 | public static void SetBorderStyle(DependencyObject obj, BorderStyle value) 58 | { 59 | obj.SetValue(BorderStyleProperty, value); 60 | } 61 | 62 | #endregion 63 | 64 | #region Size 65 | 66 | public static readonly DependencyProperty SizeProperty = DependencyProperty.RegisterAttached( 67 | "Size", 68 | typeof(Sizes?), 69 | typeof(Control), 70 | new PropertyMetadata(null)); 71 | 72 | /// 73 | /// Gets the size of the control. 74 | /// 75 | public static Sizes? GetSize(DependencyObject obj) 76 | { 77 | return (Sizes?)obj.GetValue(SizeProperty); 78 | } 79 | 80 | /// 81 | /// Sets the size of the control. 82 | /// 83 | public static void SetSize(DependencyObject obj, Sizes? value) 84 | { 85 | obj.SetValue(SizeProperty, value); 86 | } 87 | 88 | #endregion 89 | 90 | #region Brushes 91 | 92 | public static readonly DependencyProperty MouseOverForegroundProperty = DependencyProperty.RegisterAttached( 93 | "MouseOverForeground", 94 | typeof(Brush), 95 | typeof(Control), 96 | new FrameworkPropertyMetadata( 97 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 98 | )); 99 | 100 | /// 101 | /// Gets the foreground for controls in mouse over. 102 | /// 103 | public static Brush GetMouseOverForeground(DependencyObject obj) 104 | { 105 | return (Brush)obj.GetValue(MouseOverForegroundProperty); 106 | } 107 | 108 | /// 109 | /// Gets the foreground for controls in mouse over. 110 | /// 111 | public static void SetMouseOverForeground(DependencyObject obj, Brush value) 112 | { 113 | obj.SetValue(MouseOverForegroundProperty, value); 114 | } 115 | 116 | public static readonly DependencyProperty MouseOverBorderBrushProperty = DependencyProperty.RegisterAttached( 117 | "MouseOverBorderBrush", 118 | typeof(Brush), 119 | typeof(Control), 120 | new FrameworkPropertyMetadata( 121 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 122 | )); 123 | 124 | /// 125 | /// Gets the border brush for controls in mouse over. 126 | /// 127 | public static Brush GetMouseOverBorderBrush(DependencyObject obj) 128 | { 129 | return (Brush)obj.GetValue(MouseOverBorderBrushProperty); 130 | } 131 | 132 | /// 133 | /// Sets the border brush for controls in mouse over. 134 | /// 135 | public static void SetMouseOverBorderBrush(DependencyObject obj, Brush value) 136 | { 137 | obj.SetValue(MouseOverBorderBrushProperty, value); 138 | } 139 | 140 | public static readonly DependencyProperty MouseOverBackgroundProperty = DependencyProperty.RegisterAttached( 141 | "MouseOverBackground", 142 | typeof(Brush), 143 | typeof(Control), 144 | new FrameworkPropertyMetadata( 145 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 146 | )); 147 | 148 | /// 149 | /// Gets the background brush for controls in mouse over. 150 | /// 151 | public static Brush GetMouseOverBackground(DependencyObject obj) 152 | { 153 | return (Brush)obj.GetValue(MouseOverBackgroundProperty); 154 | } 155 | 156 | /// 157 | /// Sets the background brush for controls in mouse over. 158 | /// 159 | public static void SetMouseOverBackground(DependencyObject obj, Brush value) 160 | { 161 | obj.SetValue(MouseOverBackgroundProperty, value); 162 | } 163 | 164 | public static readonly DependencyProperty FocusedForegroundProperty = DependencyProperty.RegisterAttached( 165 | "FocusedForeground", 166 | typeof(Brush), 167 | typeof(Control), 168 | new FrameworkPropertyMetadata( 169 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 170 | )); 171 | 172 | /// 173 | /// Gets the foreground for controls in focused. 174 | /// 175 | public static Brush GetFocusedForeground(DependencyObject obj) 176 | { 177 | return (Brush)obj.GetValue(FocusedForegroundProperty); 178 | } 179 | 180 | /// 181 | /// Gets the foreground for controls in focused. 182 | /// 183 | public static void SetFocusedForeground(DependencyObject obj, Brush value) 184 | { 185 | obj.SetValue(FocusedForegroundProperty, value); 186 | } 187 | 188 | public static readonly DependencyProperty FocusedBorderBrushProperty = DependencyProperty.RegisterAttached( 189 | "FocusedBorderBrush", 190 | typeof(Brush), 191 | typeof(Control), 192 | new FrameworkPropertyMetadata( 193 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 194 | )); 195 | 196 | /// 197 | /// Gets the border brush for controls in focused. 198 | /// 199 | public static Brush GetFocusedBorderBrush(DependencyObject obj) 200 | { 201 | return (Brush)obj.GetValue(FocusedBorderBrushProperty); 202 | } 203 | 204 | /// 205 | /// Sets the border brush for controls in focused. 206 | /// 207 | public static void SetFocusedBorderBrush(DependencyObject obj, Brush value) 208 | { 209 | obj.SetValue(FocusedBorderBrushProperty, value); 210 | } 211 | 212 | public static readonly DependencyProperty FocusedBackgroundProperty = DependencyProperty.RegisterAttached( 213 | "FocusedBackground", 214 | typeof(Brush), 215 | typeof(Control), 216 | new FrameworkPropertyMetadata( 217 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 218 | )); 219 | 220 | /// 221 | /// Gets the background brush for controls in focused. 222 | /// 223 | public static Brush GetFocusedBackground(DependencyObject obj) 224 | { 225 | return (Brush)obj.GetValue(FocusedBackgroundProperty); 226 | } 227 | 228 | /// 229 | /// Sets the background brush for controls in focused. 230 | /// 231 | public static void SetFocusedBackground(DependencyObject obj, Brush value) 232 | { 233 | obj.SetValue(FocusedBackgroundProperty, value); 234 | } 235 | 236 | public static readonly DependencyProperty PressedForegroundProperty = DependencyProperty.RegisterAttached( 237 | "PressedForeground", 238 | typeof(Brush), 239 | typeof(Control), 240 | new FrameworkPropertyMetadata( 241 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 242 | )); 243 | 244 | /// 245 | /// Gets the foreground for controls in pressed. 246 | /// 247 | public static Brush GetPressedForeground(DependencyObject obj) 248 | { 249 | return (Brush)obj.GetValue(PressedForegroundProperty); 250 | } 251 | 252 | /// 253 | /// Gets the foreground for controls in pressed. 254 | /// 255 | public static void SetPressedForeground(DependencyObject obj, Brush value) 256 | { 257 | obj.SetValue(PressedForegroundProperty, value); 258 | } 259 | 260 | public static readonly DependencyProperty PressedBorderBrushProperty = DependencyProperty.RegisterAttached( 261 | "PressedBorderBrush", 262 | typeof(Brush), 263 | typeof(Control), 264 | new FrameworkPropertyMetadata( 265 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 266 | )); 267 | 268 | /// 269 | /// Gets the border brush for controls in pressed. 270 | /// 271 | public static Brush GetPressedBorderBrush(DependencyObject obj) 272 | { 273 | return (Brush)obj.GetValue(PressedBorderBrushProperty); 274 | } 275 | 276 | /// 277 | /// Sets the border brush for controls in pressed. 278 | /// 279 | public static void SetPressedBorderBrush(DependencyObject obj, Brush value) 280 | { 281 | obj.SetValue(PressedBorderBrushProperty, value); 282 | } 283 | 284 | public static readonly DependencyProperty PressedBackgroundProperty = DependencyProperty.RegisterAttached( 285 | "PressedBackground", 286 | typeof(Brush), 287 | typeof(Control), 288 | new FrameworkPropertyMetadata( 289 | Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits 290 | )); 291 | 292 | /// 293 | /// Gets the background brush for controls in pressed. 294 | /// 295 | public static Brush GetPressedBackground(DependencyObject obj) 296 | { 297 | return (Brush)obj.GetValue(PressedBackgroundProperty); 298 | } 299 | 300 | /// 301 | /// Sets the background brush for controls in pressed. 302 | /// 303 | public static void SetPressedBackground(DependencyObject obj, Brush value) 304 | { 305 | obj.SetValue(PressedBackgroundProperty, value); 306 | } 307 | 308 | #endregion 309 | 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /AntWpf/Controls/Helpers/Input.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Controls.Primitives; 8 | using System.Windows.Input; 9 | using System.Windows.Media; 10 | 11 | public static class Input 12 | { 13 | #region Attached Properties 14 | 15 | public static readonly DependencyProperty PlaceholderProperty = 16 | DependencyProperty.RegisterAttached("Placeholder", typeof(string), typeof(Input), new PropertyMetadata(string.Empty)); 17 | 18 | /// 19 | /// Gets the placeholder for the input control. 20 | /// 21 | [AttachedPropertyBrowsableForType(typeof(TextBoxBase))] 22 | [AttachedPropertyBrowsableForType(typeof(PasswordBox))] 23 | [AttachedPropertyBrowsableForType(typeof(ComboBox))] 24 | public static string GetPlaceholder(DependencyObject obj) 25 | { 26 | return (string)obj.GetValue(PlaceholderProperty); 27 | } 28 | 29 | /// 30 | /// Sets the placeholder for the input control. 31 | /// 32 | public static void SetPlaceholder(DependencyObject obj, string value) 33 | { 34 | obj.SetValue(PlaceholderProperty, value); 35 | } 36 | 37 | public static readonly DependencyProperty PlaceholderBrushProperty = 38 | DependencyProperty.RegisterAttached("PlaceholderBrush", typeof(Brush), typeof(Input), 39 | new FrameworkPropertyMetadata( 40 | Brushes.Silver, 41 | FrameworkPropertyMetadataOptions.AffectsRender | 42 | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender | 43 | FrameworkPropertyMetadataOptions.Inherits)); 44 | 45 | /// 46 | /// Gets the placeholder foreground brush for the input control. 47 | /// 48 | [AttachedPropertyBrowsableForType(typeof(TextBoxBase))] 49 | [AttachedPropertyBrowsableForType(typeof(PasswordBox))] 50 | [AttachedPropertyBrowsableForType(typeof(ComboBox))] 51 | public static Brush GetPlaceholderBrush(DependencyObject obj) 52 | { 53 | return (Brush)obj.GetValue(PlaceholderBrushProperty); 54 | } 55 | 56 | /// 57 | /// Sets the placeholder foreground brush for the input control. 58 | /// 59 | public static void SetPlaceholderBrush(DependencyObject obj, Brush value) 60 | { 61 | obj.SetValue(PlaceholderBrushProperty, value); 62 | } 63 | 64 | public static readonly DependencyProperty PrefixProperty = 65 | DependencyProperty.RegisterAttached("Prefix", typeof(object), typeof(Input), new PropertyMetadata(null)); 66 | 67 | /// 68 | /// Gets the prefix object of the input control. 69 | /// 70 | [AttachedPropertyBrowsableForType(typeof(TextBox))] 71 | [AttachedPropertyBrowsableForType(typeof(PasswordBox))] 72 | [AttachedPropertyBrowsableForType(typeof(ComboBox))] 73 | public static object GetPrefix(DependencyObject obj) 74 | { 75 | return obj.GetValue(PrefixProperty); 76 | } 77 | 78 | /// 79 | /// Sets the prefix object of the input control. 80 | /// 81 | public static void SetPrefix(DependencyObject obj, object value) 82 | { 83 | obj.SetValue(PrefixProperty, value); 84 | } 85 | 86 | public static readonly DependencyProperty SuffixProperty = 87 | DependencyProperty.RegisterAttached("Suffix", typeof(object), typeof(Input), new PropertyMetadata(null)); 88 | 89 | /// 90 | /// Gets the suffix object of the input control. 91 | /// 92 | [AttachedPropertyBrowsableForType(typeof(TextBox))] 93 | [AttachedPropertyBrowsableForType(typeof(PasswordBox))] 94 | public static object GetSuffix(DependencyObject obj) 95 | { 96 | return obj.GetValue(SuffixProperty); 97 | } 98 | 99 | /// 100 | /// Sets the suffix object of the input control. 101 | /// 102 | public static void SetSuffix(DependencyObject obj, object value) 103 | { 104 | obj.SetValue(SuffixProperty, value); 105 | } 106 | 107 | public static readonly DependencyProperty PasswordProperty = 108 | DependencyProperty.RegisterAttached("Password", typeof(string), typeof(Input), 109 | new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnPasswordChanged))); 110 | 111 | private static void OnPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 112 | { 113 | if (d is PasswordBox passwordBox) 114 | { 115 | var newVal = (string)e.NewValue; 116 | 117 | // Sync password 118 | if (newVal != passwordBox.Password) 119 | { 120 | passwordBox.Password = newVal; 121 | } 122 | } 123 | } 124 | 125 | /// 126 | /// Gets the password currently held by the PasswordBox. 127 | /// 128 | [AttachedPropertyBrowsableForType(typeof(PasswordBox))] 129 | public static string GetPassword(DependencyObject obj) 130 | { 131 | return (string)obj.GetValue(PasswordProperty); 132 | } 133 | 134 | /// 135 | /// Sets the password currently held by the PasswordBox. 136 | /// 137 | public static void SetPassword(DependencyObject obj, string value) 138 | { 139 | obj.SetValue(PasswordProperty, value); 140 | } 141 | 142 | public static readonly DependencyProperty ClearableProperty = 143 | DependencyProperty.RegisterAttached("Clearable", typeof(bool), typeof(Input), new PropertyMetadata(false)); 144 | 145 | /// 146 | /// Gets whether the input control has a clear behavior. 147 | /// 148 | [AttachedPropertyBrowsableForType(typeof(TextBox))] 149 | [AttachedPropertyBrowsableForType(typeof(PasswordBox))] 150 | [AttachedPropertyBrowsableForType(typeof(ComboBox))] 151 | public static bool GetClearable(DependencyObject obj) 152 | { 153 | return (bool)obj.GetValue(ClearableProperty); 154 | } 155 | 156 | /// 157 | /// Sets whether the input control has a clear behavior. 158 | /// 159 | public static void SetClearable(DependencyObject obj, bool value) 160 | { 161 | obj.SetValue(ClearableProperty, value); 162 | } 163 | 164 | public static readonly DependencyProperty EyeableProperty = 165 | DependencyProperty.RegisterAttached("Eyeable", typeof(bool), typeof(Input), new PropertyMetadata(false)); 166 | 167 | /// 168 | /// Gets whether the password currently held by PasswordBox is displayed in text. 169 | /// 170 | [AttachedPropertyBrowsableForType(typeof(PasswordBox))] 171 | public static bool GetEyeable(DependencyObject obj) 172 | { 173 | return (bool)obj.GetValue(EyeableProperty); 174 | } 175 | 176 | /// 177 | /// Sets whether the password currently held by PasswordBox is displayed in text. 178 | /// 179 | public static void SetEyeable(DependencyObject obj, bool value) 180 | { 181 | obj.SetValue(EyeableProperty, value); 182 | } 183 | 184 | public static readonly DependencyProperty ClearEnabledProperty = 185 | DependencyProperty.RegisterAttached("ClearEnabled", typeof(bool), typeof(Input), new PropertyMetadata(false, OnClearEnabled)); 186 | 187 | /// 188 | /// Gets the clear enable state of the control. 189 | /// 190 | public static bool GetClearEnabled(DependencyObject obj) 191 | { 192 | return (bool)obj.GetValue(ClearEnabledProperty); 193 | } 194 | 195 | 196 | /// 197 | /// Sets the clear enable state of the control. 198 | /// 199 | public static void SetClearEnabled(DependencyObject obj, bool value) 200 | { 201 | obj.SetValue(ClearEnabledProperty, value); 202 | } 203 | 204 | private static void OnClearEnabled(DependencyObject d, DependencyPropertyChangedEventArgs e) 205 | { 206 | if (d is UIElement) 207 | { 208 | if ((bool)e.NewValue) 209 | { 210 | ((UIElement)d).MouseLeftButtonUp += OnClear; 211 | } 212 | else 213 | { 214 | ((UIElement)d).MouseLeftButtonUp -= OnClear; 215 | } 216 | } 217 | } 218 | 219 | #endregion 220 | 221 | #region Private Methods 222 | 223 | private static void OnClear(object sender, RoutedEventArgs e) 224 | { 225 | if (sender is DependencyObject d) 226 | { 227 | var parent = d.GetAncestors().FirstOrDefault(a => a is TextBox || a is PasswordBox || a is ComboBox); 228 | 229 | if (GetClearable(parent)) 230 | { 231 | if (parent is TextBox) 232 | { 233 | ((TextBox)parent).Clear(); 234 | ((TextBox)parent).GetBindingExpression(TextBox.TextProperty)?.UpdateSource(); 235 | } 236 | else if (parent is PasswordBox) 237 | { 238 | ((PasswordBox)parent).Clear(); 239 | ((PasswordBox)parent).GetBindingExpression(PasswordProperty)?.UpdateSource(); 240 | } 241 | else if (parent is ComboBox) 242 | { 243 | if (((ComboBox)parent).IsEditable) 244 | { 245 | ((ComboBox)parent).Text = string.Empty; 246 | ((ComboBox)parent).GetBindingExpression(ComboBox.TextProperty)?.UpdateSource(); 247 | } 248 | 249 | ((ComboBox)parent).SelectedItem = null; 250 | ((ComboBox)parent).GetBindingExpression(Selector.SelectedItemProperty)?.UpdateSource(); 251 | } 252 | } 253 | } 254 | } 255 | 256 | #endregion 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /AntWpf/Controls/Helpers/ProgressAssist.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Controls; 7 | using System.Windows.Media.Animation; 8 | using System.Windows; 9 | 10 | namespace AntWpf.Controls 11 | { 12 | public class ProgressAssist 13 | { 14 | public static double GetSmoothValue(DependencyObject obj) 15 | { 16 | return (double)obj.GetValue(SmoothValueProperty); 17 | } 18 | 19 | public static void SetSmoothValue(DependencyObject obj, double value) 20 | { 21 | obj.SetValue(SmoothValueProperty, value); 22 | } 23 | 24 | public static readonly DependencyProperty SmoothValueProperty = 25 | DependencyProperty.RegisterAttached("SmoothValue", typeof(double), typeof(ProgressAssist), new PropertyMetadata(0.0, changing)); 26 | 27 | private static void changing(DependencyObject d, DependencyPropertyChangedEventArgs e) 28 | { 29 | var anim = new DoubleAnimation((double)e.OldValue, (double)e.NewValue, new TimeSpan(0, 0, 0, 0, 300)); 30 | (d as ProgressBar).BeginAnimation(ProgressBar.ValueProperty, anim, HandoffBehavior.Compose); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /AntWpf/Controls/Helpers/TreeHelper.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System.Collections.Generic; 4 | using System.Windows; 5 | using System.Windows.Media; 6 | using System.Windows.Media.Media3D; 7 | 8 | /// 9 | /// Helper methods for UI-related tasks. 10 | /// This class was obtained from Philip Sumi (a fellow WPF Disciples blog) 11 | /// http://www.hardcodet.net/uploads/2009/06/UIHelper.cs 12 | /// 13 | public static class TreeHelper 14 | { 15 | #region Find Parent 16 | 17 | /// 18 | /// Finds a parent of a given item on the visual tree. 19 | /// 20 | /// The type of the queried item. 21 | /// A direct or indirect child of the 22 | /// queried item. 23 | /// The first parent item that matches the submitted 24 | /// type parameter. If not matching item can be found, a null 25 | /// reference is being returned. 26 | public static T TryFindParent(this DependencyObject child) 27 | where T : DependencyObject 28 | { 29 | //get parent item 30 | DependencyObject parentObject = GetParentObject(child); 31 | 32 | //we've reached the end of the tree 33 | if (parentObject == null) return null; 34 | 35 | //check if the parent matches the type we're looking for 36 | if (parentObject is T parent) 37 | { 38 | return parent; 39 | } 40 | else 41 | { 42 | //use recursion to proceed with next level 43 | return TryFindParent(parentObject); 44 | } 45 | } 46 | 47 | /// 48 | /// This method is an alternative to WPF's 49 | /// method, which also 50 | /// supports content elements. Keep in mind that for content element, 51 | /// this method falls back to the logical tree of the element! 52 | /// 53 | /// The item to be processed. 54 | /// The submitted item's parent, if available. Otherwise 55 | /// null. 56 | public static DependencyObject GetParentObject(this DependencyObject child) 57 | { 58 | if (child == null) return null; 59 | 60 | //handle content elements separately 61 | if (child is ContentElement contentElement) 62 | { 63 | DependencyObject parent = ContentOperations.GetParent(contentElement); 64 | if (parent != null) return parent; 65 | 66 | return contentElement is FrameworkContentElement fce ? fce.Parent : null; 67 | } 68 | 69 | //also try searching for parent in framework elements (such as DockPanel, etc) 70 | if (child is FrameworkElement frameworkElement) 71 | { 72 | DependencyObject parent = frameworkElement.Parent; 73 | if (parent != null) return parent; 74 | } 75 | 76 | //if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper 77 | return VisualTreeHelper.GetParent(child); 78 | } 79 | 80 | /// 81 | /// Finds all Ancestors of a given item on the visual tree. 82 | /// 83 | /// A node in a visual tree 84 | /// All ancestors in visual tree of element 85 | public static IEnumerable GetAncestors(this DependencyObject child) 86 | { 87 | DependencyObject parent = VisualTreeHelper.GetParent(child); 88 | while ((parent) != null) 89 | { 90 | yield return parent; 91 | parent = VisualTreeHelper.GetParent(parent); 92 | } 93 | } 94 | 95 | #endregion 96 | 97 | #region Find children 98 | 99 | /// 100 | /// Finds a Child of a given item in the visual tree. 101 | /// 102 | /// A direct parent of the queried item. 103 | /// The type of the queried item. 104 | /// x:Name or Name of child. 105 | /// The first parent item that matches the submitted type parameter. 106 | /// If not matching item can be found, 107 | /// a null parent is being returned. 108 | public static T FindChild(this DependencyObject parent, string childName) 109 | where T : DependencyObject 110 | { 111 | // Confirm parent and childName are valid. 112 | if (parent == null) return null; 113 | 114 | T foundChild = null; 115 | 116 | int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 117 | for (int i = 0; i < childrenCount; i++) 118 | { 119 | var child = VisualTreeHelper.GetChild(parent, i); 120 | // If the child is not of the request child type child 121 | T childType = child as T; 122 | if (childType == null) 123 | { 124 | // recursively drill down the tree 125 | foundChild = FindChild(child, childName); 126 | // If the child is found, break so we do not overwrite the found child. 127 | if (foundChild != null) break; 128 | } 129 | else if (!string.IsNullOrEmpty(childName)) 130 | { 131 | var frameworkInputElement = child as IFrameworkInputElement; 132 | // If the child's name is set for search 133 | if (frameworkInputElement != null && frameworkInputElement.Name == childName) 134 | { 135 | // if the child's name is of the request name 136 | foundChild = (T)child; 137 | break; 138 | } 139 | else 140 | { 141 | // recursively drill down the tree 142 | foundChild = FindChild(child, childName); 143 | // If the child is found, break so we do not overwrite the found child. 144 | if (foundChild != null) break; 145 | } 146 | } 147 | else 148 | { 149 | // child element found. 150 | foundChild = (T)child; 151 | break; 152 | } 153 | } 154 | 155 | return foundChild; 156 | } 157 | 158 | /// 159 | /// Analyzes both visual and logical tree in order to find all elements of a given 160 | /// type that are descendants of the item. 161 | /// 162 | /// The type of the queried items. 163 | /// The root element that marks the source of the search. If the 164 | /// source is already of the requested type, it will not be included in the result. 165 | /// All descendants of that match the requested type. 166 | public static IEnumerable FindChildren(this DependencyObject source) where T : DependencyObject 167 | { 168 | if (source != null) 169 | { 170 | var childs = GetChildObjects(source); 171 | foreach (DependencyObject child in childs) 172 | { 173 | //analyze if children match the requested type 174 | if (child != null && child is T) 175 | { 176 | yield return (T)child; 177 | } 178 | 179 | //recurse tree 180 | foreach (T descendant in FindChildren(child)) 181 | { 182 | yield return descendant; 183 | } 184 | } 185 | } 186 | } 187 | 188 | 189 | /// 190 | /// This method is an alternative to WPF's 191 | /// method, which also 192 | /// supports content elements. Keep in mind that for content elements, 193 | /// this method falls back to the logical tree of the element. 194 | /// 195 | /// The item to be processed. 196 | /// Sometimes it's better to search in the VisualTree (e.g. in tests) 197 | /// The submitted item's child elements, if available. 198 | public static IEnumerable GetChildObjects(this DependencyObject parent, bool forceUsingTheVisualTreeHelper = false) 199 | { 200 | if (parent == null) yield break; 201 | 202 | if (!forceUsingTheVisualTreeHelper && (parent is ContentElement || parent is FrameworkElement)) 203 | { 204 | //use the logical tree for content / framework elements 205 | foreach (object obj in LogicalTreeHelper.GetChildren(parent)) 206 | { 207 | var depObj = obj as DependencyObject; 208 | if (depObj != null) yield return (DependencyObject)obj; 209 | } 210 | } 211 | else if (parent is Visual || parent is Visual3D) 212 | { 213 | //use the visual tree per default 214 | int count = VisualTreeHelper.GetChildrenCount(parent); 215 | for (int i = 0; i < count; i++) 216 | { 217 | yield return VisualTreeHelper.GetChild(parent, i); 218 | } 219 | } 220 | } 221 | 222 | #endregion 223 | 224 | #region Find From Point 225 | 226 | /// 227 | /// Tries to locate a given item within the visual tree, 228 | /// starting with the dependency object at a given position. 229 | /// 230 | /// The type of the element to be found 231 | /// on the visual tree of the element at the given location. 232 | /// The main element which is used to perform 233 | /// hit testing. 234 | /// The position to be evaluated on the origin. 235 | public static T TryFindFromPoint(UIElement reference, Point point) 236 | where T : DependencyObject 237 | { 238 | 239 | if (!(reference.InputHitTest(point) is DependencyObject element)) return null; 240 | else if (element is T) return (T)element; 241 | else return TryFindParent(element); 242 | } 243 | 244 | #endregion 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /AntWpf/Controls/ISpinable.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | /// 4 | /// Represents a spinable control. From https://github.com/charri/Font-Awesome-WPF/blob/master/src/WPF/FontAwesome.WPF/ISpinable.cs 5 | /// 6 | public interface ISpinable 7 | { 8 | bool? Spin { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /AntWpf/Controls/Shapes.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | public enum Shapes : byte 4 | { 5 | Circle, Square 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /AntWpf/Controls/Sizes.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | public enum Sizes 4 | { 5 | Large = -1, Small = -2 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /AntWpf/Controls/Switch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls.Primitives; 8 | using System.Windows.Media.Animation; 9 | 10 | 11 | namespace AntWpf.Controls 12 | { 13 | [TemplatePart(Name = PART_Dot, Type = typeof(FrameworkElement))] 14 | public class Switch : ToggleButton 15 | { 16 | #region Fields 17 | 18 | private const string PART_Dot = "PART_Dot"; 19 | 20 | private FrameworkElement dot; 21 | 22 | private VisualState pressedState; 23 | 24 | private Storyboard pressedStoryboard; 25 | 26 | #endregion 27 | 28 | #region Properties 29 | 30 | public static readonly DependencyProperty LoadingProperty = 31 | DependencyProperty.Register("Loading", typeof(bool), typeof(Switch), new PropertyMetadata(false)); 32 | 33 | /// 34 | /// Gets/sets loading state of switch. 35 | /// 36 | public bool Loading 37 | { 38 | get { return (bool)GetValue(LoadingProperty); } 39 | set { SetValue(LoadingProperty, value); } 40 | } 41 | 42 | public static readonly DependencyProperty SizeProperty = 43 | DependencyProperty.Register("Size", typeof(Sizes?), typeof(Switch), new PropertyMetadata(null)); 44 | 45 | /// 46 | /// Gets/sets the size of the switch. 47 | /// 48 | public Sizes? Size 49 | { 50 | get { return (Sizes?)GetValue(SizeProperty); } 51 | set { SetValue(SizeProperty, value); } 52 | } 53 | 54 | public static readonly DependencyProperty UnCheckedContentProperty = 55 | DependencyProperty.Register("UnCheckedContent", typeof(object), typeof(Switch), new PropertyMetadata(null)); 56 | 57 | /// 58 | /// Gets/sets content to be shown when the state is unchecked. 59 | /// 60 | public object UnCheckedContent 61 | { 62 | get { return GetValue(UnCheckedContentProperty); } 63 | set { SetValue(UnCheckedContentProperty, value); } 64 | } 65 | 66 | #endregion 67 | 68 | #region Constructors 69 | 70 | static Switch() 71 | { 72 | DefaultStyleKeyProperty.OverrideMetadata(typeof(Switch), new FrameworkPropertyMetadata(typeof(Switch))); 73 | } 74 | 75 | #endregion 76 | 77 | #region Overrides 78 | 79 | public override void OnApplyTemplate() 80 | { 81 | base.OnApplyTemplate(); 82 | 83 | dot = GetTemplateChild(PART_Dot) as FrameworkElement; 84 | pressedState = GetTemplateChild("Pressed") as VisualState; 85 | 86 | if (pressedState != null && pressedState.Storyboard != null) 87 | { 88 | pressedStoryboard = pressedState.Storyboard.Clone(); 89 | } 90 | } 91 | 92 | protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) 93 | { 94 | base.OnRenderSizeChanged(sizeInfo); 95 | SetDotAnimation(); 96 | } 97 | private bool DotAnimated = false; 98 | protected override void OnIsPressedChanged(DependencyPropertyChangedEventArgs e) 99 | { 100 | base.OnIsPressedChanged(e); 101 | //if (!DotAnimated) 102 | //{ 103 | if (dot != null /*&& IsChecked.HasValue && IsChecked.Value*/ && IsPressed) 104 | { 105 | var to = dot.Margin; 106 | // to.Left -= dot.ActualWidth * 1.3333 - dot.ActualWidth; 107 | to.Right -= dot.ActualWidth * 1.3333 - dot.ActualWidth; 108 | var ease = new CircleEase() { EasingMode = EasingMode.EaseInOut }; 109 | var animation = new ThicknessAnimation(to, TimeSpan.FromSeconds(0.36)) { EasingFunction = ease }; 110 | 111 | dot.BeginAnimation(MarginProperty, animation); 112 | } 113 | 114 | //else if (!IsPressed) DotAnimated = false; 115 | //} 116 | } 117 | 118 | private void SetDotAnimation() 119 | { 120 | if (dot == null || pressedState == null || DotAnimated) return; 121 | 122 | DotAnimated = true; 123 | var storyboard = pressedStoryboard != null ? pressedStoryboard.Clone() : new Storyboard(); 124 | var ease = new CircleEase() { EasingMode = EasingMode.EaseInOut }; 125 | var animation = new DoubleAnimation(dot.ActualWidth * 1.3333, TimeSpan.FromSeconds(0.36)) { EasingFunction = ease }; 126 | 127 | Storyboard.SetTargetName(animation, PART_Dot); 128 | Storyboard.SetTargetProperty(animation, new PropertyPath("Width")); 129 | 130 | storyboard.Children.Add(animation); 131 | pressedState.Storyboard = storyboard; 132 | } 133 | 134 | #endregion 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /AntWpf/Controls/Utils/CornerRadiusUtil.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System.Windows; 4 | 5 | public static class CornerRadiusUtil 6 | { 7 | /// 8 | /// Verifies if this CornerRadius contains only valid values 9 | /// The set of validity checks is passed as parameters. 10 | /// 11 | /// CornerRadius value 12 | /// allows negative values 13 | /// allows Double.NaN 14 | /// allows Double.PositiveInfinity 15 | /// allows Double.NegativeInfinity 16 | /// Whether or not the CornerRadius complies to the range specified 17 | public static bool IsValid(CornerRadius corner, bool allowNegative, bool allowNaN, bool allowPositiveInfinity, bool allowNegativeInfinity) 18 | { 19 | if (!allowNegative) 20 | { 21 | if (corner.TopLeft < 0d || corner.TopRight < 0d || corner.BottomLeft < 0d || corner.BottomRight < 0d) 22 | { 23 | return (false); 24 | } 25 | } 26 | 27 | if (!allowNaN) 28 | { 29 | if (DoubleUtil.IsNaN(corner.TopLeft) || DoubleUtil.IsNaN(corner.TopRight) || 30 | DoubleUtil.IsNaN(corner.BottomLeft) || DoubleUtil.IsNaN(corner.BottomRight)) 31 | { 32 | return (false); 33 | } 34 | } 35 | 36 | if (!allowPositiveInfinity) 37 | { 38 | if (double.IsPositiveInfinity(corner.TopLeft) || double.IsPositiveInfinity(corner.TopRight) || 39 | double.IsPositiveInfinity(corner.BottomLeft) || double.IsPositiveInfinity(corner.BottomRight)) 40 | { 41 | return (false); 42 | } 43 | } 44 | 45 | if (!allowNegativeInfinity) 46 | { 47 | if (double.IsNegativeInfinity(corner.TopLeft) || double.IsNegativeInfinity(corner.TopRight) || 48 | double.IsNegativeInfinity(corner.BottomLeft) || double.IsNegativeInfinity(corner.BottomRight)) 49 | { 50 | return (false); 51 | } 52 | } 53 | 54 | return true; 55 | } 56 | 57 | /// 58 | /// Verifies if the CornerRadius contains only zero values 59 | /// 60 | /// CornerRadius 61 | /// Size 62 | public static bool IsZero(CornerRadius corner) 63 | { 64 | return DoubleUtil.IsZero(corner.TopLeft) && DoubleUtil.IsZero(corner.TopRight) 65 | && DoubleUtil.IsZero(corner.BottomRight) && DoubleUtil.IsZero(corner.BottomLeft); 66 | } 67 | 68 | /// 69 | /// Verifies if the CornerRadius contains same values 70 | /// 71 | /// CornerRadius 72 | /// true if yes, otherwise false 73 | public static bool IsUniform(CornerRadius corner) 74 | { 75 | var topLeft = corner.TopLeft; 76 | return DoubleUtil.AreClose(topLeft, corner.TopRight) 77 | && DoubleUtil.AreClose(topLeft, corner.BottomRight) 78 | && DoubleUtil.AreClose(topLeft, corner.BottomLeft); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /AntWpf/Controls/Utils/DoubleUtil.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | internal static class DoubleUtil 7 | { 8 | // Const values 9 | // Smallest double value such that 1.0+DBL_EPSILON != 1.0 10 | internal const double DBL_EPSILON = 2.2204460492503131e-016; 11 | 12 | // Number close to zero, where float.MinValue is -float.MaxValue 13 | internal const float FLT_MIN = 1.175494351e-38F; 14 | 15 | /// 16 | /// AreClose - Returns whether or not two doubles are "close". That is, whether or 17 | /// not they are within epsilon of each other. Note that this epsilon is proportional 18 | /// to the numbers themselves to that AreClose survives scalar multiplication. 19 | /// There are plenty of ways for this to return false even for numbers which 20 | /// are theoretically identical, so no code calling this should fail to work if this 21 | /// returns false. This is important enough to repeat: 22 | /// NB: NO CODE CALLING THIS FUNCTION SHOULD DEPEND ON ACCURATE RESULTS - this should be 23 | /// used for optimizations *only*. 24 | /// 25 | /// 26 | /// bool - the result of the AreClose comparision. 27 | /// 28 | /// The first double to compare. 29 | /// The second double to compare. 30 | public static bool AreClose(double value1, double value2) 31 | { 32 | //in case they are Infinities (then epsilon check does not work) 33 | if (value1 == value2) return true; 34 | // This computes (|value1-value2| / (|value1| + |value2| + 10.0)) < DBL_EPSILON 35 | var eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON; 36 | var delta = value1 - value2; 37 | return (-eps < delta) && (eps > delta); 38 | } 39 | 40 | /// 41 | /// LessThan - Returns whether or not the first double is less than the second double. 42 | /// That is, whether or not the first is strictly less than *and* not within epsilon of 43 | /// the other number. Note that this epsilon is proportional to the numbers themselves 44 | /// to that AreClose survives scalar multiplication. Note, 45 | /// There are plenty of ways for this to return false even for numbers which 46 | /// are theoretically identical, so no code calling this should fail to work if this 47 | /// returns false. This is important enough to repeat: 48 | /// NB: NO CODE CALLING THIS FUNCTION SHOULD DEPEND ON ACCURATE RESULTS - this should be 49 | /// used for optimizations *only*. 50 | /// 51 | /// 52 | /// bool - the result of the LessThan comparision. 53 | /// 54 | /// The first double to compare. 55 | /// The second double to compare. 56 | public static bool LessThan(double value1, double value2) 57 | { 58 | return (value1 < value2) && !AreClose(value1, value2); 59 | } 60 | 61 | /// 62 | /// GreaterThan - Returns whether or not the first double is greater than the second double. 63 | /// That is, whether or not the first is strictly greater than *and* not within epsilon of 64 | /// the other number. Note that this epsilon is proportional to the numbers themselves 65 | /// to that AreClose survives scalar multiplication. Note, 66 | /// There are plenty of ways for this to return false even for numbers which 67 | /// are theoretically identical, so no code calling this should fail to work if this 68 | /// returns false. This is important enough to repeat: 69 | /// NB: NO CODE CALLING THIS FUNCTION SHOULD DEPEND ON ACCURATE RESULTS - this should be 70 | /// used for optimizations *only*. 71 | /// 72 | /// 73 | /// bool - the result of the GreaterThan comparision. 74 | /// 75 | /// The first double to compare. 76 | /// The second double to compare. 77 | public static bool GreaterThan(double value1, double value2) 78 | { 79 | return (value1 > value2) && !AreClose(value1, value2); 80 | } 81 | 82 | /// 83 | /// IsOne - Returns whether or not the double is "close" to 1. Same as AreClose(double, 1), 84 | /// but this is faster. 85 | /// 86 | /// 87 | /// bool - the result of the AreClose comparision. 88 | /// 89 | /// The double to compare to 1. 90 | public static bool IsOne(double value) 91 | { 92 | return Math.Abs(value - 1.0) < 10.0 * DBL_EPSILON; 93 | } 94 | 95 | /// 96 | /// IsZero - Returns whether or not the double is "close" to 0. Same as AreClose(double, 0), 97 | /// but this is faster. 98 | /// 99 | /// 100 | /// bool - the result of the AreClose comparision. 101 | /// 102 | /// The double to compare to 0. 103 | public static bool IsZero(double value) 104 | { 105 | return Math.Abs(value) < 10.0 * DBL_EPSILON; 106 | } 107 | 108 | [StructLayout(LayoutKind.Explicit)] 109 | private struct NanUnion 110 | { 111 | [FieldOffset(0)] 112 | internal double DoubleValue; 113 | [FieldOffset(0)] 114 | internal ulong UintValue; 115 | } 116 | 117 | // The standard CLR double.IsNaN() function is approximately 100 times slower than our own wrapper, 118 | // so please make sure to use DoubleUtil.IsNaN() in performance sensitive code. 119 | // PS item that tracks the CLR improvement is DevDiv Schedule : 26916. 120 | // IEEE 754 : If the argument is any value in the range 0x7ff0000000000001L through 0x7fffffffffffffffL 121 | // or in the range 0xfff0000000000001L through 0xffffffffffffffffL, the result will be NaN. 122 | public static bool IsNaN(double value) 123 | { 124 | var t = new NanUnion 125 | { 126 | DoubleValue = value 127 | }; 128 | 129 | var exp = t.UintValue & 0xfff0000000000000; 130 | var man = t.UintValue & 0x000fffffffffffff; 131 | 132 | return (exp == 0x7ff0000000000000 || exp == 0xfff0000000000000) && (man != 0); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /AntWpf/Controls/Utils/DpiUtil.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System.Windows; 4 | using System.Windows.Media; 5 | 6 | public static class DpiUtil 7 | { 8 | public static DpiScale GetDpi(Visual visual) 9 | { 10 | #if NET40 || NET45 11 | var source = PresentationSource.FromVisual(visual); 12 | 13 | if (source?.CompositionTarget == null) 14 | { 15 | return new DpiScale(1.0, 1.0); 16 | } 17 | 18 | var device = source.CompositionTarget.TransformToDevice; 19 | return new DpiScale(device.M11, device.M22); 20 | #else 21 | return VisualTreeHelper.GetDpi(visual); 22 | #endif 23 | } 24 | } 25 | 26 | #if NET40 || NET45 27 | /// Stores DPI information from which a or is rendered. 28 | public struct DpiScale 29 | { 30 | /// Gets the DPI scale on the X axis. 31 | /// The DPI scale for the X axis. 32 | public double DpiScaleX { get; private set; } 33 | 34 | /// Gets the DPI scale on the Yaxis. 35 | /// The DPI scale for the Y axis. 36 | public double DpiScaleY { get; private set; } 37 | 38 | /// Get or sets the PixelsPerDip at which the text should be rendered. 39 | /// The current value. 40 | public double PixelsPerDip 41 | { 42 | get 43 | { 44 | return DpiScaleY; 45 | } 46 | } 47 | 48 | /// Gets the DPI along X axis. 49 | /// The DPI along the X axis. 50 | public double PixelsPerInchX 51 | { 52 | get 53 | { 54 | return 96.0 * DpiScaleX; 55 | } 56 | } 57 | 58 | /// Gets the DPI along Y axis. 59 | /// The DPI along the Y axis. 60 | public double PixelsPerInchY 61 | { 62 | get 63 | { 64 | return 96.0 * DpiScaleY; 65 | } 66 | } 67 | 68 | /// Initializes a new instance of the structure. 69 | /// The DPI scale on the X axis. 70 | /// The DPI scale on the Y axis. 71 | public DpiScale(double dpiScaleX, double dpiScaleY) 72 | { 73 | DpiScaleX = dpiScaleX; 74 | DpiScaleY = dpiScaleY; 75 | } 76 | } 77 | #endif 78 | } 79 | -------------------------------------------------------------------------------- /AntWpf/Controls/Utils/RectUtil.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System; 4 | using System.Windows; 5 | 6 | internal static class RectUtil 7 | { 8 | /// 9 | /// Deflates rectangle by given thickness 10 | /// 11 | /// Rectangle 12 | /// Thickness 13 | /// Deflated Rectangle 14 | public static Rect Deflate(Rect rect, Thickness thick) 15 | { 16 | return new Rect(rect.Left + thick.Left, rect.Top + thick.Top, 17 | Math.Max(0.0, rect.Width - thick.Left - thick.Right), 18 | Math.Max(0.0, rect.Height - thick.Top - thick.Bottom)); 19 | } 20 | 21 | /// 22 | /// Inflates rectangle by given thickness 23 | /// 24 | /// Rectangle 25 | /// Thickness 26 | /// Inflated Rectangle 27 | public static Rect Inflate(Rect rect, Thickness thick) 28 | { 29 | return new Rect(rect.Left - thick.Left, rect.Top - thick.Top, 30 | Math.Max(0.0, rect.Width + thick.Left + thick.Right), 31 | Math.Max(0.0, rect.Height + thick.Top + thick.Bottom)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /AntWpf/Controls/Utils/Spinner.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Windows; 6 | using System.Windows.Media; 7 | using System.Windows.Media.Animation; 8 | 9 | /// 10 | /// Provides the ability to spin for controls. 11 | /// Known defects: 12 | /// Using trigger to change control RenderTransform property will result in animation lose. 13 | /// Try adding the Spin property Setter after the RenderTransform property Setter for notification purposes. 14 | /// Example: Theme/Switch.xaml 15 | /// 16 | public static class Spinner 17 | { 18 | private const string storyBoardName = "Antd.SpinnerStoryBoard"; 19 | 20 | /// 21 | /// Start the spinning animation. 22 | /// 23 | public static void BeginSpin(this T control, double seconds) where T : FrameworkElement, ISpinable 24 | { 25 | var transform = control.RenderTransform; 26 | control.SetCurrentValue(UIElement.RenderTransformOriginProperty, new Point(0.5, 0.5)); 27 | TransformGroup transformGroup; 28 | 29 | if (transform is TransformGroup) 30 | { 31 | if (!(((TransformGroup)transform).Children.FirstOrDefault() is RotateTransform)) 32 | { 33 | transformGroup = (TransformGroup)transform.Clone(); 34 | transformGroup.Children.Insert(0, new RotateTransform(0.0)); 35 | control.SetCurrentValue(UIElement.RenderTransformProperty, transformGroup); 36 | } 37 | } 38 | else 39 | { 40 | transformGroup = new TransformGroup(); 41 | 42 | if (transform is RotateTransform) 43 | { 44 | transformGroup.Children.Add(transform); 45 | } 46 | else 47 | { 48 | transformGroup.Children.Add(new RotateTransform(0.0)); 49 | 50 | if (transform != null && transform != Transform.Identity) 51 | { 52 | transformGroup.Children.Add(transform); 53 | } 54 | } 55 | 56 | control.SetCurrentValue(UIElement.RenderTransformProperty, transformGroup); 57 | } 58 | 59 | if (!(control.Resources[storyBoardName] is Storyboard storyboard)) 60 | { 61 | storyboard = new Storyboard(); 62 | var animation = new DoubleAnimation 63 | { 64 | From = 0, 65 | To = 360, 66 | AutoReverse = false, 67 | Duration = TimeSpan.FromSeconds(seconds), 68 | RepeatBehavior = RepeatBehavior.Forever 69 | }; 70 | 71 | Storyboard.SetTarget(animation, control); 72 | Storyboard.SetTargetProperty(animation, 73 | new PropertyPath("(0).(1)[0].(2)", UIElement.RenderTransformProperty, 74 | TransformGroup.ChildrenProperty, RotateTransform.AngleProperty)); 75 | 76 | storyboard.Children.Add(animation); 77 | control.Resources.Add(storyBoardName, storyboard); 78 | } 79 | 80 | storyboard.Begin(); 81 | } 82 | 83 | /// 84 | /// Stop the spinning animation. 85 | /// 86 | public static void StopSpin(this T control) where T : FrameworkElement, ISpinable 87 | { 88 | (control.Resources[storyBoardName] as Storyboard)?.Stop(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /AntWpf/Controls/Utils/ThicknessUtil.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System.Windows; 4 | 5 | internal static class ThicknessUtil 6 | { 7 | /// 8 | /// Verifies if this Thickness contains only valid values 9 | /// The set of validity checks is passed as parameters. 10 | /// 11 | /// Thickness value 12 | /// allows negative values 13 | /// allows Double.NaN 14 | /// allows Double.PositiveInfinity 15 | /// allows Double.NegativeInfinity 16 | /// Whether or not the thickness complies to the range specified 17 | public static bool IsValid(Thickness thick, bool allowNegative, bool allowNaN, bool allowPositiveInfinity, bool allowNegativeInfinity) 18 | { 19 | if (!allowNegative) 20 | { 21 | if (thick.Left < 0d || thick.Right < 0d || thick.Top < 0d || thick.Bottom < 0d) 22 | return false; 23 | } 24 | 25 | if (!allowNaN) 26 | { 27 | if (DoubleUtil.IsNaN(thick.Left) || DoubleUtil.IsNaN(thick.Right) 28 | || DoubleUtil.IsNaN(thick.Top) || DoubleUtil.IsNaN(thick.Bottom)) 29 | return false; 30 | } 31 | 32 | if (!allowPositiveInfinity) 33 | { 34 | if (double.IsPositiveInfinity(thick.Left) || double.IsPositiveInfinity(thick.Right) 35 | || double.IsPositiveInfinity(thick.Top) || double.IsPositiveInfinity(thick.Bottom)) 36 | { 37 | return false; 38 | } 39 | } 40 | 41 | if (!allowNegativeInfinity) 42 | { 43 | if (double.IsNegativeInfinity(thick.Left) || double.IsNegativeInfinity(thick.Right) 44 | || double.IsNegativeInfinity(thick.Top) || double.IsNegativeInfinity(thick.Bottom)) 45 | { 46 | return false; 47 | } 48 | } 49 | 50 | return true; 51 | } 52 | 53 | /// 54 | /// Method to add up the left and right size as width, as well as the top and bottom size as height 55 | /// 56 | /// Thickness 57 | /// Size 58 | public static Size CollapseThickness(Thickness thick) 59 | { 60 | return new Size(thick.Left + thick.Right, thick.Top + thick.Bottom); 61 | } 62 | 63 | /// 64 | /// Verifies if the Thickness contains only zero values 65 | /// 66 | /// Thickness 67 | /// Size 68 | public static bool IsZero(Thickness thick) 69 | { 70 | return DoubleUtil.IsZero(thick.Left) && DoubleUtil.IsZero(thick.Top) 71 | && DoubleUtil.IsZero(thick.Right) && DoubleUtil.IsZero(thick.Bottom); 72 | } 73 | 74 | /// 75 | /// Verifies if all the values in Thickness are same 76 | /// 77 | /// Thickness 78 | /// true if yes, otherwise false 79 | public static bool IsUniform(Thickness thick) 80 | { 81 | var left = thick.Left; 82 | return DoubleUtil.AreClose(left, thick.Top) 83 | && DoubleUtil.AreClose(left, thick.Right) 84 | && DoubleUtil.AreClose(left, thick.Bottom); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /AntWpf/Controls/Utils/UIElementUtil.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Controls 2 | { 3 | using System; 4 | 5 | public static class UIElementUtil 6 | { 7 | public static double RoundLayoutValue(double value, double dpiScale) 8 | { 9 | double newValue; 10 | 11 | // If DPI == 1, don't use DPI-aware rounding. 12 | if (!DoubleUtil.AreClose(dpiScale, 1.0)) 13 | { 14 | newValue = Math.Round(value * dpiScale) / dpiScale; 15 | // If rounding produces a value unacceptable to layout (NaN, Infinity or MaxValue), use the original value. 16 | if (double.IsNaN(newValue) || 17 | double.IsInfinity(newValue) || 18 | DoubleUtil.AreClose(newValue, double.MaxValue)) 19 | { 20 | newValue = value; 21 | } 22 | } 23 | else 24 | { 25 | newValue = Math.Round(value); 26 | } 27 | 28 | return newValue; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /AntWpf/Converters/ArcEndPointConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | using System.Windows.Markup; 6 | 7 | //https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/blob/master/src/MaterialDesignThemes.Wpf/Converters/CircularProgressBar/ArcEndPointConverter.cs 8 | 9 | namespace AntWpf.Converters 10 | { 11 | public class ArcEndPointConverter : MarkupExtension, IMultiValueConverter 12 | { 13 | /// 14 | /// CircularProgressBar draws two arcs to support a full circle at 100 %. 15 | /// With one arc at 100 % the start point is identical the end point, so nothing is drawn. 16 | /// Midpoint at half of current percentage is the endpoint of the first arc 17 | /// and the start point of the second arc. 18 | /// 19 | public const string ParameterMidPoint = "MidPoint"; 20 | 21 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 22 | { 23 | double actualWidth = values[0].ExtractDouble(); 24 | double value = values[1].ExtractDouble(); 25 | double minimum = values[2].ExtractDouble(); 26 | double maximum = values[3].ExtractDouble(); 27 | 28 | if (new[] { actualWidth, value, minimum, maximum }.AnyNan()) 29 | return Binding.DoNothing; 30 | 31 | if (values.Length == 5) 32 | { 33 | double fullIndeterminateScaling = values[4].ExtractDouble(); 34 | if (!double.IsNaN(fullIndeterminateScaling) && fullIndeterminateScaling > 0.0) 35 | { 36 | value = (maximum - minimum) * fullIndeterminateScaling; 37 | } 38 | } 39 | 40 | double percent = maximum <= minimum ? 1.0 : (value - minimum) / (maximum - minimum); 41 | if (Equals(parameter, ParameterMidPoint)) 42 | percent /= 2; 43 | 44 | double degrees = 360 * percent; 45 | double radians = degrees * (Math.PI / 180); 46 | 47 | var centre = new Point(actualWidth / 2, actualWidth / 2); 48 | double hypotenuseRadius = (actualWidth / 2); 49 | 50 | double adjacent = Math.Cos(radians) * hypotenuseRadius; 51 | double opposite = Math.Sin(radians) * hypotenuseRadius; 52 | 53 | return new Point(centre.X + opposite, centre.Y - adjacent); 54 | } 55 | 56 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException(); 57 | 58 | public override object ProvideValue(IServiceProvider serviceProvider) 59 | { 60 | return this; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /AntWpf/Converters/ArcSizeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | using System.Windows.Markup; 6 | 7 | //https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/blob/master/src/MaterialDesignThemes.Wpf/Converters/CircularProgressBar/ArcSizeConverter.cs 8 | 9 | 10 | namespace AntWpf.Converters 11 | { 12 | public class ArcSizeConverter : MarkupExtension, IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | => value is double v && (v > 0.0) ? new Size(v / 2, v / 2) : new Point(); 16 | 17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => Binding.DoNothing; 18 | 19 | public override object ProvideValue(IServiceProvider serviceProvider) 20 | { 21 | return this; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /AntWpf/Converters/ArithmeticConverter.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Converters 2 | { 3 | using System; 4 | using System.Globalization; 5 | using System.Windows; 6 | using System.Windows.Data; 7 | using System.Windows.Markup; 8 | 9 | public abstract class ArithmeticConverter : MarkupExtension, IValueConverter 10 | { 11 | public abstract double Convert(double value, Type targetType, double parameter, CultureInfo culture); 12 | 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | try 16 | { 17 | var val = (double)value; 18 | 19 | if (double.IsNaN(val)) 20 | { 21 | return value; 22 | } 23 | 24 | return Convert(val, targetType, double.Parse(parameter as string), culture); 25 | 26 | } catch { } 27 | 28 | return value; 29 | } 30 | 31 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 32 | { 33 | return DependencyProperty.UnsetValue; 34 | } 35 | public override object ProvideValue(IServiceProvider serviceProvider) 36 | { 37 | return this; 38 | } 39 | } 40 | 41 | public class AdditionConverter : ArithmeticConverter 42 | { 43 | public override double Convert(double value, Type targetType, double parameter, CultureInfo culture) 44 | { 45 | return value + parameter; 46 | } 47 | 48 | 49 | } 50 | 51 | public class SubtractionConverter : ArithmeticConverter 52 | { 53 | public override double Convert(double value, Type targetType, double parameter, CultureInfo culture) 54 | { 55 | return value - parameter; 56 | } 57 | } 58 | 59 | public class DultiplicationConverter : ArithmeticConverter 60 | { 61 | public override double Convert(double value, Type targetType, double parameter, CultureInfo culture) 62 | { 63 | return value * parameter; 64 | } 65 | } 66 | 67 | public class DivisionConverter : ArithmeticConverter 68 | { 69 | public override double Convert(double value, Type targetType, double parameter, CultureInfo culture) 70 | { 71 | // Divisor cannot be 0 72 | if (parameter == 0.0) 73 | { 74 | return value; 75 | } 76 | 77 | return value / parameter; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /AntWpf/Converters/DoubleToCornerRadiusConverter.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Converters 2 | { 3 | using System; 4 | using System.Globalization; 5 | using System.Windows; 6 | using System.Windows.Data; 7 | using System.Windows.Markup; 8 | 9 | [ValueConversion(typeof(double), typeof(CornerRadius))] 10 | public class DoubleToCornerRadiusConverter : MarkupExtension, IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | if (!(value is double)) 15 | { 16 | return default(CornerRadius); 17 | } 18 | 19 | var d = (double)value; 20 | 21 | if (double.IsNaN(d) || d < 1) 22 | { 23 | d = 0; 24 | } else 25 | { 26 | // May require 50% rounded corners 27 | double.TryParse(parameter as string, out double val); 28 | 29 | if (val > 0) 30 | { 31 | d /= val; 32 | } 33 | } 34 | 35 | return new CornerRadius(d); 36 | } 37 | 38 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 39 | { 40 | return DependencyProperty.UnsetValue; 41 | } 42 | 43 | public override object ProvideValue(IServiceProvider serviceProvider) 44 | { 45 | return this; 46 | } 47 | } 48 | 49 | [ValueConversion(typeof(CornerRadius), typeof(double))] 50 | public class CornerRadiusToDoubleConverter : IValueConverter 51 | { 52 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 53 | { 54 | if (!(value is CornerRadius)) 55 | { 56 | return default(double); 57 | } 58 | 59 | var cornerRadius = (CornerRadius)value; 60 | return Math.Max(cornerRadius.TopLeft, Math.Max(cornerRadius.TopRight, Math.Max(cornerRadius.BottomRight, cornerRadius.BottomLeft))); 61 | } 62 | 63 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 64 | { 65 | return DependencyProperty.UnsetValue; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /AntWpf/Converters/DoubleToThicknessMultiConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using System.Windows.Markup; 9 | using System.Windows; 10 | 11 | namespace AntWpf.Converters 12 | { 13 | public class DoubleToThicknessMultiConverter : MarkupExtension, IMultiValueConverter 14 | { 15 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | var parent = values[0] as double?; 18 | var self = values[1] as double?; 19 | 20 | if (parent == null || self == null) 21 | { 22 | return default(Thickness); 23 | } 24 | 25 | double.TryParse(parameter as string, out double param); 26 | return new Thickness(parent.Value - self.Value - param, 0.0, 0.0, 0.0); 27 | } 28 | 29 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 30 | { 31 | return targetTypes.Select(t => DependencyProperty.UnsetValue).ToArray(); 32 | } 33 | 34 | public override object ProvideValue(IServiceProvider serviceProvider) 35 | { 36 | return this; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /AntWpf/Converters/LessThanConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using System.Windows.Markup; 9 | 10 | namespace AntWpf.Converters 11 | { 12 | public class LessThanConverter : MarkupExtension, IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | double v = value.ExtractDouble(); 17 | double p = parameter.ExtractDouble(); 18 | 19 | return v < p; 20 | 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | 28 | public override object ProvideValue(IServiceProvider serviceProvider) 29 | { 30 | return this; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /AntWpf/Converters/LocalEx.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | //https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/blob/master/src/MaterialDesignThemes.Wpf/Converters/CircularProgressBar/LocalEx.cs 5 | 6 | namespace AntWpf.Converters 7 | { 8 | internal static class LocalEx 9 | { 10 | public static double ExtractDouble(this object value) 11 | { 12 | double d = value as double? ?? double.NaN; 13 | return double.IsInfinity(d) ? double.NaN : d; 14 | } 15 | 16 | 17 | public static bool AnyNan(this IEnumerable values) => values.Any(double.IsNaN); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /AntWpf/Converters/MathConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using System.Windows.Markup; 9 | 10 | namespace AntWpf.Converters 11 | { 12 | public enum MathOperation 13 | { 14 | Add, 15 | Divide, 16 | Multiply, 17 | Subtract, 18 | Pow 19 | } 20 | public sealed class MathConverter : MarkupExtension, IValueConverter 21 | { 22 | public MathOperation Operation { get; set; } 23 | 24 | public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) 25 | { 26 | try 27 | { 28 | double value1 = System.Convert.ToDouble(value, CultureInfo.InvariantCulture); 29 | double value2 = System.Convert.ToDouble(parameter, CultureInfo.InvariantCulture); 30 | switch (Operation) 31 | { 32 | case MathOperation.Add: 33 | return value1 + value2; 34 | case MathOperation.Divide: 35 | return value1 / value2; 36 | case MathOperation.Multiply: 37 | return value1 * value2; 38 | case MathOperation.Subtract: 39 | return value1 - value2; 40 | case MathOperation.Pow: 41 | return Math.Pow(value1, value2); 42 | default: 43 | return Binding.DoNothing; 44 | } 45 | } 46 | catch (FormatException) 47 | { 48 | return Binding.DoNothing; 49 | } 50 | } 51 | 52 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 53 | => Binding.DoNothing; 54 | 55 | public override object ProvideValue(IServiceProvider serviceProvider) 56 | { 57 | return this; 58 | } 59 | 60 | 61 | } 62 | 63 | public sealed class MathMultiConverter : MarkupExtension, IMultiValueConverter 64 | { 65 | public MathOperation Operation { get; set; } 66 | 67 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 68 | { 69 | try 70 | { 71 | double value1 = System.Convert.ToDouble(values[0], CultureInfo.InvariantCulture); 72 | double value2 = System.Convert.ToDouble(values[1], CultureInfo.InvariantCulture); 73 | switch (Operation) 74 | { 75 | case MathOperation.Add: 76 | return value1 + value2; 77 | case MathOperation.Divide: 78 | return value1 / value2; 79 | case MathOperation.Multiply: 80 | return value1 * value2; 81 | case MathOperation.Subtract: 82 | return value1 - value2; 83 | case MathOperation.Pow: 84 | return Math.Pow(value1, value2); 85 | default: 86 | return Binding.DoNothing; 87 | } 88 | } 89 | catch (FormatException) 90 | { 91 | return Binding.DoNothing; 92 | } 93 | } 94 | 95 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 96 | { 97 | throw new NotImplementedException(); 98 | } 99 | 100 | public override object ProvideValue(IServiceProvider serviceProvider) 101 | { 102 | return this; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /AntWpf/Converters/StartPointConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | using System.Windows.Markup; 6 | 7 | namespace AntWpf.Converters 8 | { 9 | public class StartPointConverter : MarkupExtension, IValueConverter 10 | { 11 | [Obsolete] 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | if (value is double v && (v > 0.0)) 15 | { 16 | return new Point(v / 2, 0); 17 | } 18 | 19 | return new Point(); 20 | } 21 | 22 | [Obsolete] 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => Binding.DoNothing; 24 | 25 | public override object ProvideValue(IServiceProvider serviceProvider) 26 | { 27 | return this; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /AntWpf/Converters/ThicknessReverseConverter.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Converters 2 | { 3 | using System; 4 | using System.Globalization; 5 | using System.Windows; 6 | using System.Windows.Data; 7 | using System.Windows.Markup; 8 | 9 | [ValueConversion(typeof(Thickness), typeof(Thickness))] 10 | public class ThicknessReverseConverter : MarkupExtension, IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | var thickness = (Thickness)value; 15 | 16 | thickness.Left *= -1; 17 | thickness.Top *= -1; 18 | 19 | thickness.Right *= -1; 20 | thickness.Bottom *= -1; 21 | 22 | return thickness; 23 | } 24 | 25 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 26 | { 27 | return DependencyProperty.UnsetValue; 28 | } 29 | 30 | public override object ProvideValue(IServiceProvider serviceProvider) 31 | { 32 | return this; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /AntWpf/Converters/ThicknessToDoubleConverter.cs: -------------------------------------------------------------------------------- 1 | namespace AntWpf.Converters 2 | { 3 | using System; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Windows; 7 | using System.Windows.Data; 8 | using System.Windows.Markup; 9 | 10 | [ValueConversion(typeof(Thickness), typeof(double))] 11 | public class ThicknessToDoubleConverter : MarkupExtension, IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | if (!(value is Thickness)) 16 | { 17 | return default(double); 18 | } 19 | 20 | var thickness = (Thickness)value; 21 | var d = Math.Max(thickness.Left, Math.Max(thickness.Top, Math.Max(thickness.Right, thickness.Bottom))); 22 | 23 | // If it is a shape, it may be necessary to discard approximately 0.2px to remove the sawtooth. 24 | // Recorded in: Window10 x64, xiaomi laptop pro15.6 25 | // The cause of this problem is DPI. 26 | //if (bool.Parse(parameter as string)) 27 | //{ 28 | // d -= d * 0.176; 29 | //} 30 | 31 | return d; 32 | } 33 | 34 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 35 | { 36 | return DependencyProperty.UnsetValue; 37 | } 38 | 39 | public override object ProvideValue(IServiceProvider serviceProvider) 40 | { 41 | return this; 42 | } 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /AntWpf/LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /AntWpf/README.md: -------------------------------------------------------------------------------- 1 | # AntWpf 2 | A UI framework using [ant design](https://ant.design/docs/spec/introduce) language to help developers build their own WPF applications. 3 | 4 | ##### Under development, not suitable for production environment 5 | 6 | # GETTING STARTED 7 | 8 | ``` 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ``` 20 | ## Buttons 21 | 22 | ![Buttons](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/buttons.png?raw=true) 23 | ``` 24 | xmlns:Ant="clr-namespace:AntWpf.Controls;assembly=AntWpf" 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ``` 35 | ## Inputs 36 | 37 | ![Inputs](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/inputs.png?raw=true) 38 | ``` 39 | xmlns:Ant="clr-namespace:AntWpf.Controls;assembly=AntWpf" 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ``` 51 | # CheckBoxes & RadioButtons 52 | 53 | ![Inputs](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/check_radios.png?raw=true) 54 | ``` 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ``` 72 | # ProgressBars 73 | 74 | ![Inputs](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/progress_bar.png?raw=true) 75 | ``` 76 | 77 | 78 | 79 | 80 | 81 | 82 | ``` 83 | # Icons 84 | 85 | ![Inputs](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/icons.png?raw=true) 86 | ``` 87 | 88 | ``` 89 | [![AntDesign](https://img.shields.io/nuget/dt/AntWpf)](https://www.nuget.org/packages/AntWpf/) 90 | [![AntDesign](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](https://github.com/Mumtozbekov/AntWpf/blob/master/AntWpf/LICENSE.txt) 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /AntWpf/Styles/Animations.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 32 | 38 | 39 | 40 | 46 | 52 | 58 | 59 | 60 | 61 | 62 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /AntWpf/Styles/AntIcon.xaml: -------------------------------------------------------------------------------- 1 |  4 | 28 | -------------------------------------------------------------------------------- /AntWpf/Styles/AntIcons.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | M567.7 514.9l254.8-254.6c15.4-15.4 15.4-40.3 0-55.6-15.4-15.4-40.3-15.4-55.6 0L512 459.2 257.1 204.6c-15.4-15.4-40.3-15.4-55.6 0-15.4 15.4-15.4 40.3 0 55.6l254.8 254.6-254.8 254.7c-15.4 15.4-15.4 40.3 0 55.6 7.7 7.7 17.8 11.5 27.8 11.5 10.1 0 20.1-3.8 27.8-11.5L512 570.5l254.9 254.7c7.7 7.7 17.7 11.5 27.8 11.5 10.1 0 20.1-3.8 27.8-11.5 15.4-15.4 15.4-40.3 0-55.6L567.7 514.9z 7 | M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3-22.2-52.4-53.9-99.4-94.3-139.9-40.4-40.4-87.5-72.2-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3 0.1 19.9-16 36-35.9 36z 8 | M512 384c19.9 0 36-16.1 36-36V36c0-19.9-16.1-36-36-36s-36 16.1-36 36v312c0 19.9 16.1 36 36 36zM512 1024c-69.1 0-136.2-13.5-199.3-40.2C251.7 958 197 921 150 874c-47-47-84-101.7-109.8-162.7C13.5 648.2 0 581.1 0 512c0-81.3 18.5-159.1 55-231.2 34.8-68.7 85.7-129.7 147.2-176.5 15.8-12 38.4-9 50.4 6.8s9 38.4-6.8 50.4c-52.8 40.2-96.6 92.7-126.5 151.7C87.9 375.3 72 442.1 72 512c0 59.4 11.6 117 34.6 171.3 22.2 52.4 53.9 99.5 94.3 139.9 40.4 40.4 87.5 72.2 139.9 94.3C395 940.4 452.6 952 512 952c59.4 0 117-11.6 171.3-34.6 52.4-22.2 99.5-53.9 139.9-94.3 40.4-40.4 72.2-87.5 94.3-139.9C940.4 629 952 571.4 952 512c0-69.9-15.9-136.7-47.3-198.6-29.9-59.1-73.7-111.5-126.5-151.7-15.8-12-18.9-34.6-6.8-50.4 12-15.8 34.6-18.9 50.4-6.8C883.2 151.3 934.1 212.3 969 281c36.5 72.1 55 149.8 55 231.2 0 69.1-13.5 136.2-40.2 199.3C958 772.3 921 827 874 874s-101.8 83.9-162.7 109.7c-63.1 26.8-130.2 40.3-199.3 40.3z 9 | M949.5 898.5L743.8 692.9C798.9 626.4 832 541.1 832 448c0-212.1-171.9-384-384-384S64 235.9 64 448s171.9 384 384 384c93.1 0 178.4-33.1 244.9-88.2l205.7 205.7c7 7 16.2 10.5 25.5 10.5s18.4-3.5 25.5-10.5c13.9-14.1 13.9-36.9-0.1-51z m-380.1-163C531 751.8 490.2 760 448 760s-83-8.2-121.4-24.5c-37.1-15.7-70.5-38.2-99.2-66.9-28.7-28.7-51.2-62.1-66.9-99.2C144.2 531 136 490.2 136 448s8.2-83 24.5-121.4c15.7-37.1 38.2-70.5 66.9-99.2 28.7-28.7 62.1-51.2 99.2-66.9C365 144.2 405.8 136 448 136s83 8.2 121.4 24.5c37.1 15.7 70.5 38.2 99.2 66.9 28.7 28.7 51.2 62.1 66.9 99.2C751.8 365 760 405.8 760 448s-8.2 83-24.5 121.4c-15.7 37.1-38.2 70.5-66.9 99.2-28.7 28.7-62 51.2-99.2 66.9z 10 | M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z 11 | M721.3 305.6L393.8 634.1l-85.4-149.5c-9.9-17.3-31.8-23.3-49.1-13.4S236 503 245.9 520.3l108.8 190.5c6.6 11.6 18.8 18.2 31.3 18.2 6.1 0 12.2-1.5 17.8-4.7 3.2-1.9 6.1-4.1 8.5-6.7l0.4-0.4 359.5-360.6c14-14.1 14-36.9-0.1-50.9-14-14.2-36.7-14.2-50.8-0.1zM512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9z 12 | M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9zM630.2 705.6H545V355.5c0-19.9-16.1-36-36-36h-96c-19.9 0-36 16.1-36 36s16.1 36 36 36h60v314.1h-85.2c-19.9 0-36 16.1-36 36s16.1 36 36 36H630.2c19.9 0 36-16.1 36-36s-16.1-36-36-36zM473 220.5a36 36 0 1 0 72 0 36 36 0 1 0-72 0z 13 | M512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512s-11.6 117-34.5 171.2c-22.2 52.4-53.9 99.4-94.3 139.9-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952s-117-11.6-171.2-34.5c-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512s11.6-117 34.5-171.2c22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72m0-72C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m0 640c-22.1 0-40-17.9-40-40V231c0-22.1 17.9-40 40-40s40 17.9 40 40v369c0 22.1-17.9 40-40 40z m-45 109a45 45 0 1 0 90 0 45 45 0 1 0-90 0z 14 | M717.2 306.2c-14.1-14-36.9-14-50.9 0.1L512 461 357.7 306.3c-14-14.1-36.8-14.1-50.9-0.1-14.1 14-14.1 36.8-0.1 50.9L461.2 512 306.7 666.9c-14 14.1-14 36.9 0.1 50.9 7 7 16.2 10.5 25.4 10.5s18.5-3.5 25.5-10.6L512 563l154.3 154.8c7 7.1 16.3 10.6 25.5 10.6s18.4-3.5 25.4-10.5c14.1-14 14.1-36.8 0.1-50.9L562.8 512l154.4-154.9c14.1-14.1 14.1-36.9 0-50.9zM512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9z 15 | M963.4 511.7c-0.3-5.6-8.9-33.3-20.9-62.1-12.3-29.7-33.1-72.7-61.9-108.6-37.7-47.2-84.2-84.9-138.2-111.9-66.3-33.3-143.9-50.1-230.5-50.1-86.5 0-164.1 16.9-230.4 50.2C227.9 256 181.4 293.6 143.3 341c-28.8 36-49.5 79-61.8 108.7-12 28.8-20.5 56.5-20.8 62.1v0.4c0.3 5.6 8.9 33.3 20.9 62.2 12.4 29.7 33.1 72.7 61.8 108.5 37.7 47.2 84.2 84.9 138.2 111.9 66.7 33.4 144.2 50.3 230.4 50.3 86.3 0 163.8-16.9 230.4-50.3 53.8-26.9 100.3-64.6 138.2-111.8 28.8-35.9 49.6-78.9 61.9-108.6 12-28.8 20.6-56.5 20.9-62.1v-0.2-0.4z m-74.2 0.2c-5.7 17.4-27.8 80.2-64.4 125.8l-0.5 0.5c-31.1 39-69.6 70.1-114.3 92.6-56.5 28.3-123.3 42.7-198.4 42.7-75.2 0-141.9-14.4-198.4-42.7-44.6-22.3-83-53.5-114.3-92.7-36.8-45.8-59-108.8-64.7-126.3 5.7-17.4 27.9-80.3 64.7-126.3 31.4-39.2 69.9-70.3 114.4-92.6 56.6-28.3 123.4-42.6 198.6-42.6 75.5 0 142.2 14.3 198.3 42.6 44.6 22.3 83 53.5 114.3 92.7 36.8 46 59 108.9 64.7 126.3zM511.9 337.8c-95.6 0-173.3 77.8-173.3 173.3s77.8 173.3 173.3 173.3 173.3-77.8 173.3-173.3-77.7-173.3-173.3-173.3z m102 173.3c0 27.2-10.6 52.8-29.9 72.1-19.3 19.3-44.9 29.9-72.1 29.9-27.2 0-52.8-10.6-72.1-29.9-19.3-19.3-29.9-44.9-29.9-72.1 0-27.2 10.6-52.8 29.9-72.1 19.3-19.3 44.9-29.9 72.1-29.9 27.2 0 52.8 10.6 72.1 29.9 19.3 19.3 29.9 44.9 29.9 72.1z 16 | M895.7 300.1c0 9.6-3.2 19.3-9.6 27.4L545.2 751.3c-8.3 10.3-20.8 16.3-34.1 16.3-13.2 0-25.8-6-34-16.3L138 329.3c-15.1-18.8-12.1-46.3 6.7-61.4 18.8-15.1 46.3-12.1 61.4 6.7l305.1 379.6L818 272.7c15.1-18.8 42.6-21.8 61.4-6.7 10.7 8.7 16.3 21.3 16.3 34.1z 17 | M895.7 659.9c0-9.6-3.2-19.3-9.6-27.4L545.2 208.7c-8.3-10.3-20.8-16.3-34.1-16.3-13.2 0-25.8 6-34 16.3L138 630.7c-15.1 18.8-12.1 46.3 6.7 61.4 18.8 15.1 46.3 12.1 61.4-6.7l305.1-379.6L818 687.3c15.1 18.8 42.6 21.8 61.4 6.7 10.7-8.7 16.3-21.3 16.3-34.1z 18 | M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM332 240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224H332V240z m460 600H232V536h560v304zM484 701v53c0 4.4 3.6 8 8 8h40c4.4 0 8-3.6 8-8v-53c12.1-8.7 20-22.9 20-39 0-26.5-21.5-48-48-48s-48 21.5-48 48c0 16.1 7.9 30.3 20 39z 19 | 20 | 21 | M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m260.3 356.4L412.8 717.1l-0.4 0.4c-2.4 2.6-5.3 4.9-8.5 6.7-5.6 3.2-11.8 4.7-17.8 4.7-12.5 0-24.7-6.5-31.3-18.2L245.9 520.3C236 503 242 481 259.3 471.2c17.3-9.9 39.3-3.9 49.1 13.4l85.4 149.5 327.5-328.5c14-14.1 36.8-14.1 50.9-0.1 14.1 14.1 14.1 36.9 0.1 50.9z 22 | M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m-3 184.5c19.9 0 36 16.1 36 36s-16.1 36-36 36-36-16.1-36-36 16.1-36 36-36z m157.2 557.1c0 19.9-16.1 36-36 36H387.8c-19.9 0-36-16.1-36-36s16.1-36 36-36H473V391.5h-60c-19.9 0-36-16.1-36-36s16.1-36 36-36h96c19.9 0 36 16.1 36 36v350.1h85.2c19.9 0 36 16.1 36 36z 23 | M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m-40 231c0-22.1 17.9-40 40-40s40 17.9 40 40v369c0 22.1-17.9 40-40 40s-40-17.9-40-40V231z m40 563c-24.9 0-45-20.1-45-45s20.1-45 45-45 45 20.1 45 45c0 24.8-20.1 45-45 45z 24 | M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m205.3 666.9c14 14.1 14 36.9-0.1 50.9-7 7-16.2 10.5-25.4 10.5s-18.5-3.5-25.5-10.6L512 563 357.7 717.7c-7 7.1-16.3 10.6-25.5 10.6s-18.4-3.5-25.4-10.5c-14.1-14-14.1-36.8-0.1-50.9L461.2 512 306.7 357.1c-14-14.1-14-36.9 0.1-50.9s36.9-14 50.9 0.1L512 461l154.3-154.8c14-14.1 36.8-14.1 50.9-0.1 14.1 14 14.1 36.8 0.1 50.9L562.8 512l154.5 154.9z 25 | M512.5 390.6c-29.9 0-57.9 11.6-79.1 32.8-21.1 21.2-32.8 49.2-32.8 79.1 0 29.9 11.7 57.9 32.8 79.1 21.2 21.1 49.2 32.8 79.1 32.8 29.9 0 57.9-11.7 79.1-32.8 21.1-21.2 32.8-49.2 32.8-79.1 0-29.9-11.7-57.9-32.8-79.1-21.2-21.2-49.2-32.8-79.1-32.8zM924.8 626.1l-65.4-55.9c3.1-19 4.7-38.4 4.7-57.7s-1.6-38.8-4.7-57.7l65.4-55.9c10.1-8.6 13.8-22.6 9.3-35.2l-0.9-2.6c-18.1-50.4-44.8-96.8-79.6-137.7l-1.8-2.1c-8.6-10.1-22.5-13.9-35.1-9.5l-81.2 28.9c-30-24.6-63.4-44-99.6-57.5l-15.7-84.9c-2.4-13.1-12.7-23.3-25.8-25.7l-2.7-0.5c-52-9.4-106.8-9.4-158.8 0l-2.7 0.5c-13.1 2.4-23.4 12.6-25.8 25.7l-15.8 85.3c-35.9 13.6-69.1 32.9-98.9 57.3l-81.8-29.1c-12.5-4.4-26.5-0.7-35.1 9.5l-1.8 2.1c-34.8 41.1-61.5 87.4-79.6 137.7l-0.9 2.6c-4.5 12.5-0.8 26.5 9.3 35.2l66.2 56.5c-3.1 18.8-4.6 38-4.6 57 0 19.2 1.5 38.4 4.6 57l-66 56.5c-10.1 8.6-13.8 22.6-9.3 35.2l0.9 2.6c18.1 50.3 44.8 96.8 79.6 137.7l1.8 2.1c8.6 10.1 22.5 13.9 35.1 9.5l81.8-29.1c29.8 24.5 63 43.9 98.9 57.3l15.8 85.3c2.4 13.1 12.7 23.3 25.8 25.7l2.7 0.5c26.1 4.7 52.7 7.1 79.4 7.1 26.7 0 53.4-2.4 79.4-7.1l2.7-0.5c13.1-2.4 23.4-12.6 25.8-25.7l15.7-84.9c36.2-13.6 69.6-32.9 99.6-57.5l81.2 28.9c12.5 4.4 26.5 0.7 35.1-9.5l1.8-2.1c34.8-41.1 61.5-87.4 79.6-137.7l0.9-2.6c4.3-12.4 0.6-26.3-9.5-35z m-412.3 52.2c-97.1 0-175.8-78.7-175.8-175.8s78.7-175.8 175.8-175.8 175.8 78.7 175.8 175.8-78.7 175.8-175.8 175.8z 26 | M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM540 701v53c0 4.4-3.6 8-8 8h-40c-4.4 0-8-3.6-8-8v-53c-12.1-8.7-20-22.9-20-39 0-26.5 21.5-48 48-48s48 21.5 48 48c0 16.1-7.9 30.3-20 39z m152-237H332V240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224z 27 | 28 | -------------------------------------------------------------------------------- /AntWpf/Styles/CheckBox.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 176 | 177 | -------------------------------------------------------------------------------- /AntWpf/Styles/Control.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 10 | 11 | 19 | -------------------------------------------------------------------------------- /AntWpf/Styles/Controls.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 44 | 45 | 46 | 63 | 64 | 65 | 73 | 74 | -------------------------------------------------------------------------------- /AntWpf/Styles/RadioButton.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 90 | -------------------------------------------------------------------------------- /AntWpf/Styles/Slider.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | 26 | 27 | 100 | 101 | 102 | 104 | 105 | 106 | 107 | 109 | 110 | 111 | 116 | 117 | 118 | 119 | 120 | 127 | 128 | 129 | 131 | 132 | 134 | 135 | 136 | 137 | 138 | 139 | 141 | 142 | 143 | 150 | 151 | 152 | 154 | 157 | 158 | 160 | 163 | 164 | 166 | 169 | 172 | 173 | 174 | 175 | 176 | 177 | 179 | 180 | 181 | 182 | 184 | 185 | 186 | 191 | 192 | 193 | 194 | 195 | 196 | 203 | 204 | 205 | 207 | 208 | 210 | 211 | 212 | 213 | 214 | 215 | 217 | 218 | 219 | 226 | 227 | 228 | 230 | 233 | 234 | 236 | 239 | 240 | 242 | 245 | 248 | 249 | 250 | 251 | 252 | 278 | -------------------------------------------------------------------------------- /AntWpf/Styles/TextBox.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 131 | 132 | -------------------------------------------------------------------------------- /AntWpf/ant_wpf.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/AntWpf/ant_wpf.ico -------------------------------------------------------------------------------- /AntWpf/images/buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/AntWpf/images/buttons.png -------------------------------------------------------------------------------- /AntWpf/images/check_radios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/AntWpf/images/check_radios.png -------------------------------------------------------------------------------- /AntWpf/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/AntWpf/images/icons.png -------------------------------------------------------------------------------- /AntWpf/images/inputs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/AntWpf/images/inputs.png -------------------------------------------------------------------------------- /AntWpf/images/logos_ant-design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/AntWpf/images/logos_ant-design.png -------------------------------------------------------------------------------- /AntWpf/images/progress_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/AntWpf/images/progress_bar.png -------------------------------------------------------------------------------- /AntWpf/logos_ant-design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/AntWpf/logos_ant-design.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AntWpf 2 | A UI framework using [ant design](https://ant.design/docs/spec/introduce) language to help developers build their own WPF applications. 3 | 4 | ##### Under development, not suitable for production environment 5 | 6 | # GETTING STARTED 7 | 8 | ``` 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ``` 20 | ## Buttons 21 | 22 | ![Buttons](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/buttons.png?raw=true) 23 | ``` 24 | xmlns:Ant="clr-namespace:AntWpf.Controls;assembly=AntWpf" 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ``` 35 | ## Inputs 36 | 37 | ![Inputs](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/inputs.png?raw=true) 38 | ``` 39 | xmlns:Ant="clr-namespace:AntWpf.Controls;assembly=AntWpf" 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ``` 51 | # CheckBoxes & RadioButtons 52 | 53 | ![Inputs](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/check_radios.png?raw=true) 54 | ``` 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ``` 72 | # ProgressBars 73 | 74 | ![Inputs](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/progress_bar.png?raw=true) 75 | ``` 76 | 77 | 78 | 79 | 80 | 81 | 82 | ``` 83 | # Icons 84 | 85 | ![Inputs](https://github.com/mumtozbekov/AntWpf/blob/master/AntWpf/images/icons.png?raw=true) 86 | ``` 87 | 88 | ``` 89 | [![AntDesign](https://img.shields.io/nuget/dt/AntWpf)](https://www.nuget.org/packages/AntWpf/) 90 | [![AntDesign](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](https://github.com/Mumtozbekov/AntWpf/blob/master/AntWpf/LICENSE.txt) 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /logos_ant-design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mumtozbekov/AntWpf/8cbe9e3d09904afead7240f39dd52170d30115d0/logos_ant-design.png --------------------------------------------------------------------------------