├── .editorconfig ├── .gitattributes ├── .gitignore ├── .gitmodules ├── CONTRIBUTING.md ├── Directory.Build.props ├── OHOS_Project ├── .gitignore ├── AppScope │ ├── app.json5 │ └── resources │ │ └── base │ │ ├── element │ │ └── string.json │ │ └── media │ │ ├── app_icon.png │ │ └── startIcon.png ├── build-profile.json5 ├── code-linter.json5 ├── entry │ ├── .gitignore │ ├── build-profile.json5 │ ├── hvigorfile.ts │ ├── obfuscation-rules.txt │ ├── oh-package-lock.json5 │ ├── oh-package.json5 │ └── src │ │ ├── main │ │ ├── cpp │ │ │ ├── CMakeLists.txt │ │ │ ├── napi_init.cpp │ │ │ └── types │ │ │ │ └── libentry │ │ │ │ ├── Index.d.ts │ │ │ │ └── oh-package.json5 │ │ ├── ets │ │ │ ├── entryability │ │ │ │ └── EntryAbility.ets │ │ │ ├── entrybackupability │ │ │ │ └── EntryBackupAbility.ets │ │ │ └── pages │ │ │ │ └── Index.ets │ │ ├── module.json5 │ │ └── resources │ │ │ ├── base │ │ │ ├── element │ │ │ │ ├── color.json │ │ │ │ ├── float.json │ │ │ │ └── string.json │ │ │ ├── media │ │ │ │ ├── background.png │ │ │ │ ├── foreground.png │ │ │ │ ├── layered_image.json │ │ │ │ └── startIcon.png │ │ │ └── profile │ │ │ │ ├── backup_config.json │ │ │ │ └── main_pages.json │ │ │ └── dark │ │ │ └── element │ │ │ └── color.json │ │ ├── mock │ │ ├── Libentry.mock.ets │ │ └── mock-config.json5 │ │ ├── ohosTest │ │ ├── ets │ │ │ └── test │ │ │ │ ├── Ability.test.ets │ │ │ │ └── List.test.ets │ │ └── module.json5 │ │ └── test │ │ ├── List.test.ets │ │ └── LocalUnit.test.ets ├── hvigor │ └── hvigor-config.json5 ├── hvigorfile.ts ├── oh-package-lock.json5 └── oh-package.json5 ├── OpenHarmony.Avalonia.sln ├── README.en.md ├── README.md └── Src ├── Avalonia.OpenHarmony ├── Assets │ └── HarmonyOS_Sans_Regular.ttf ├── Avalonia.OpenHarmony.csproj ├── AvaloniaXComponent.cs ├── ClipboardImpl.cs ├── CursorFactory.cs ├── FramebufferManager.cs ├── OHDebugHelper.cs ├── OpenHarmonyApplicationExtensions.cs ├── OpenHarmonyFontManagerImpl.cs ├── OpenHarmonyFramebuffer.cs ├── OpenHarmonyInputMethod.cs ├── OpenHarmonyInputPane.cs ├── OpenHarmonyKeyboardDevice.cs ├── OpenHarmonyPlatform.cs ├── OpenHarmonyPlatformSettings.cs ├── OpenHarmonyPlatformThreading.cs ├── OpenHarmonyRenderTimer.cs ├── OpenHarmonyRuntimePlatform.cs ├── OpenHarmonyStorageProvider │ ├── OpenHarmonyStorageBookmarkFile.cs │ ├── OpenHarmonyStorageBookmarkFolder.cs │ ├── OpenHarmonyStorageBookmarkItemBase.cs │ └── OpenHarmonyStorageProvider.cs ├── SingleViewLifetime.cs ├── TopLevelImpl.cs ├── XComponent.cs └── libs │ ├── Avalonia.Skia │ └── Avalonia.Skia.dll │ ├── HarfBuzzSharp │ └── HarfBuzzSharp.dll │ └── SkiaSharp │ └── SkiaSharp.dll ├── Entry ├── Entry.csproj ├── Properties │ └── PublishProfiles │ │ ├── PublishAmd64.pubxml │ │ └── PublishArm64.pubxml ├── XComponentEntry.cs ├── napi_init.cs ├── rd.xml └── runtimes │ ├── arm64-v8a │ ├── libHarfBuzzSharp.so │ ├── libSkiaSharp.so │ ├── libbrotlicommon.so.1 │ ├── libbrotlicommon.so.1.1.0 │ ├── libbrotlidec.so.1 │ ├── libbrotlidec.so.1.1.0 │ ├── libbrotlienc.so.1 │ ├── libbrotlienc.so.1.1.0 │ ├── libbz2.so.1 │ ├── libbz2.so.1.0.8 │ ├── libexpat.so.1 │ ├── libexpat.so.1.9.3 │ ├── libfontconfig.so.1 │ ├── libfontconfig.so.1.12.1 │ ├── libfreetype.so.6 │ ├── libfreetype.so.6.20.2 │ ├── libpng16.so.16 │ ├── libpng16.so.16.44.0 │ ├── libz.so.1 │ └── libz.so.1.3.1 │ └── x86_64 │ ├── libHarfBuzzSharp.so │ ├── libSkiaSharp.so │ ├── libbrotlicommon.so.1 │ ├── libbrotlicommon.so.1.1.0 │ ├── libbrotlidec.so.1 │ ├── libbrotlidec.so.1.1.0 │ ├── libbrotlienc.so.1 │ ├── libbrotlienc.so.1.1.0 │ ├── libbz2.so.1 │ ├── libbz2.so.1.0.8 │ ├── libexpat.so.1 │ ├── libexpat.so.1.10.0 │ ├── libfontconfig.so.1 │ ├── libfontconfig.so.1.12.1 │ ├── libfreetype.so.6 │ ├── libfreetype.so.6.20.2 │ ├── libpng16.so.16 │ ├── libpng16.so.16.44.0 │ ├── libz.so.1 │ └── libz.so.1.3.1 └── Example ├── AOOH_Gallery.Desktop ├── AOOH_Gallery.Desktop.csproj ├── Program.cs └── app.manifest ├── AOOH_Gallery ├── AOOH_Gallery.csproj ├── App.axaml ├── App.axaml.cs ├── Assets │ ├── Gallery Home 背景图片.png │ ├── OpenHarmony.Net组织头像.png │ └── avalonia-logo.ico ├── ViewLocator.cs ├── ViewModels │ ├── MainViewViewModel.cs │ └── ViewModelBase.cs └── Views │ ├── FQA.axaml │ ├── FQA.axaml.cs │ ├── IMEPage.axaml │ ├── IMEPage.axaml.cs │ ├── MainView.axaml │ ├── MainView.axaml.cs │ ├── MainWindow.axaml │ ├── MainWindow.axaml.cs │ ├── StorgePage.axaml │ ├── StorgePage.axaml.cs │ ├── SystemFonts.axaml │ └── SystemFonts.axaml.cs ├── AvaloniaApp.Desktop ├── AvaloniaApp.Desktop.csproj ├── Program.cs ├── Properties │ └── launchSettings.json └── app.manifest └── AvaloniaApp ├── App.axaml ├── App.axaml.cs ├── Assets ├── O1CN01T2ugeo1gJT57UONrC_!!0-item_pic.jpg ├── appreciate_fill_light.png ├── apps (1).png ├── avalonia-logo.ico ├── deliver_fill.png ├── emoji1.png ├── emoji2.png ├── emoji3.png ├── emoji4.png ├── group (1).png ├── home.png ├── home_fill_light.png ├── mark.png ├── mark_fill.png ├── money_bag_fill.png ├── news_hot_fill_light.png ├── news_hot_light.png ├── people.png ├── people_fill.png ├── right.png ├── round_right_fill.png ├── search (1).png ├── search.png └── test_image.png ├── AvaloniaApp.csproj ├── ViewLocator.cs ├── ViewModels ├── HomePageViewModel.cs ├── MainViewModel.cs ├── MessagePageViewModel.cs ├── NewsPageViewModel.cs ├── ProfilePageViewModel.cs └── ViewModelBase.cs └── Views ├── HomePageView.axaml ├── HomePageView.axaml.cs ├── MainView.axaml ├── MainView.axaml.cs ├── MainWindow.axaml ├── MainWindow.axaml.cs ├── MessagePageView.axaml ├── MessagePageView.axaml.cs ├── NewsPageView.axaml ├── NewsPageView.axaml.cs ├── ProfilePageView.axaml └── ProfilePageView.axaml.cs /.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 364 | /OHOS_Project/entry/libs/arm64-v8a/* 365 | /OHOS_Project/entry/libs/x86_64/* 366 | 367 | 368 | # Jetbrains 369 | .idea -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ThirdParty/PublishAotCross"] 2 | path = ThirdParty/PublishAotCross 3 | url = https://github.com/OpenHarmony-NET/PublishAotCross 4 | [submodule "ThirdParty/OpenHarmony.NET.Runtime"] 5 | path = ThirdParty/OpenHarmony.NET.Runtime 6 | url = https://github.com/OpenHarmony-NET/OpenHarmony.NET.Runtime 7 | [submodule "ThirdParty/OpenHarmony.NDK.Bindings"] 8 | path = ThirdParty/OpenHarmony.NDK.Bindings 9 | url = https://github.com/OpenHarmony-NET/OpenHarmony.NDK.Bindings 10 | [submodule "ThirdParty/Ursa.Avalonia"] 11 | path = ThirdParty/Ursa.Avalonia 12 | url = https://github.com/WCKYWCKF/Ursa.Avalonia 13 | branch = oh 14 | [submodule "ThirdParty/Semi.Avalonia"] 15 | path = ThirdParty/Semi.Avalonia 16 | url = https://github.com/WCKYWCKF/Semi.Avalonia 17 | branch = oh 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | The key words "**must**", "**must not**", "**should**", "**should not**" and "**may**" in this document are to be interpreted as described in [RFC 2119](http://www.ietf.org/rfc/rfc2119.txt). 4 | 5 | ## Code of Conduct 6 | 7 | This project is adopting the [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) as its Code of Conduct. 8 | 9 | 10 | ## Opening Issues 11 | 12 | Whenever you find a bug or think of a new feature, you **may** open an issue on the [issue tracker](https://github.com/OpenHarmony-NET/OpenHarmony.Avalonia) **if they are not already reported**. 13 | 14 | ### Reporting Bugs 15 | 16 | When reporting a bug, you **should** include the following information: 17 | 18 | - Version or commit hash of the library 19 | - A minimum (non) working example 20 | - Steps to reproduce the bug 21 | - Expected behavior 22 | - Actual behavior 23 | - Screenshots or logs (if applicable) 24 | 25 | And you **must** also provide a descriptive title and you **should** provide the relevant informations as possible. 26 | 27 | ### Requesting Features 28 | 29 | You **should** ensure that the feature you are requesting is not already implemented or requested. 30 | 31 | You **must** provide its use case and a clear description of the feature. 32 | 33 | You **should** provide code snippets or screenshots to illustrate your request. 34 | 35 | ## Sending Pull Requests 36 | 37 | To be accepted, your code contribution **must** following the current `editorconfig` rules and the code style of the project. 38 | 39 | You **should** writting unit tests for your code, if applicable. If you are meeting difficulties on writing unit tests, we **may** help you. 40 | 41 | You **should** create a new branch from the `main` branch and name it according to the feature or bug you are working on. 42 | 43 | And your commit history **should** be clean and well formatted: 44 | 45 | - We are using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) to structure our commit messages. 46 | Template: 47 | ``` 48 | [optional scope]: 49 | 50 | [optional body] 51 | 52 | [optional footer(s)] 53 | ``` 54 | [For more information](https://www.conventionalcommits.org/en/v1.0.0/#specification) 55 | 56 | 57 | ## Conversions 58 | 59 | - We are usiing [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html) to version our library. 60 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | enable 4 | 11.2.2 5 | 6 | 7 | -------------------------------------------------------------------------------- /OHOS_Project/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /oh_modules 3 | /local.properties 4 | /.idea 5 | **/build 6 | /.hvigor 7 | .cxx 8 | /.clangd 9 | /.clang-format 10 | /.clang-tidy 11 | **/.test 12 | /.appanalyzer -------------------------------------------------------------------------------- /OHOS_Project/AppScope/app.json5: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "bundleName": "com.example.avalonia", 4 | "vendor": "example", 5 | "versionCode": 1000000, 6 | "versionName": "1.0.0", 7 | "icon": "$media:app_icon", 8 | "label": "$string:app_name" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /OHOS_Project/AppScope/resources/base/element/string.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": [ 3 | { 4 | "name": "app_name", 5 | "value": "AvaloniaApp" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /OHOS_Project/AppScope/resources/base/media/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/OHOS_Project/AppScope/resources/base/media/app_icon.png -------------------------------------------------------------------------------- /OHOS_Project/AppScope/resources/base/media/startIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/OHOS_Project/AppScope/resources/base/media/startIcon.png -------------------------------------------------------------------------------- /OHOS_Project/build-profile.json5: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "signingConfigs": [], 4 | "products": [ 5 | { 6 | "name": "default", 7 | "signingConfig": "default", 8 | "compatibleSdkVersion": "5.0.1(13)", 9 | "runtimeOS": "HarmonyOS", 10 | "buildOption": { 11 | "strictMode": { 12 | "caseSensitiveCheck": true, 13 | "useNormalizedOHMUrl": true 14 | } 15 | } 16 | } 17 | ], 18 | "buildModeSet": [ 19 | { 20 | "name": "debug", 21 | }, 22 | { 23 | "name": "release" 24 | } 25 | ] 26 | }, 27 | "modules": [ 28 | { 29 | "name": "entry", 30 | "srcPath": "./entry", 31 | "targets": [ 32 | { 33 | "name": "default", 34 | "applyToProducts": [ 35 | "default" 36 | ] 37 | } 38 | ] 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /OHOS_Project/code-linter.json5: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "**/*.ets" 4 | ], 5 | "ignore": [ 6 | "**/src/ohosTest/**/*", 7 | "**/src/test/**/*", 8 | "**/src/mock/**/*", 9 | "**/node_modules/**/*", 10 | "**/oh_modules/**/*", 11 | "**/build/**/*", 12 | "**/.preview/**/*" 13 | ], 14 | "ruleSet": [ 15 | "plugin:@performance/recommended", 16 | "plugin:@typescript-eslint/recommended" 17 | ], 18 | "rules": { 19 | "@security/no-unsafe-aes": "error", 20 | "@security/no-unsafe-hash": "error", 21 | "@security/no-unsafe-mac": "warn", 22 | "@security/no-unsafe-dh": "error", 23 | "@security/no-unsafe-dsa": "error", 24 | "@security/no-unsafe-ecdsa": "error", 25 | "@security/no-unsafe-rsa-encrypt": "error", 26 | "@security/no-unsafe-rsa-sign": "error", 27 | "@security/no-unsafe-rsa-key": "error", 28 | "@security/no-unsafe-dsa-key": "error", 29 | "@security/no-unsafe-dh-key": "error", 30 | "@security/no-unsafe-3des": "error" 31 | } 32 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /oh_modules 3 | /.preview 4 | /build 5 | /.cxx 6 | /.test -------------------------------------------------------------------------------- /OHOS_Project/entry/build-profile.json5: -------------------------------------------------------------------------------- 1 | { 2 | "apiType": "stageMode", 3 | "buildOption": { 4 | "externalNativeOptions": { 5 | "path": "./src/main/cpp/CMakeLists.txt", 6 | "arguments": "", 7 | "cppFlags": "", 8 | "abiFilters": ["arm64-v8a", "x86_64"] 9 | } 10 | }, 11 | "buildOptionSet": [ 12 | { 13 | "name": "release", 14 | "arkOptions": { 15 | "obfuscation": { 16 | "ruleOptions": { 17 | "enable": false, 18 | "files": [ 19 | "./obfuscation-rules.txt" 20 | ] 21 | } 22 | } 23 | }, 24 | "nativeLib": { 25 | "debugSymbol": { 26 | "strip": true, 27 | "exclude": [] 28 | } 29 | } 30 | }, 31 | ], 32 | "targets": [ 33 | { 34 | "name": "default" 35 | }, 36 | { 37 | "name": "ohosTest", 38 | } 39 | ] 40 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/hvigorfile.ts: -------------------------------------------------------------------------------- 1 | import { hapTasks } from '@ohos/hvigor-ohos-plugin'; 2 | 3 | export default { 4 | system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ 5 | plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ 6 | } 7 | -------------------------------------------------------------------------------- /OHOS_Project/entry/obfuscation-rules.txt: -------------------------------------------------------------------------------- 1 | # Define project specific obfuscation rules here. 2 | # You can include the obfuscation configuration files in the current module's build-profile.json5. 3 | # 4 | # For more details, see 5 | # https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 6 | 7 | # Obfuscation options: 8 | # -disable-obfuscation: disable all obfuscations 9 | # -enable-property-obfuscation: obfuscate the property names 10 | # -enable-toplevel-obfuscation: obfuscate the names in the global scope 11 | # -compact: remove unnecessary blank spaces and all line feeds 12 | # -remove-log: remove all console.* statements 13 | # -print-namecache: print the name cache that contains the mapping from the old names to new names 14 | # -apply-namecache: reuse the given cache file 15 | 16 | # Keep options: 17 | # -keep-property-name: specifies property names that you want to keep 18 | # -keep-global-name: specifies names that you want to keep in the global scope 19 | 20 | -enable-property-obfuscation 21 | -enable-toplevel-obfuscation 22 | -enable-filename-obfuscation 23 | -enable-export-obfuscation -------------------------------------------------------------------------------- /OHOS_Project/entry/oh-package-lock.json5: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "stableOrder": true 4 | }, 5 | "lockfileVersion": 3, 6 | "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", 7 | "specifiers": { 8 | "libentry.so@src/main/cpp/types/libentry": "libentry.so@src/main/cpp/types/libentry" 9 | }, 10 | "packages": { 11 | "libentry.so@src/main/cpp/types/libentry": { 12 | "name": "libentry.so", 13 | "version": "1.0.0", 14 | "resolved": "src/main/cpp/types/libentry", 15 | "registryType": "local" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/oh-package.json5: -------------------------------------------------------------------------------- 1 | { 2 | "name": "entry", 3 | "version": "1.0.0", 4 | "description": "Please describe the basic information.", 5 | "main": "", 6 | "author": "", 7 | "license": "", 8 | "dependencies": { 9 | "libentry.so": "file:./src/main/cpp/types/libentry" 10 | } 11 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # the minimum version of CMake. 2 | cmake_minimum_required(VERSION 3.5.0) 3 | project(OHOS_Project) 4 | 5 | set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 6 | 7 | if(DEFINED PACKAGE_FIND_FILE) 8 | include(${PACKAGE_FIND_FILE}) 9 | endif() 10 | 11 | include_directories(${NATIVERENDER_ROOT_PATH} 12 | ${NATIVERENDER_ROOT_PATH}/include) 13 | 14 | add_library(entry SHARED napi_init.cpp) 15 | target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libnative_drawing.so) -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/cpp/napi_init.cpp: -------------------------------------------------------------------------------- 1 | #include "napi/native_api.h" 2 | #include 3 | #include 4 | #include 5 | #include "napi/native_api.h" 6 | #include 7 | #include 8 | #include 9 | 10 | extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { 11 | auto handle = dlopen("libavalonia.so", RTLD_NOW); 12 | assert(handle != nullptr); 13 | auto func = (void (*)())dlsym(handle, "RegisterEntryModule"); 14 | assert(func != nullptr); 15 | func(); 16 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/cpp/types/libentry/Index.d.ts: -------------------------------------------------------------------------------- 1 | export const setStartDocumentViewPicker: (cbFn: (maxSelectNumber: number, defaultFilePathUri: string, 2 | fileSuffixFilters: Array, selectMode: number, authMod: boolean) => void) => void; 3 | 4 | export const setStartDocumentViewPickerSaveMode: (cbFn: (newFileNames: Array, defaultFilePathUri: string, 5 | fileSuffixChoices: Array, pickerMode: number) => void) => void; 6 | 7 | export const setPickerResult: (result: Array) => void; 8 | 9 | export const setColor: (colorMode: number) => void; 10 | export const setInputPaneHeight: (keyboardHeightChange: number) => void; -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/cpp/types/libentry/oh-package.json5: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libentry.so", 3 | "types": "./Index.d.ts", 4 | "version": "1.0.0", 5 | "description": "Please describe the basic information." 6 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/ets/entryability/EntryAbility.ets: -------------------------------------------------------------------------------- 1 | import { AbilityConstant, Configuration, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; 2 | import { hilog } from '@kit.PerformanceAnalysisKit'; 3 | import { window } from '@kit.ArkUI'; 4 | import { picker } from '@kit.CoreFileKit'; 5 | import { fileIo as fs } from '@kit.CoreFileKit'; 6 | import { common } from '@kit.AbilityKit'; 7 | import { BusinessError } from '@kit.BasicServicesKit'; 8 | import * as avalonia from 'libentry.so' 9 | import { uri } from '@kit.ArkTS'; 10 | 11 | const DOMAIN = 0x0000; 12 | 13 | function returnNumber() { 14 | return 10; 15 | } 16 | 17 | export default class EntryAbility extends UIAbility { 18 | onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { 19 | this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); 20 | hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); 21 | //将文件选择器的触发器注册到.Net中 22 | avalonia.setStartDocumentViewPicker((maxSelectNumber: number, defaultFilePathUri: string, 23 | fileSuffixFilters: Array, selectMode: number, authMod: boolean) => { 24 | const documentSelectOptions = new picker.DocumentSelectOptions(); 25 | // 选择文档的最大数目(可选)。 26 | documentSelectOptions.maxSelectNumber = maxSelectNumber; 27 | hilog.info(DOMAIN, 'testTag', 'maxSelectNumber:' + maxSelectNumber); 28 | // 指定选择的文件或者目录路径(可选)。 29 | documentSelectOptions.defaultFilePathUri = defaultFilePathUri; 30 | // 选择文件的后缀类型['后缀类型描述|后缀类型'](可选,不传该参数,默认不过滤,即显示所有文件),若选择项存在多个后缀名,则每一个后缀名之间用英文逗号进行分隔(可选),后缀类型名不能超过100。此外2in1设备支持通过通配符方式['所有文件(*.*)|.*'],表示为显示所有文件,手机暂不支持该配置。 31 | documentSelectOptions.fileSuffixFilters = fileSuffixFilters 32 | //选择是否对指定文件或目录授权,true为授权,当为true时,defaultFilePathUri为必选参数,拉起文管授权界面;false为非授权(默认为false),拉起常规文管界面(可选),仅支持2in1设备。 33 | documentSelectOptions.authMode = authMod; 34 | documentSelectOptions.selectMode = selectMode; 35 | //批量授权模式,默认为false(非批量授权模式)。当multAuthMode为true时为批量授权模式。当multAuthMode为true时,只有multiUriArray参数生效,其他参数不生效。仅支持手机设备。 36 | //documentSelectOptions.multiAuthMode = false; 37 | //需要传入批量授权的uri数组(仅支持文件,文件夹不生效)。配合multAuthMode使用。当multAuthMode为false时,配置该参数不生效。仅支持手机设备。 38 | //documentSelectOptions.multiUriArray = 39 | // ["file://docs/storage/Users/currentUser/test", "file://docs/storage/Users/currentUser/2test"]; 40 | //开启聚合视图模式,支持拉起文件管理应用的聚合视图。默认为DEFAULT,表示该参数不生效,非聚合视图。当该参数置为非DEFAULT时,其他参数不生效。仅支持手机设备。 41 | //documentSelectOptions.mergeMode = picker.MergeTypeMode.DEFAULT; 42 | let uris: Array = []; 43 | let context = getContext(this) as common.Context; // 请确保 getContext(this) 返回结果为 UIAbilityContext 44 | // 创建文件选择器实例 45 | const documentViewPicker = new picker.DocumentViewPicker(context); 46 | documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array) => { 47 | //文件选择成功后,返回被选中文档的URI结果集。 48 | uris = documentSelectResult; 49 | console.info('documentViewPicker.select to file succeed and uris are:' + uris); 50 | }).catch((err: BusinessError) => { 51 | console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`); 52 | }).finally(() => { 53 | avalonia.setPickerResult(uris); 54 | }) 55 | }) 56 | avalonia.setStartDocumentViewPickerSaveMode((newFileNames: Array, defaultFilePathUri: string, 57 | fileSuffixChoices: Array, pickerMode: number) => { 58 | let result: Array = []; 59 | let documentSaveOptions = new picker.DocumentSaveOptions(); 60 | documentSaveOptions.newFileNames = newFileNames; 61 | documentSaveOptions.defaultFilePathUri = defaultFilePathUri; 62 | documentSaveOptions.fileSuffixChoices = fileSuffixChoices; 63 | documentSaveOptions.pickerMode = pickerMode; 64 | const documentPicker = new picker.DocumentViewPicker(getContext(this) as common.Context); 65 | documentPicker.save(documentSaveOptions).then((documentSaveResult: Array) => { 66 | console.info('DocumentViewPicker.save successfully, documentSaveResult uri: ' + 67 | JSON.stringify(documentSaveResult)); 68 | result = documentSaveResult; 69 | }).catch((err: BusinessError) => { 70 | console.error('DocumentViewPicker.save failed with err: ' + JSON.stringify(err)); 71 | }).finally(() => { 72 | avalonia.setPickerResult(result); 73 | }); 74 | }); 75 | } 76 | 77 | onDestroy(): void { 78 | hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); 79 | } 80 | 81 | onWindowStageCreate(windowStage: window.WindowStage): void { 82 | // Main window is created, set main page for this ability 83 | hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); 84 | windowStage.loadContent('pages/Index', (err) => { 85 | if (err.code) { 86 | hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); 87 | return; 88 | } 89 | windowStage.getMainWindow().then(w => { 90 | w.setWindowLayoutFullScreen(true) 91 | w.setPreferredOrientation(window.Orientation.AUTO_ROTATION) 92 | w.on('keyboardHeightChange', (data: number) => { 93 | avalonia.setInputPaneHeight(px2vp(data)); 94 | }) 95 | }) 96 | hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); 97 | }); 98 | } 99 | 100 | onConfigurationUpdate(newConfig: Configuration): void { 101 | avalonia.setColor(newConfig.colorMode); 102 | } 103 | 104 | onWindowStageDestroy(): void { 105 | // Main window is destroyed, release UI related resources 106 | hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); 107 | } 108 | 109 | onForeground(): void { 110 | // Ability has brought to foreground 111 | hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); 112 | } 113 | 114 | onBackground(): void { 115 | // Ability has back to background 116 | hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); 117 | } 118 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets: -------------------------------------------------------------------------------- 1 | import { hilog } from '@kit.PerformanceAnalysisKit'; 2 | import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; 3 | 4 | const DOMAIN = 0x0000; 5 | 6 | export default class EntryBackupAbility extends BackupExtensionAbility { 7 | async onBackup() { 8 | hilog.info(DOMAIN, 'testTag', 'onBackup ok'); 9 | await Promise.resolve(); 10 | } 11 | 12 | async onRestore(bundleVersion: BundleVersion) { 13 | hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); 14 | await Promise.resolve(); 15 | } 16 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/ets/pages/Index.ets: -------------------------------------------------------------------------------- 1 | @Entry 2 | @Component 3 | struct Index { 4 | @State message: string = 'Hello World'; 5 | 6 | build() { 7 | Row() { 8 | XComponent({ type: XComponentType.SURFACE, id: 'AvaloniaRootComponent', libraryname: "entry" }) 9 | } 10 | .height('100%') 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/module.json5: -------------------------------------------------------------------------------- 1 | { 2 | "module": { 3 | "name": "entry", 4 | "type": "entry", 5 | "description": "$string:module_desc", 6 | "mainElement": "EntryAbility", 7 | "deviceTypes": [ 8 | "phone", 9 | "tablet", 10 | "2in1", 11 | "car" 12 | ], 13 | "deliveryWithInstall": true, 14 | "installationFree": false, 15 | "pages": "$profile:main_pages", 16 | "abilities": [ 17 | { 18 | "name": "EntryAbility", 19 | "srcEntry": "./ets/entryability/EntryAbility.ets", 20 | "description": "$string:EntryAbility_desc", 21 | "icon": "$media:layered_image", 22 | "label": "$string:EntryAbility_label", 23 | "startWindowIcon": "$media:startIcon", 24 | "startWindowBackground": "$color:start_window_background", 25 | "exported": true, 26 | "orientation": "auto_rotation", 27 | "skills": [ 28 | { 29 | "entities": [ 30 | "entity.system.home" 31 | ], 32 | "actions": [ 33 | "action.system.home" 34 | ] 35 | } 36 | ] 37 | } 38 | ], 39 | "extensionAbilities": [ 40 | { 41 | "name": "EntryBackupAbility", 42 | "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", 43 | "type": "backup", 44 | "exported": false, 45 | "metadata": [ 46 | { 47 | "name": "ohos.extension.backup", 48 | "resource": "$profile:backup_config" 49 | } 50 | ], 51 | } 52 | ] 53 | } 54 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/element/color.json: -------------------------------------------------------------------------------- 1 | { 2 | "color": [ 3 | { 4 | "name": "start_window_background", 5 | "value": "#FFFFFF" 6 | }, 7 | { 8 | "name": "icon_background", 9 | "value": "#FFFFFF" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/element/float.json: -------------------------------------------------------------------------------- 1 | { 2 | "float": [ 3 | { 4 | "name": "page_text_font_size", 5 | "value": "50fp" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/element/string.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": [ 3 | { 4 | "name": "module_desc", 5 | "value": "module description" 6 | }, 7 | { 8 | "name": "EntryAbility_desc", 9 | "value": "description" 10 | }, 11 | { 12 | "name": "EntryAbility_label", 13 | "value": "AvaloniaApp" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/media/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/OHOS_Project/entry/src/main/resources/base/media/background.png -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/media/foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/OHOS_Project/entry/src/main/resources/base/media/foreground.png -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/media/layered_image.json: -------------------------------------------------------------------------------- 1 | { 2 | "layered-image": 3 | { 4 | "background" : "$media:background", 5 | "foreground" : "$media:foreground" 6 | } 7 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/media/startIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/OHOS_Project/entry/src/main/resources/base/media/startIcon.png -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/profile/backup_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "allowToBackupRestore": true 3 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/base/profile/main_pages.json: -------------------------------------------------------------------------------- 1 | { 2 | "src": [ 3 | "pages/Index" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /OHOS_Project/entry/src/main/resources/dark/element/color.json: -------------------------------------------------------------------------------- 1 | { 2 | "color": [ 3 | { 4 | "name": "start_window_background", 5 | "value": "#000000" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/mock/Libentry.mock.ets: -------------------------------------------------------------------------------- 1 | const NativeMock: Record = { 2 | 'add': (a: number, b: number) => { 3 | return a + b; 4 | }, 5 | }; 6 | 7 | export default NativeMock; -------------------------------------------------------------------------------- /OHOS_Project/entry/src/mock/mock-config.json5: -------------------------------------------------------------------------------- 1 | { 2 | "libentry.so": { 3 | "source": "src/mock/Libentry.mock.ets" 4 | } 5 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/ohosTest/ets/test/Ability.test.ets: -------------------------------------------------------------------------------- 1 | import { hilog } from '@kit.PerformanceAnalysisKit'; 2 | import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; 3 | 4 | export default function abilityTest() { 5 | describe('ActsAbilityTest', () => { 6 | // Defines a test suite. Two parameters are supported: test suite name and test suite function. 7 | beforeAll(() => { 8 | // Presets an action, which is performed only once before all test cases of the test suite start. 9 | // This API supports only one parameter: preset action function. 10 | }) 11 | beforeEach(() => { 12 | // Presets an action, which is performed before each unit test case starts. 13 | // The number of execution times is the same as the number of test cases defined by **it**. 14 | // This API supports only one parameter: preset action function. 15 | }) 16 | afterEach(() => { 17 | // Presets a clear action, which is performed after each unit test case ends. 18 | // The number of execution times is the same as the number of test cases defined by **it**. 19 | // This API supports only one parameter: clear action function. 20 | }) 21 | afterAll(() => { 22 | // Presets a clear action, which is performed after all test cases of the test suite end. 23 | // This API supports only one parameter: clear action function. 24 | }) 25 | it('assertContain', 0, () => { 26 | // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. 27 | hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); 28 | let a = 'abc'; 29 | let b = 'b'; 30 | // Defines a variety of assertion methods, which are used to declare expected boolean conditions. 31 | expect(a).assertContain(b); 32 | expect(a).assertEqual(a); 33 | }) 34 | }) 35 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/ohosTest/ets/test/List.test.ets: -------------------------------------------------------------------------------- 1 | import abilityTest from './Ability.test'; 2 | 3 | export default function testsuite() { 4 | abilityTest(); 5 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/ohosTest/module.json5: -------------------------------------------------------------------------------- 1 | { 2 | "module": { 3 | "name": "entry_test", 4 | "type": "feature", 5 | "deviceTypes": [ 6 | "phone", 7 | "tablet", 8 | "2in1", 9 | "car" 10 | ], 11 | "deliveryWithInstall": true, 12 | "installationFree": false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /OHOS_Project/entry/src/test/List.test.ets: -------------------------------------------------------------------------------- 1 | import localUnitTest from './LocalUnit.test'; 2 | 3 | export default function testsuite() { 4 | localUnitTest(); 5 | } -------------------------------------------------------------------------------- /OHOS_Project/entry/src/test/LocalUnit.test.ets: -------------------------------------------------------------------------------- 1 | import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; 2 | 3 | export default function localUnitTest() { 4 | describe('localUnitTest', () => { 5 | // Defines a test suite. Two parameters are supported: test suite name and test suite function. 6 | beforeAll(() => { 7 | // Presets an action, which is performed only once before all test cases of the test suite start. 8 | // This API supports only one parameter: preset action function. 9 | }); 10 | beforeEach(() => { 11 | // Presets an action, which is performed before each unit test case starts. 12 | // The number of execution times is the same as the number of test cases defined by **it**. 13 | // This API supports only one parameter: preset action function. 14 | }); 15 | afterEach(() => { 16 | // Presets a clear action, which is performed after each unit test case ends. 17 | // The number of execution times is the same as the number of test cases defined by **it**. 18 | // This API supports only one parameter: clear action function. 19 | }); 20 | afterAll(() => { 21 | // Presets a clear action, which is performed after all test cases of the test suite end. 22 | // This API supports only one parameter: clear action function. 23 | }); 24 | it('assertContain', 0, () => { 25 | // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. 26 | let a = 'abc'; 27 | let b = 'b'; 28 | // Defines a variety of assertion methods, which are used to declare expected boolean conditions. 29 | expect(a).assertContain(b); 30 | expect(a).assertEqual(a); 31 | }); 32 | }); 33 | } -------------------------------------------------------------------------------- /OHOS_Project/hvigor/hvigor-config.json5: -------------------------------------------------------------------------------- 1 | { 2 | "modelVersion": "5.0.2", 3 | "dependencies": { 4 | }, 5 | "execution": { 6 | // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ 7 | // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ 8 | // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ 9 | // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ 10 | // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ 11 | }, 12 | "logging": { 13 | // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ 14 | }, 15 | "debugging": { 16 | // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ 17 | }, 18 | "nodeOptions": { 19 | // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ 20 | // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /OHOS_Project/hvigorfile.ts: -------------------------------------------------------------------------------- 1 | import { appTasks } from '@ohos/hvigor-ohos-plugin'; 2 | 3 | export default { 4 | system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ 5 | plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ 6 | } 7 | -------------------------------------------------------------------------------- /OHOS_Project/oh-package-lock.json5: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "stableOrder": true 4 | }, 5 | "lockfileVersion": 3, 6 | "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", 7 | "specifiers": { 8 | "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0", 9 | "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21" 10 | }, 11 | "packages": { 12 | "@ohos/hamock@1.0.0": { 13 | "name": "@ohos/hamock", 14 | "version": "1.0.0", 15 | "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==", 16 | "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har", 17 | "registryType": "ohpm" 18 | }, 19 | "@ohos/hypium@1.0.21": { 20 | "name": "@ohos/hypium", 21 | "version": "1.0.21", 22 | "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==", 23 | "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har", 24 | "registryType": "ohpm" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /OHOS_Project/oh-package.json5: -------------------------------------------------------------------------------- 1 | { 2 | "modelVersion": "5.0.2", 3 | "description": "Please describe the basic information.", 4 | "dependencies": { 5 | }, 6 | "devDependencies": { 7 | "@ohos/hypium": "1.0.21", 8 | "@ohos/hamock": "1.0.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /OpenHarmony.Avalonia.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.12.35410.144 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Entry", "Src\Entry\Entry.csproj", "{956C344F-D951-4676-A07E-10A75ACDB433}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.OpenHarmony", "Src\Avalonia.OpenHarmony\Avalonia.OpenHarmony.csproj", "{CC9E4CDF-637E-43FC-999C-5717F97CFE43}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Example", "Example", "{F1FEDF1B-E967-4070-B986-C11E9D6D6C61}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvaloniaApp", "Src\Example\AvaloniaApp\AvaloniaApp.csproj", "{32CF34B5-F75A-4A00-A730-90140C0A792D}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvaloniaApp.Desktop", "Src\Example\AvaloniaApp.Desktop\AvaloniaApp.Desktop.csproj", "{D1AC0C3E-A28F-4604-9B04-74101768F712}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenHarmony.NDK.Bindings", "ThirdParty\OpenHarmony.NDK.Bindings\OpenHarmony.NDK.Bindings\OpenHarmony.NDK.Bindings.csproj", "{F8E2F26E-DAE3-4CA7-924E-7F05E655E71D}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOOH_Gallery", "Src\Example\AOOH_Gallery\AOOH_Gallery.csproj", "{0DB36DC2-D05D-46F8-9C89-FB15778DA2CA}" 19 | EndProject 20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOOH_Gallery.Desktop", "Src\Example\AOOH_Gallery.Desktop\AOOH_Gallery.Desktop.csproj", "{A43F296F-D6DD-4F64-8F35-2622AF619254}" 21 | EndProject 22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AOOH_Gallery", "AOOH_Gallery", "{492440ED-F090-4FFE-918F-20FD73E6DE4C}" 23 | EndProject 24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semi.Avalonia.Demo", "ThirdParty\Semi.Avalonia\demo\Semi.Avalonia.Demo\Semi.Avalonia.Demo.csproj", "{0B866685-11D8-41D3-8BAA-A0D176358AC3}" 25 | EndProject 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ursa.Demo", "ThirdParty\Ursa.Avalonia\demo\Ursa.Demo\Ursa.Demo.csproj", "{ABD9CA64-B006-47A8-848A-21D43393DE73}" 27 | EndProject 28 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Irihitech", "Irihitech", "{7812D870-170F-488A-A058-F8C1433C178A}" 29 | EndProject 30 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semi.Avalonia", "ThirdParty\Semi.Avalonia\src\Semi.Avalonia\Semi.Avalonia.csproj", "{86579D70-3255-433F-B7C7-9F17EB63A655}" 31 | EndProject 32 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semi.Avalonia.ColorPicker", "ThirdParty\Semi.Avalonia\src\Semi.Avalonia.ColorPicker\Semi.Avalonia.ColorPicker.csproj", "{0B4EA84D-3379-4530-86A9-36416CE38583}" 33 | EndProject 34 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semi.Avalonia.TreeDataGrid", "ThirdParty\Semi.Avalonia\src\Semi.Avalonia.TreeDataGrid\Semi.Avalonia.TreeDataGrid.csproj", "{D3D1AB90-E346-4B83-8609-5789426E8C52}" 35 | EndProject 36 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semi.Avalonia.DataGrid", "ThirdParty\Semi.Avalonia\src\Semi.Avalonia.DataGrid\Semi.Avalonia.DataGrid.csproj", "{39F1FF7A-3EE4-4AB8-A6A2-FA36AB703490}" 37 | EndProject 38 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ursa", "ThirdParty\Ursa.Avalonia\src\Ursa\Ursa.csproj", "{E8623BDC-FA99-4D07-8227-0152AC186377}" 39 | EndProject 40 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ursa.Themes.Semi", "ThirdParty\Ursa.Avalonia\src\Ursa.Themes.Semi\Ursa.Themes.Semi.csproj", "{51CD02F7-9D11-49C6-A1D0-8AC9BAABF505}" 41 | EndProject 42 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" 43 | ProjectSection(SolutionItems) = preProject 44 | .editorconfig = .editorconfig 45 | Directory.Build.props = Directory.Build.props 46 | EndProjectSection 47 | EndProject 48 | Global 49 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 50 | Debug|Any CPU = Debug|Any CPU 51 | Release|Any CPU = Release|Any CPU 52 | EndGlobalSection 53 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 54 | {956C344F-D951-4676-A07E-10A75ACDB433}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {956C344F-D951-4676-A07E-10A75ACDB433}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {956C344F-D951-4676-A07E-10A75ACDB433}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {956C344F-D951-4676-A07E-10A75ACDB433}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {CC9E4CDF-637E-43FC-999C-5717F97CFE43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {CC9E4CDF-637E-43FC-999C-5717F97CFE43}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {CC9E4CDF-637E-43FC-999C-5717F97CFE43}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {CC9E4CDF-637E-43FC-999C-5717F97CFE43}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {32CF34B5-F75A-4A00-A730-90140C0A792D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {32CF34B5-F75A-4A00-A730-90140C0A792D}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {32CF34B5-F75A-4A00-A730-90140C0A792D}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {32CF34B5-F75A-4A00-A730-90140C0A792D}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {D1AC0C3E-A28F-4604-9B04-74101768F712}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {D1AC0C3E-A28F-4604-9B04-74101768F712}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {D1AC0C3E-A28F-4604-9B04-74101768F712}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {D1AC0C3E-A28F-4604-9B04-74101768F712}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {F8E2F26E-DAE3-4CA7-924E-7F05E655E71D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {F8E2F26E-DAE3-4CA7-924E-7F05E655E71D}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {F8E2F26E-DAE3-4CA7-924E-7F05E655E71D}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {F8E2F26E-DAE3-4CA7-924E-7F05E655E71D}.Release|Any CPU.Build.0 = Release|Any CPU 74 | {0DB36DC2-D05D-46F8-9C89-FB15778DA2CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 75 | {0DB36DC2-D05D-46F8-9C89-FB15778DA2CA}.Debug|Any CPU.Build.0 = Debug|Any CPU 76 | {0DB36DC2-D05D-46F8-9C89-FB15778DA2CA}.Release|Any CPU.ActiveCfg = Release|Any CPU 77 | {0DB36DC2-D05D-46F8-9C89-FB15778DA2CA}.Release|Any CPU.Build.0 = Release|Any CPU 78 | {A43F296F-D6DD-4F64-8F35-2622AF619254}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {A43F296F-D6DD-4F64-8F35-2622AF619254}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {A43F296F-D6DD-4F64-8F35-2622AF619254}.Release|Any CPU.ActiveCfg = Release|Any CPU 81 | {A43F296F-D6DD-4F64-8F35-2622AF619254}.Release|Any CPU.Build.0 = Release|Any CPU 82 | {0B866685-11D8-41D3-8BAA-A0D176358AC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 83 | {0B866685-11D8-41D3-8BAA-A0D176358AC3}.Debug|Any CPU.Build.0 = Debug|Any CPU 84 | {0B866685-11D8-41D3-8BAA-A0D176358AC3}.Release|Any CPU.ActiveCfg = Release|Any CPU 85 | {0B866685-11D8-41D3-8BAA-A0D176358AC3}.Release|Any CPU.Build.0 = Release|Any CPU 86 | {ABD9CA64-B006-47A8-848A-21D43393DE73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 87 | {ABD9CA64-B006-47A8-848A-21D43393DE73}.Debug|Any CPU.Build.0 = Debug|Any CPU 88 | {ABD9CA64-B006-47A8-848A-21D43393DE73}.Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {ABD9CA64-B006-47A8-848A-21D43393DE73}.Release|Any CPU.Build.0 = Release|Any CPU 90 | {86579D70-3255-433F-B7C7-9F17EB63A655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 91 | {86579D70-3255-433F-B7C7-9F17EB63A655}.Debug|Any CPU.Build.0 = Debug|Any CPU 92 | {86579D70-3255-433F-B7C7-9F17EB63A655}.Release|Any CPU.ActiveCfg = Release|Any CPU 93 | {86579D70-3255-433F-B7C7-9F17EB63A655}.Release|Any CPU.Build.0 = Release|Any CPU 94 | {0B4EA84D-3379-4530-86A9-36416CE38583}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 95 | {0B4EA84D-3379-4530-86A9-36416CE38583}.Debug|Any CPU.Build.0 = Debug|Any CPU 96 | {0B4EA84D-3379-4530-86A9-36416CE38583}.Release|Any CPU.ActiveCfg = Release|Any CPU 97 | {0B4EA84D-3379-4530-86A9-36416CE38583}.Release|Any CPU.Build.0 = Release|Any CPU 98 | {D3D1AB90-E346-4B83-8609-5789426E8C52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 99 | {D3D1AB90-E346-4B83-8609-5789426E8C52}.Debug|Any CPU.Build.0 = Debug|Any CPU 100 | {D3D1AB90-E346-4B83-8609-5789426E8C52}.Release|Any CPU.ActiveCfg = Release|Any CPU 101 | {D3D1AB90-E346-4B83-8609-5789426E8C52}.Release|Any CPU.Build.0 = Release|Any CPU 102 | {39F1FF7A-3EE4-4AB8-A6A2-FA36AB703490}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 103 | {39F1FF7A-3EE4-4AB8-A6A2-FA36AB703490}.Debug|Any CPU.Build.0 = Debug|Any CPU 104 | {39F1FF7A-3EE4-4AB8-A6A2-FA36AB703490}.Release|Any CPU.ActiveCfg = Release|Any CPU 105 | {39F1FF7A-3EE4-4AB8-A6A2-FA36AB703490}.Release|Any CPU.Build.0 = Release|Any CPU 106 | {E8623BDC-FA99-4D07-8227-0152AC186377}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 107 | {E8623BDC-FA99-4D07-8227-0152AC186377}.Debug|Any CPU.Build.0 = Debug|Any CPU 108 | {E8623BDC-FA99-4D07-8227-0152AC186377}.Release|Any CPU.ActiveCfg = Release|Any CPU 109 | {E8623BDC-FA99-4D07-8227-0152AC186377}.Release|Any CPU.Build.0 = Release|Any CPU 110 | {51CD02F7-9D11-49C6-A1D0-8AC9BAABF505}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 111 | {51CD02F7-9D11-49C6-A1D0-8AC9BAABF505}.Debug|Any CPU.Build.0 = Debug|Any CPU 112 | {51CD02F7-9D11-49C6-A1D0-8AC9BAABF505}.Release|Any CPU.ActiveCfg = Release|Any CPU 113 | {51CD02F7-9D11-49C6-A1D0-8AC9BAABF505}.Release|Any CPU.Build.0 = Release|Any CPU 114 | EndGlobalSection 115 | GlobalSection(SolutionProperties) = preSolution 116 | HideSolutionNode = FALSE 117 | EndGlobalSection 118 | GlobalSection(NestedProjects) = preSolution 119 | {32CF34B5-F75A-4A00-A730-90140C0A792D} = {F1FEDF1B-E967-4070-B986-C11E9D6D6C61} 120 | {D1AC0C3E-A28F-4604-9B04-74101768F712} = {F1FEDF1B-E967-4070-B986-C11E9D6D6C61} 121 | {0DB36DC2-D05D-46F8-9C89-FB15778DA2CA} = {492440ED-F090-4FFE-918F-20FD73E6DE4C} 122 | {A43F296F-D6DD-4F64-8F35-2622AF619254} = {492440ED-F090-4FFE-918F-20FD73E6DE4C} 123 | {492440ED-F090-4FFE-918F-20FD73E6DE4C} = {F1FEDF1B-E967-4070-B986-C11E9D6D6C61} 124 | {0B866685-11D8-41D3-8BAA-A0D176358AC3} = {7812D870-170F-488A-A058-F8C1433C178A} 125 | {ABD9CA64-B006-47A8-848A-21D43393DE73} = {7812D870-170F-488A-A058-F8C1433C178A} 126 | {7812D870-170F-488A-A058-F8C1433C178A} = {F1FEDF1B-E967-4070-B986-C11E9D6D6C61} 127 | {86579D70-3255-433F-B7C7-9F17EB63A655} = {7812D870-170F-488A-A058-F8C1433C178A} 128 | {0B4EA84D-3379-4530-86A9-36416CE38583} = {7812D870-170F-488A-A058-F8C1433C178A} 129 | {D3D1AB90-E346-4B83-8609-5789426E8C52} = {7812D870-170F-488A-A058-F8C1433C178A} 130 | {39F1FF7A-3EE4-4AB8-A6A2-FA36AB703490} = {7812D870-170F-488A-A058-F8C1433C178A} 131 | {E8623BDC-FA99-4D07-8227-0152AC186377} = {7812D870-170F-488A-A058-F8C1433C178A} 132 | {51CD02F7-9D11-49C6-A1D0-8AC9BAABF505} = {7812D870-170F-488A-A058-F8C1433C178A} 133 | EndGlobalSection 134 | GlobalSection(ExtensibilityGlobals) = postSolution 135 | SolutionGuid = {CCB04250-A59B-47A9-8DBC-F6EBEB6428CD} 136 | EndGlobalSection 137 | EndGlobal 138 | -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 | # OpenHarmony.Avalonia 2 | 3 | English | [简体中文](README.md) 4 | 5 | ## Usage 6 | 7 | See [guide](https://openharmony-net.github.io/docs/docs/avalonia/introduction.html) 8 | 9 | ## Development 10 | 11 | Folder structure: 12 | ```bash 13 | |-- OHOS_Project <-- DevEco Project directory 14 | |-- OpenHarmony.Avalonia.sln <-- Visual Studio solution file 15 | |-- README.md 16 | |-- Src <-- Project source code 17 | | |-- Avalonia.OpenHarmony <-- Avalonia platform API implementation 18 | | |-- Entry <-- Avalonia entry 19 | (register as RegisterEntryModule 20 | and initialize as XComponent) 21 | | |-- Example <-- Example project 22 | |-- ThirdParty 23 | ``` 24 | 25 | ## Contributing 26 | 27 | We encourage you to participate in the development of OpenHarmony.Avalonia! Please see [contributing guide](CONTRIBUTING.md) for how to proceed. 28 | 29 | ## Status 30 | 31 | .NET runtime and GPU rendering have been resolved. 32 | 33 | ## 计划 34 | 35 | - [ ] Keyboard events 36 | - [ ] Mouse events 37 | - [ ] Multi-window 38 | - [x] Font 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenHarmony.Avalonia 2 | 3 | 简体中文 | [English](README.en.md) 4 | 5 | ## 使用 6 | 7 | 请参考[文档](https://openharmony-net.github.io/docs/docs/avalonia/introduction.html) 8 | 9 | ## 开发 10 | 11 | 目录结构 12 | ```bash 13 | |-- OHOS_Project <-- DevEco项目目录 14 | |-- OpenHarmony.Avalonia.sln <-- 解决方案文件 15 | |-- README.md 16 | |-- Src <-- 项目源代码 17 | | |-- Avalonia.OpenHarmony <-- Avalonia 的平台API的实现 18 | | |-- Entry <-- Avalonia 的入口 19 | (注册为RegisterEntryModule, 20 | 以及注册为XComponent的初始化操作) 21 | | |-- Example <-- 示例项目 22 | |-- ThirdParty 23 | ``` 24 | 25 | ## 如何参与项目 26 | 27 | 我们鼓励您参与 OpenHarmony.Avalonia 的开发!请查看[贡献指南](CONTRIBUTING.md)以了解如何进行。 28 | 29 | ## 状态 30 | .NET运行时和GPU渲染均已解决 31 | 32 | ## 计划 33 | 34 | - [ ] 键盘事件 35 | - [ ] 鼠标事件 36 | - [ ] 多窗口 37 | - [x] 字体 38 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/Assets/HarmonyOS_Sans_Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Avalonia.OpenHarmony/Assets/HarmonyOS_Sans_Regular.ttf -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/Avalonia.OpenHarmony.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | AvaloniaOpenHarmony 5 | net8.0 6 | enable 7 | enable 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | libs\Avalonia.Skia\Avalonia.Skia.dll 29 | 30 | 31 | libs\HarfBuzzSharp\HarfBuzzSharp.dll 32 | 33 | 34 | libs\SkiaSharp\SkiaSharp.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/AvaloniaXComponent.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | using Avalonia.Controls.Embedding; 4 | using Avalonia.Input; 5 | using Avalonia.Input.Raw; 6 | using Avalonia.OpenGL.Egl; 7 | 8 | using OpenHarmony.NDK.Bindings.Native; 9 | 10 | using Silk.NET.OpenGLES; 11 | 12 | namespace Avalonia.OpenHarmony; 13 | 14 | public class AvaloniaXComponent : XComponent where TApp : Application, new() 15 | { 16 | private readonly MouseDevice _mouseDevice; 17 | private readonly PenDevice _penDevice; 18 | 19 | private readonly TouchDevice _touchDevice; 20 | private nint display; 21 | private EglInterface? egl; 22 | private GL? gl; 23 | public EmbeddableControlRoot? Root; 24 | public SingleViewLifetime? SingleViewLifetime; 25 | private nint surface; 26 | public TopLevelImpl? TopLevelImpl; 27 | 28 | public bool UseSoftRenderer = false; 29 | 30 | public AvaloniaXComponent(nint XComponentHandle, nint WindowHandle) : base(XComponentHandle, WindowHandle) 31 | { 32 | _touchDevice = new TouchDevice(); 33 | _penDevice = new PenDevice(); 34 | _mouseDevice = new MouseDevice(); 35 | } 36 | 37 | public void InitOpenGlEnv() 38 | { 39 | egl = new EglInterface("libEGL.so"); 40 | 41 | display = egl.GetDisplay(0); 42 | if (egl.Initialize(display, out var major, out var minor) == false) 43 | { 44 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "CSharp", "egl.Initialize fail"); 45 | return; 46 | } 47 | 48 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "CSharp", "egl init success"); 49 | 50 | int[] attributes = [0x3033, 0x0004, 0x3024, 8, 0x3023, 8, 0x3022, 8, 0x3021, 8, 0x3040, 0x0004, 0x3038]; 51 | if (egl.ChooseConfig(display, attributes, out var configs, 1, out var choosenConfig) == false) 52 | { 53 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "CSharp", "egl.ChooseConfig fail"); 54 | return; 55 | } 56 | 57 | int[] winAttribs = [0x309D, 0x3089, 0x3038]; 58 | surface = egl.CreateWindowSurface(display, configs, WindowHandle, winAttribs); 59 | if (surface == 0) 60 | { 61 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "CSharp", "egl.CreateWindowSurface fail"); 62 | return; 63 | } 64 | 65 | 66 | int[] attrib3_list = [0x3098, 2, 0x3038]; 67 | var sharedEglContext = 0; 68 | var context = egl.CreateContext(display, configs, sharedEglContext, attrib3_list); 69 | if (egl.MakeCurrent(display, surface, surface, context) == false) 70 | { 71 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "CSharp", "egl.MakeCurrent fail"); 72 | return; 73 | } 74 | 75 | 76 | gl = GL.GetApi(name => 77 | { 78 | var ptr = Marshal.StringToHGlobalAnsi(name); 79 | var fun = egl.GetProcAddress(ptr); 80 | Marshal.FreeHGlobal(ptr); 81 | return fun; 82 | }); 83 | } 84 | 85 | public override void OnSurfaceCreated() 86 | { 87 | if (UseSoftRenderer) InitOpenGlEnv(); 88 | var builder = CreateAppBuilder(); 89 | if (UseSoftRenderer) 90 | { 91 | builder.UseSoftwareRenderer(); 92 | if (gl != null) AvaloniaLocator.CurrentMutable.Bind().ToConstant(gl); 93 | } 94 | 95 | SingleViewLifetime = new SingleViewLifetime(); 96 | builder.AfterApplicationSetup(CreateView).SetupWithLifetime(SingleViewLifetime); 97 | 98 | 99 | Root?.StartRendering(); 100 | } 101 | 102 | public override void OnSurfaceRendered(ulong timestamp, ulong targetTimestamp) 103 | { 104 | if (TopLevelImpl == null) 105 | return; 106 | base.OnSurfaceRendered(timestamp, targetTimestamp); 107 | TopLevelImpl.Render(); 108 | if (UseSoftRenderer && egl != null) egl.SwapBuffers(display, surface); 109 | } 110 | 111 | private void CreateView(AppBuilder appBuilder) 112 | { 113 | if (SingleViewLifetime == null) 114 | return; 115 | TopLevelImpl = new TopLevelImpl(XComponentHandle, WindowHandle); 116 | Root = new EmbeddableControlRoot(TopLevelImpl); 117 | SingleViewLifetime.Root = Root; 118 | Root.Prepare(); 119 | } 120 | 121 | public override unsafe void DispatchTouchEvent() 122 | { 123 | if (TopLevelImpl == null) 124 | return; 125 | if (TopLevelImpl.Input == null) 126 | return; 127 | if (TopLevelImpl.InputRoot == null) 128 | return; 129 | OH_NativeXComponent_TouchEvent touchEvent = default; 130 | var result = Ace.OH_NativeXComponent_GetTouchEvent((OH_NativeXComponent*)XComponentHandle, (void*)WindowHandle, 131 | &touchEvent); 132 | if (result == (int)OH_NATIVEXCOMPONENT_RESULT.SUCCESS) 133 | for (uint i = 0; i < touchEvent.numPoints; i++) 134 | { 135 | OH_NativeXComponent_TouchPointToolType toolType = default; 136 | float tiltX = 0; 137 | float tiltY = 0; 138 | 139 | 140 | Ace.OH_NativeXComponent_GetTouchPointToolType((OH_NativeXComponent*)XComponentHandle, i, &toolType); 141 | Ace.OH_NativeXComponent_GetTouchPointTiltX((OH_NativeXComponent*)XComponentHandle, i, &tiltX); 142 | Ace.OH_NativeXComponent_GetTouchPointTiltY((OH_NativeXComponent*)XComponentHandle, i, &tiltY); 143 | 144 | 145 | var id = touchEvent.touchPoints[(int)i].id; 146 | 147 | var type = touchEvent.touchPoints[(int)i].type switch 148 | { 149 | OH_NativeXComponent_TouchEventType.OH_NATIVEXCOMPONENT_DOWN => RawPointerEventType.TouchBegin, 150 | OH_NativeXComponent_TouchEventType.OH_NATIVEXCOMPONENT_UP => RawPointerEventType.TouchEnd, 151 | OH_NativeXComponent_TouchEventType.OH_NATIVEXCOMPONENT_MOVE => RawPointerEventType.TouchUpdate, 152 | OH_NativeXComponent_TouchEventType.OH_NATIVEXCOMPONENT_CANCEL => RawPointerEventType.TouchCancel, 153 | _ => throw new NotImplementedException() 154 | }; 155 | 156 | var position = new Point(touchEvent.touchPoints[(int)i].x, touchEvent.touchPoints[(int)i].y) / 157 | TopLevelImpl.RenderScaling; 158 | var modifiers = RawInputModifiers.None; 159 | if (type == RawPointerEventType.TouchUpdate) modifiers |= RawInputModifiers.LeftMouseButton; 160 | var args = new RawTouchEventArgs(_touchDevice, (ulong)touchEvent.touchPoints[(int)i].timeStamp, 161 | TopLevelImpl.InputRoot, type, position, RawInputModifiers.LeftMouseButton, id); 162 | 163 | TopLevelImpl.Input?.Invoke(args); 164 | } 165 | else 166 | Hilog.OH_LOG_ERROR(LogType.LOG_APP, "csharp", "OH_NativeXComponent_GetTouchEvent fail"); 167 | } 168 | 169 | public override unsafe void OnSurfaceChanged() 170 | { 171 | base.OnSurfaceChanged(); 172 | ulong width = 0, height = 0; 173 | TopLevelImpl.Resize(); 174 | Ace.OH_NativeXComponent_GetXComponentSize((OH_NativeXComponent*)XComponentHandle, (void*)WindowHandle, &width, 175 | &height); 176 | if (UseSoftRenderer && gl != null) gl.Viewport(0, 0, (uint)width, (uint)height); 177 | } 178 | 179 | private AppBuilder CreateAppBuilder() 180 | { 181 | return AppBuilder.Configure().UseOpenHarmony(); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/ClipboardImpl.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Input; 2 | using Avalonia.Input.Platform; 3 | 4 | namespace Avalonia.OpenHarmony; 5 | 6 | public class ClipboardImpl : IClipboard 7 | { 8 | public Task ClearAsync() 9 | { 10 | throw new NotImplementedException(); 11 | } 12 | 13 | public Task GetDataAsync(string format) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | 18 | public Task GetFormatsAsync() 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | 23 | public Task GetTextAsync() 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | 28 | public Task SetDataObjectAsync(IDataObject data) 29 | { 30 | throw new NotImplementedException(); 31 | } 32 | 33 | public Task SetTextAsync(string? text) 34 | { 35 | throw new NotImplementedException(); 36 | } 37 | } -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/CursorFactory.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Input; 2 | using Avalonia.Platform; 3 | 4 | namespace Avalonia.OpenHarmony; 5 | 6 | public class CursorFactory : ICursorFactory 7 | { 8 | public ICursorImpl CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot) 9 | { 10 | return CursorImpl.ZeroCursor; 11 | } 12 | 13 | public ICursorImpl GetCursor(StandardCursorType cursorType) 14 | { 15 | return CursorImpl.ZeroCursor; 16 | } 17 | 18 | private sealed class CursorImpl : ICursorImpl 19 | { 20 | private CursorImpl() 21 | { 22 | } 23 | 24 | public static CursorImpl ZeroCursor { get; } = new(); 25 | 26 | public void Dispose() 27 | { 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/FramebufferManager.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls.Platform.Surfaces; 2 | using Avalonia.Platform; 3 | 4 | namespace Avalonia.OpenHarmony; 5 | 6 | public class FramebufferManager : IFramebufferPlatformSurface 7 | { 8 | private readonly TopLevelImpl TopLevelImpl; 9 | 10 | public FramebufferManager(TopLevelImpl topLevelImpl) 11 | { 12 | TopLevelImpl = topLevelImpl; 13 | } 14 | 15 | public IFramebufferRenderTarget CreateFramebufferRenderTarget() 16 | { 17 | return new FuncFramebufferRenderTarget(Lock); 18 | } 19 | 20 | public ILockedFramebuffer Lock() 21 | { 22 | return new OpenHarmonyFramebuffer(TopLevelImpl); 23 | } 24 | } -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OHDebugHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | 3 | using OpenHarmony.NDK.Bindings.Native; 4 | 5 | namespace Avalonia.OpenHarmony; 6 | 7 | public static class OHDebugHelper 8 | { 9 | private const string CSharp = "CSharp"; 10 | private static readonly ObservableCollection _logs = new(); 11 | public static ReadOnlyObservableCollection Logs { get; } = new(_logs); 12 | public static int MaxLogCount { get; set; } = 1000; 13 | 14 | public static void Debug(string log) 15 | { 16 | AddLog(LogLevel.LOG_DEBUG, log); 17 | } 18 | 19 | public static void Error(string title, Exception exception) 20 | { 21 | AddLog(LogLevel.LOG_ERROR, $"{title}\n{exception}"); 22 | } 23 | 24 | public static void Fatal(string log) 25 | { 26 | AddLog(LogLevel.LOG_FATAL, log); 27 | } 28 | 29 | public static void Info(string log) 30 | { 31 | AddLog(LogLevel.LOG_INFO, log); 32 | } 33 | 34 | public static void Warn(string log) 35 | { 36 | AddLog(LogLevel.LOG_WARN, log); 37 | } 38 | 39 | public static void AddLog(LogLevel logLevel, string log) 40 | { 41 | LogRecord logRecord = new(logLevel, log); 42 | if (_logs.Count > MaxLogCount) _logs.Clear(); 43 | 44 | _logs.Add(logRecord); 45 | Hilog.OH_LOG_PRINT(LogType.LOG_APP, logLevel, CSharp, log); 46 | } 47 | } 48 | 49 | public record LogRecord(LogLevel LogLevel, string Message) 50 | { 51 | public DateTime Time { get; } = DateTime.Now; 52 | } 53 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyApplicationExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Avalonia.OpenHarmony; 2 | 3 | public static class OpenHarmonyApplicationExtensions 4 | { 5 | public static AppBuilder UseOpenHarmony(this AppBuilder builder) 6 | { 7 | return builder 8 | .UseStandardRuntimePlatformSubsystem() 9 | .UseWindowingSubsystem(OpenHarmonyPlatform.Initialize, "OpenHarmony") 10 | .UseSkia(); 11 | } 12 | 13 | public static AppBuilder UseSoftwareRenderer(this AppBuilder builder) 14 | { 15 | AvaloniaLocator.CurrentMutable.Bind().ToConstant(new OpenHarmonyPlatformOptions 16 | { RenderingMode = [OpenHarmonyPlatformRenderingMode.Software] }); 17 | return builder; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyFontManagerImpl.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Globalization; 3 | using System.Reflection; 4 | using System.Runtime.CompilerServices; 5 | using System.Runtime.Loader; 6 | 7 | using Avalonia.Media; 8 | using Avalonia.Media.Fonts; 9 | using Avalonia.Platform; 10 | using Avalonia.Skia; 11 | 12 | using SkiaSharp; 13 | 14 | namespace Avalonia.OpenHarmony; 15 | 16 | public class TestE : EmbeddedFontCollection 17 | { 18 | public TestE(Uri key, Uri source) : base(key, source) 19 | { 20 | } 21 | 22 | public override void Initialize(IFontManagerImpl fontManager) 23 | { 24 | foreach (var fontAsset in Directory.GetFiles("/system/fonts")) 25 | try 26 | { 27 | using var stream = File.OpenRead(fontAsset); 28 | 29 | if (fontManager.TryCreateGlyphTypeface(stream, FontSimulations.None, out var glyphTypeface)) 30 | { 31 | Call(glyphTypeface); 32 | } 33 | } 34 | catch (Exception e) 35 | { 36 | OHDebugHelper.Error("我们无权访问这个字体。", e); 37 | } 38 | } 39 | 40 | public override bool TryGetGlyphTypeface(string familyName, FontStyle style, FontWeight weight, FontStretch stretch, 41 | [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface) 42 | { 43 | if (familyName == "$Default") 44 | familyName = "HarmonyOS Sans SC"; 45 | return base.TryGetGlyphTypeface(familyName, style, weight, stretch, out glyphTypeface); 46 | } 47 | 48 | private void Call(object? glyphTypeface) 49 | { 50 | var type = typeof(EmbeddedFontCollection); 51 | var method = type.GetMethod("AddGlyphTypeface", BindingFlags.NonPublic | BindingFlags.Instance); 52 | method.Invoke(this, [glyphTypeface]); 53 | } 54 | } 55 | 56 | internal class OpenHarmonyFontManagerImpl : IFontManagerImpl 57 | { 58 | private readonly SKFontManager _skFontManager = SKFontManager.Default; 59 | 60 | private readonly TestE _testE = new( 61 | new Uri("fonts:AvaloniaFonts", UriKind.Absolute), 62 | new Uri("resm:Avalonia.OpenHarmony.Assets?assembly=Avalonia.OpenHarmony")); 63 | 64 | public OpenHarmonyFontManagerImpl() 65 | { 66 | FontManager.Current.AddFontCollection(_testE); 67 | } 68 | 69 | public string GetDefaultFontFamilyName() 70 | { 71 | return "HarmonyOS Sans SC"; 72 | } 73 | 74 | public string[] GetInstalledFontFamilyNames(bool checkForUpdates = false) 75 | { 76 | return 77 | [ 78 | "HarmonyOS Sans", 79 | "HarmonyOS Sans SC", 80 | "HarmonyOS Sans Condensed", 81 | "HarmonyOS Sans Digit", 82 | "Noto Serif", 83 | "Noto Sans Mono" 84 | ]; 85 | } 86 | 87 | public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, 88 | FontWeight fontWeight, FontStretch fontStretch, CultureInfo? culture, out Typeface fontKey) 89 | { 90 | return _testE.TryMatchCharacter(codepoint, 91 | fontStyle, 92 | fontWeight, 93 | fontStretch, 94 | null, 95 | culture, 96 | out fontKey); 97 | } 98 | 99 | public bool TryCreateGlyphTypeface(string familyName, FontStyle style, FontWeight weight, 100 | FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface) 101 | { 102 | return _testE.TryGetGlyphTypeface(familyName, style, weight, stretch, out glyphTypeface); 103 | } 104 | 105 | public bool TryCreateGlyphTypeface(Stream stream, FontSimulations fontSimulations, 106 | [NotNullWhen(true)] out IGlyphTypeface? glyphTypeface) 107 | { 108 | var skTypeface = SKTypeface.FromStream(stream); 109 | 110 | if (skTypeface != null) 111 | { 112 | glyphTypeface = Create(skTypeface, fontSimulations); 113 | 114 | return true; 115 | } 116 | 117 | glyphTypeface = null; 118 | 119 | return false; 120 | } 121 | 122 | private IGlyphTypeface Create(object? skTypeface, object? fontSimulations) 123 | { 124 | Type? type = null; 125 | foreach (var alc in AssemblyLoadContext.All) 126 | { 127 | foreach (var assembly in alc.Assemblies) 128 | { 129 | type = assembly.GetType("Avalonia.Skia.GlyphTypefaceImpl"); 130 | if (type != null) 131 | break; 132 | } 133 | 134 | if (type != null) 135 | break; 136 | } 137 | 138 | var ctor = type.GetConstructor([typeof(SKTypeface), typeof(FontSimulations)]); 139 | var obj = RuntimeHelpers.GetUninitializedObject(type); 140 | ctor.Invoke(obj, [skTypeface, fontSimulations]); 141 | return (IGlyphTypeface)obj; 142 | } 143 | 144 | public bool TryGetFamilyTypefaces(string familyName, 145 | [NotNullWhen(true)] out IReadOnlyList? familyTypefaces) 146 | { 147 | familyTypefaces = null; 148 | 149 | var set = _skFontManager.GetFontStyles(familyName); 150 | 151 | if (set.Count == 0) return false; 152 | 153 | var typefaces = new List(set.Count); 154 | 155 | foreach (var fontStyle in set) 156 | typefaces.Add(new Typeface(familyName, fontStyle.Slant.ToAvalonia(), (FontWeight)fontStyle.Weight, 157 | (FontStretch)fontStyle.Width)); 158 | 159 | familyTypefaces = typefaces; 160 | 161 | return true; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyFramebuffer.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform; 2 | 3 | using PixelFormat = Avalonia.Platform.PixelFormat; 4 | 5 | namespace Avalonia.OpenHarmony; 6 | 7 | public class OpenHarmonyFramebuffer : ILockedFramebuffer 8 | { 9 | private readonly TopLevelImpl TopLevelImpl; 10 | 11 | public OpenHarmonyFramebuffer(TopLevelImpl topLevelImpl) 12 | { 13 | TopLevelImpl = topLevelImpl; 14 | Size = topLevelImpl.Size; 15 | RowBytes = 4 * Size.Width; 16 | Format = PixelFormat.Rgba8888; 17 | Dpi = new Vector(96, 96) * topLevelImpl.Scaling; 18 | } 19 | 20 | public nint Address => TopLevelImpl.Address; 21 | 22 | public PixelSize Size { get; } 23 | 24 | public int RowBytes { get; } 25 | 26 | public Vector Dpi { get; } 27 | 28 | public PixelFormat Format { get; } 29 | 30 | public void Dispose() 31 | { 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyInputPane.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Runtime.InteropServices; 3 | 4 | using Avalonia.Controls.Platform; 5 | 6 | using OpenHarmony.NDK.Bindings.Native; 7 | 8 | namespace Avalonia.OpenHarmony; 9 | 10 | public class OpenHarmonyInputPane : InputPaneBase 11 | { 12 | private readonly TopLevelImpl _topLevelImpl; 13 | 14 | public OpenHarmonyInputPane(TopLevelImpl topLevelImpl) 15 | { 16 | _topLevelImpl = topLevelImpl; 17 | InputPaneHeightChanged += data => { OnGeometryChange(0, data); }; 18 | OnGeometryChange(0, _inputPaneHeight); 19 | } 20 | 21 | public bool OnGeometryChange(double y, double height) 22 | { 23 | var oldState = (OccludedRect, State); 24 | 25 | OccludedRect = new Rect(0, y, _topLevelImpl.ClientSize.Width, height); 26 | State = OccludedRect.Height != 0 ? InputPaneState.Open : InputPaneState.Closed; 27 | 28 | if (oldState != (OccludedRect, State)) OnStateChanged(new InputPaneStateEventArgs(State, null, OccludedRect)); 29 | OHDebugHelper.Debug("输入法的软键盘高度:" + height); 30 | return true; 31 | } 32 | 33 | private static int _inputPaneHeight; 34 | private static event Action? InputPaneHeightChanged; 35 | 36 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)], EntryPoint = "setInputPaneHeight")] 37 | public static unsafe napi_value SetInputPaneHeight(napi_env env, napi_callback_info info) 38 | { 39 | ulong argc = 1; 40 | var args = stackalloc napi_value[(int)argc]; 41 | node_api.napi_get_cb_info(env, info, &argc, args, null, null); 42 | int result; 43 | if (node_api.napi_get_value_int32(env, args[0], &result) is napi_status.napi_ok) 44 | { 45 | InputPaneHeightChanged?.Invoke(_inputPaneHeight = result); 46 | } 47 | 48 | return default; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyKeyboardDevice.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Input; 2 | 3 | namespace Avalonia.OpenHarmony; 4 | 5 | internal class OpenHarmonyKeyboardDevice : KeyboardDevice 6 | { 7 | internal static KeyboardDevice Instance => 8 | (AvaloniaLocator.Current.GetService() as KeyboardDevice)!; 9 | } -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyPlatform.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Input; 2 | using Avalonia.Input.Platform; 3 | using Avalonia.Media; 4 | using Avalonia.OpenGL.Egl; 5 | using Avalonia.Platform; 6 | using Avalonia.Rendering; 7 | using Avalonia.Rendering.Composition; 8 | 9 | namespace Avalonia.OpenHarmony; 10 | 11 | public class OpenHarmonyPlatform 12 | { 13 | public static OpenHarmonyPlatformOptions Options = new() 14 | { RenderingMode = [OpenHarmonyPlatformRenderingMode.Software] }; 15 | 16 | public static void Initialize() 17 | { 18 | var options = AvaloniaLocator.Current.GetService() ?? 19 | new OpenHarmonyPlatformOptions(); 20 | var fontManagerOptions = new FontManagerOptions() 21 | { 22 | DefaultFamilyName = "HarmonyOS Sans SC", 23 | }; 24 | 25 | AvaloniaLocator.CurrentMutable 26 | .Bind().ToSingleton() 27 | .Bind().ToConstant(fontManagerOptions) 28 | // .Bind().ToConstant(new FontManager(new OpenHarmonyFontManagerImpl())) 29 | .Bind().ToConstant(new FontManager(new OpenHarmonyFontManagerImpl())) 30 | .Bind().ToSingleton() 31 | .Bind().ToSingleton() 32 | .Bind().ToSingleton() 33 | .Bind().ToSingleton() 34 | .Bind().ToSingleton() 35 | .Bind().ToSingleton(); 36 | 37 | var platformGraphics = InitializeGraphics(options); 38 | if (platformGraphics is not null) 39 | AvaloniaLocator.CurrentMutable.Bind().ToConstant(platformGraphics); 40 | 41 | var compositor = new Compositor(platformGraphics); 42 | AvaloniaLocator.CurrentMutable.Bind().ToConstant(compositor); 43 | 44 | // FontManager.Current.AddFontCollection(new TestE( 45 | // new Uri("fonts:AvaloniaSystemFonts"), 46 | // new Uri("resm:Avalonia.OpenHarmony.Assets?assembly=Avalonia.OpenHarmony"))); 47 | } 48 | 49 | private static IPlatformGraphics? InitializeGraphics(OpenHarmonyPlatformOptions options) 50 | { 51 | foreach (var renderingMode in options.RenderingMode) 52 | { 53 | if (renderingMode == OpenHarmonyPlatformRenderingMode.Egl) 54 | return EglPlatformGraphics.TryCreate(() => 55 | { 56 | return new EglDisplay(new EglDisplayCreationOptions 57 | { 58 | Egl = new EglInterface("libEGL.so"), 59 | SupportsMultipleContexts = true, 60 | SupportsContextSharing = true 61 | }); 62 | }); 63 | 64 | if (renderingMode == OpenHarmonyPlatformRenderingMode.Software) return null; 65 | } 66 | 67 | throw new Exception("no render mode"); 68 | } 69 | } 70 | 71 | public sealed class OpenHarmonyPlatformOptions 72 | { 73 | public IReadOnlyList RenderingMode { get; set; } = 74 | [OpenHarmonyPlatformRenderingMode.Egl, OpenHarmonyPlatformRenderingMode.Software]; 75 | } 76 | 77 | public enum OpenHarmonyPlatformRenderingMode 78 | { 79 | Software = 1, 80 | 81 | Egl = 2 82 | } 83 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyPlatformSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Runtime.InteropServices; 3 | 4 | using Avalonia.Platform; 5 | 6 | using OpenHarmony.NDK.Bindings.Native; 7 | 8 | namespace Avalonia.OpenHarmony; 9 | 10 | public class OpenHarmonyPlatformSettings : DefaultPlatformSettings 11 | { 12 | public OpenHarmonyPlatformSettings() 13 | { 14 | ColorModeChanged += mode => 15 | { 16 | OHDebugHelper.Debug("OpenHarmonyPlatformSettings" + $"ColorModeChanged: {mode}"); 17 | OnColorValuesChanged(new PlatformColorValues() 18 | { 19 | ThemeVariant = mode switch 20 | { 21 | ColorMode.COLOR_MODE_DARK => PlatformThemeVariant.Dark, 22 | _ => PlatformThemeVariant.Light 23 | } 24 | }); 25 | }; 26 | } 27 | 28 | public override PlatformColorValues GetColorValues() 29 | { 30 | return new PlatformColorValues() 31 | { 32 | ThemeVariant = _colorMode switch 33 | { 34 | ColorMode.COLOR_MODE_DARK => PlatformThemeVariant.Dark, 35 | _ => PlatformThemeVariant.Light 36 | } 37 | }; 38 | } 39 | 40 | private static event Action? ColorModeChanged; 41 | private static ColorMode _colorMode; 42 | 43 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)], EntryPoint = "setColor")] 44 | public static unsafe napi_value SetColor(napi_env env, napi_callback_info info) 45 | { 46 | ulong argc = 1; 47 | var args = stackalloc napi_value[(int)argc]; 48 | node_api.napi_get_cb_info(env, info, &argc, args, null, null); 49 | int result; 50 | if (node_api.napi_get_value_int32(env, args[0], &result) is napi_status.napi_ok) 51 | { 52 | if (result is >= -1 and <= 1) 53 | { 54 | // .Net9 AOT的BUG,我在此处永远留下这一行注释。告诉所有人,AOT里不要玩太抽象的东西。 55 | // ColorModeChanged?.Invoke(_colorMode = (ColorMode)result); 56 | _colorMode = (ColorMode)result; 57 | ColorModeChanged?.Invoke(_colorMode); 58 | } 59 | else 60 | { 61 | _colorMode = ColorMode.COLOR_MODE_NOT_SET; 62 | ColorModeChanged?.Invoke(_colorMode); 63 | } 64 | } 65 | 66 | return default; 67 | } 68 | } 69 | 70 | internal enum ColorMode 71 | { 72 | /** 73 | * The color mode is not set. 74 | * 75 | * @syscap SystemCapability.Ability.AbilityBase 76 | * @since 9 77 | */ 78 | /** 79 | * The color mode is not set. 80 | * 81 | * @syscap SystemCapability.Ability.AbilityBase 82 | * @crossplatform 83 | * @since 10 84 | */ 85 | /** 86 | * The color mode is not set. 87 | * 88 | * @syscap SystemCapability.Ability.AbilityBase 89 | * @crossplatform 90 | * @atomicservice 91 | * @since 11 92 | */ 93 | COLOR_MODE_NOT_SET = -1, 94 | 95 | /** 96 | * Dark mode. 97 | * 98 | * @syscap SystemCapability.Ability.AbilityBase 99 | * @since 9 100 | */ 101 | /** 102 | * Dark mode. 103 | * 104 | * @syscap SystemCapability.Ability.AbilityBase 105 | * @crossplatform 106 | * @since 10 107 | */ 108 | /** 109 | * Dark mode. 110 | * 111 | * @syscap SystemCapability.Ability.AbilityBase 112 | * @crossplatform 113 | * @atomicservice 114 | * @since 11 115 | */ 116 | COLOR_MODE_DARK = 0, 117 | 118 | /** 119 | * Light mode. 120 | * 121 | * @syscap SystemCapability.Ability.AbilityBase 122 | * @since 9 123 | */ 124 | /** 125 | * Light mode. 126 | * 127 | * @syscap SystemCapability.Ability.AbilityBase 128 | * @crossplatform 129 | * @since 10 130 | */ 131 | /** 132 | * Light mode. 133 | * 134 | * @syscap SystemCapability.Ability.AbilityBase 135 | * @crossplatform 136 | * @atomicservice 137 | * @since 11 138 | */ 139 | COLOR_MODE_LIGHT = 1 140 | } 141 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyPlatformThreading.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform; 2 | using Avalonia.Threading; 3 | 4 | using OpenHarmony.NDK.Bindings.Native; 5 | 6 | namespace Avalonia.OpenHarmony; 7 | 8 | public class OpenHarmonyPlatformThreading : IPlatformThreadingInterface 9 | { 10 | private readonly Thread LoopThread; 11 | 12 | private List list = []; 13 | private List list2 = []; 14 | 15 | public OpenHarmonyPlatformThreading() 16 | { 17 | LoopThread = Thread.CurrentThread; 18 | } 19 | 20 | public bool CurrentThreadIsLoopThread => LoopThread == Thread.CurrentThread; 21 | 22 | public event Action? Signaled; 23 | 24 | public void Signal(DispatcherPriority priority) 25 | { 26 | EnsureInvokeOnMainThread(() => Signaled?.Invoke(null)); 27 | } 28 | 29 | public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick) 30 | { 31 | if (interval.TotalMilliseconds < 10) 32 | interval = TimeSpan.FromMilliseconds(10); 33 | 34 | var stopped = false; 35 | Timer? timer = null; 36 | timer = new Timer(_ => 37 | { 38 | if (stopped) 39 | return; 40 | 41 | EnsureInvokeOnMainThread(() => 42 | { 43 | try 44 | { 45 | tick(); 46 | } 47 | catch (Exception ex) 48 | { 49 | Hilog.OH_LOG_ERROR(LogType.LOG_APP, "CSharp", ex.Message); 50 | Hilog.OH_LOG_ERROR(LogType.LOG_APP, "CSharp", ex.StackTrace); 51 | throw ex; 52 | } 53 | finally 54 | { 55 | if (!stopped) 56 | timer!.Change(interval, Timeout.InfiniteTimeSpan); 57 | } 58 | }); 59 | }, 60 | null, interval, Timeout.InfiniteTimeSpan); 61 | 62 | return new Disposable(() => 63 | { 64 | stopped = true; 65 | timer.Dispose(); 66 | }); 67 | } 68 | 69 | private void EnsureInvokeOnMainThread(Action action) 70 | { 71 | lock (list) 72 | { 73 | list.Add(action); 74 | } 75 | } 76 | 77 | public void Tick() 78 | { 79 | lock (list) 80 | { 81 | (list2, list) = (list, list2); 82 | } 83 | 84 | foreach (var action in list2) action(); 85 | list2.Clear(); 86 | } 87 | } 88 | 89 | internal class Disposable : IDisposable 90 | { 91 | private readonly Action Action; 92 | 93 | public Disposable(Action action) 94 | { 95 | Action = action; 96 | } 97 | 98 | public void Dispose() 99 | { 100 | Action?.Invoke(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyRenderTimer.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | using Avalonia.Rendering; 4 | 5 | namespace Avalonia.OpenHarmony; 6 | 7 | public class OpenHarmonyRenderTimer : IRenderTimer 8 | { 9 | private static readonly Stopwatch s_sw = Stopwatch.StartNew(); 10 | public bool RunsInBackground => false; 11 | 12 | public event Action? Tick; 13 | 14 | public void Render() 15 | { 16 | var timespan = s_sw.Elapsed; 17 | s_sw.Restart(); 18 | Tick?.Invoke(timespan); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyRuntimePlatform.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform; 2 | 3 | namespace Avalonia.OpenHarmony; 4 | 5 | public class OpenHarmonyRuntimePlatform : StandardRuntimePlatform 6 | { 7 | public override RuntimePlatformInfo GetRuntimeInfo() 8 | { 9 | var isMobile = true; 10 | var isTv = false; 11 | var result = new RuntimePlatformInfo 12 | { 13 | IsMobile = isMobile && !isTv, 14 | IsDesktop = !isMobile && !isTv, 15 | IsTV = isTv 16 | }; 17 | 18 | return result; 19 | } 20 | } -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyStorageProvider/OpenHarmonyStorageBookmarkFile.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform.Storage; 2 | 3 | namespace Avalonia.OpenHarmony; 4 | 5 | internal class OpenHarmonyStorageBookmarkFile : OpenHarmonyStorageBookmarkItemBase, IStorageBookmarkFile 6 | { 7 | internal OpenHarmonyStorageBookmarkFile(string uri) : base(uri) 8 | { 9 | _base = new FileInfo(Path.ToString()); 10 | } 11 | 12 | public Task OpenReadAsync() 13 | { 14 | return Task.Run(() => File.OpenRead(Path.ToString())); 15 | } 16 | 17 | public Task OpenWriteAsync() 18 | { 19 | return Task.Run(() => File.OpenWrite(Path.ToString())); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyStorageProvider/OpenHarmonyStorageBookmarkFolder.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform.Storage; 2 | 3 | namespace Avalonia.OpenHarmony; 4 | 5 | public class OpenHarmonyStorageBookmarkFolder : OpenHarmonyStorageBookmarkItemBase, IStorageBookmarkFolder 6 | { 7 | internal OpenHarmonyStorageBookmarkFolder(string uri) : base(uri) 8 | { 9 | _base = new DirectoryInfo(Path.ToString()); 10 | } 11 | 12 | public async IAsyncEnumerable GetItemsAsync() 13 | { 14 | foreach (var item in await Task.Run(() => ((DirectoryInfo)_base).GetDirectories())) 15 | { 16 | yield return new OpenHarmonyStorageBookmarkFolder(item.FullName); 17 | } 18 | 19 | foreach (var item in await Task.Run(() => ((DirectoryInfo)_base).GetFiles())) 20 | { 21 | yield return new OpenHarmonyStorageBookmarkFile(item.FullName); 22 | } 23 | } 24 | 25 | [Obsolete("你无权对用户文件执行此操作。")] 26 | public Task CreateFileAsync(string name) 27 | { 28 | throw new NotSupportedException("你无权对用户文件执行此操作。"); 29 | } 30 | 31 | [Obsolete("你无权对用户文件执行此操作。")] 32 | public Task CreateFolderAsync(string name) 33 | { 34 | throw new NotSupportedException("你无权对用户文件执行此操作。"); 35 | } 36 | } -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/OpenHarmonyStorageProvider/OpenHarmonyStorageBookmarkItemBase.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform.Storage; 2 | 3 | namespace Avalonia.OpenHarmony; 4 | 5 | public abstract class OpenHarmonyStorageBookmarkItemBase : IStorageBookmarkItem 6 | { 7 | protected readonly string _sourceUri; 8 | protected FileSystemInfo _base; 9 | 10 | protected unsafe OpenHarmonyStorageBookmarkItemBase(string uri) 11 | { 12 | _sourceUri = uri; 13 | var path = OpenHarmonyStorageProvider.GetPathByOpenHarmonyUri(uri); 14 | path ??= "沙箱路径转换失败"; 15 | Name = System.IO.Path.GetFileName(path); 16 | Path = new Uri(path); 17 | CanBookmark = true; 18 | } 19 | 20 | public void Dispose() 21 | { 22 | // TODO 在此释放托管资源 23 | } 24 | 25 | public Task GetBasicPropertiesAsync() 26 | { 27 | return Task.FromResult(new StorageItemProperties(null, _base.CreationTime, _base.LastWriteTime)); 28 | } 29 | 30 | #pragma warning disable CS8619 // 值中的引用类型的为 Null 性与目标类型不匹配。 31 | public Task SaveBookmarkAsync() => Task.FromResult(_sourceUri); 32 | #pragma warning restore CS8619 // 值中的引用类型的为 Null 性与目标类型不匹配。 33 | 34 | [Obsolete("你无权对用户文件执行此操作。")] 35 | public virtual Task GetParentAsync() 36 | { 37 | // return Task.FromResult(_base.); 38 | throw new NotSupportedException("你无权对用户文件执行此操作。"); 39 | } 40 | 41 | [Obsolete("你无权对用户文件执行此操作。")] 42 | public Task DeleteAsync() 43 | { 44 | throw new NotSupportedException("你无权对用户文件执行此操作。"); 45 | } 46 | 47 | [Obsolete("你无权对用户文件执行此操作。")] 48 | public Task MoveAsync(IStorageFolder destination) 49 | { 50 | throw new NotSupportedException("你无权对用户文件执行此操作。"); 51 | } 52 | 53 | public string Name { get; } 54 | public Uri Path { get; } 55 | public bool CanBookmark { get; } 56 | 57 | public Task ReleaseBookmarkAsync() 58 | { 59 | return Task.CompletedTask; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/SingleViewLifetime.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Controls.Embedding; 4 | 5 | namespace Avalonia.OpenHarmony; 6 | 7 | public class SingleViewLifetime : ISingleViewApplicationLifetime 8 | { 9 | private Control? _mainView; 10 | public EmbeddableControlRoot? Root; 11 | 12 | public Control? MainView 13 | { 14 | get => _mainView; 15 | set 16 | { 17 | _mainView = value; 18 | Root!.Content = value; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/XComponent.cs: -------------------------------------------------------------------------------- 1 | using OpenHarmony.NDK.Bindings.Native; 2 | 3 | namespace Avalonia.OpenHarmony; 4 | 5 | public class XComponent 6 | { 7 | public XComponent(IntPtr XComponentHandle, IntPtr WindowHandle) 8 | { 9 | this.XComponentHandle = XComponentHandle; 10 | this.WindowHandle = WindowHandle; 11 | } 12 | 13 | public IntPtr XComponentHandle { get; } 14 | public IntPtr WindowHandle { get; } 15 | 16 | public virtual unsafe Size GetSize() 17 | { 18 | ulong Width = 0; 19 | ulong Height = 0; 20 | Ace.OH_NativeXComponent_GetXComponentSize((OH_NativeXComponent*)XComponentHandle, (void*)WindowHandle, &Width, 21 | &Height); 22 | return new Size(Width, Height); 23 | } 24 | 25 | public virtual void OnSurfaceCreated() 26 | { 27 | } 28 | 29 | 30 | public virtual void OnSurfaceDestroyed() 31 | { 32 | } 33 | 34 | 35 | public virtual void OnSurfaceRendered(ulong timestamp, ulong targetTimestamp) 36 | { 37 | } 38 | 39 | public virtual void OnSurfaceChanged() 40 | { 41 | } 42 | 43 | public virtual void DispatchTouchEvent() 44 | { 45 | } 46 | } -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/libs/Avalonia.Skia/Avalonia.Skia.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Avalonia.OpenHarmony/libs/Avalonia.Skia/Avalonia.Skia.dll -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/libs/HarfBuzzSharp/HarfBuzzSharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Avalonia.OpenHarmony/libs/HarfBuzzSharp/HarfBuzzSharp.dll -------------------------------------------------------------------------------- /Src/Avalonia.OpenHarmony/libs/SkiaSharp/SkiaSharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Avalonia.OpenHarmony/libs/SkiaSharp/SkiaSharp.dll -------------------------------------------------------------------------------- /Src/Entry/Entry.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | true 8 | libavalonia 9 | 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 | -------------------------------------------------------------------------------- /Src/Entry/Properties/PublishProfiles/PublishAmd64.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Releases 8 | Any CPU 9 | ../../OHOS_Project/entry/libs/x86_64 10 | FileSystem 11 | <_TargetId>Folder 12 | net9.0 13 | linux-musl-x64 14 | true 15 | true 16 | 17 | -------------------------------------------------------------------------------- /Src/Entry/Properties/PublishProfiles/PublishArm64.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Debug 8 | Any CPU 9 | ../../OHOS_Project/entry/libs/arm64-v8a 10 | FileSystem 11 | <_TargetId>Folder 12 | net9.0 13 | linux-musl-arm64 14 | true 15 | true 16 | 17 | -------------------------------------------------------------------------------- /Src/Entry/XComponentEntry.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Runtime.InteropServices; 3 | 4 | using Avalonia.OpenHarmony; 5 | 6 | using AOOH_Gallery; 7 | 8 | using OpenHarmony.NDK.Bindings.Native; 9 | 10 | namespace Entry; 11 | 12 | public static unsafe class XComponentEntry 13 | { 14 | public static Dictionary XComponents = []; 15 | 16 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] 17 | public static void OnSurfaceCreated(OH_NativeXComponent* component, void* window) 18 | { 19 | try 20 | { 21 | Ace.OH_NativeXComponent_RegisterOnFrameCallback(component, &OnSurfaceRendered); 22 | if (XComponents.TryGetValue((nint)component, out var xComponent)) 23 | return; 24 | xComponent = new AvaloniaXComponent((nint)component, (nint)window); 25 | XComponents.Add((nint)component, xComponent); 26 | xComponent.OnSurfaceCreated(); 27 | } 28 | catch (Exception ex) 29 | { 30 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "csharp", ex.Message); 31 | if (ex.StackTrace != null) Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "csharp", ex.StackTrace); 32 | 33 | if (ex.InnerException != null) 34 | { 35 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "csharp", ex.InnerException.Message); 36 | if (ex.InnerException.StackTrace != null) 37 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "csharp", ex.InnerException.StackTrace); 38 | } 39 | } 40 | } 41 | 42 | 43 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] 44 | public static void OnSurfaceRendered(OH_NativeXComponent* component, ulong timestamp, ulong targetTimestamp) 45 | { 46 | try 47 | { 48 | if (XComponents.TryGetValue((nint)component, out var xComponent) == false) 49 | return; 50 | xComponent.OnSurfaceRendered(timestamp, targetTimestamp); 51 | } 52 | catch (Exception ex) 53 | { 54 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "csharp", ex.Message); 55 | if (ex.StackTrace != null) Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "csharp", ex.StackTrace); 56 | 57 | if (ex.InnerException != null) 58 | { 59 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "csharp", ex.InnerException.Message); 60 | if (ex.InnerException.StackTrace != null) 61 | Hilog.OH_LOG_DEBUG(LogType.LOG_APP, "csharp", ex.InnerException.StackTrace); 62 | } 63 | } 64 | } 65 | 66 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] 67 | public static void OnSurfaceChanged(OH_NativeXComponent* component, void* window) 68 | { 69 | if (XComponents.TryGetValue((nint)component, out var xComponent) == false) 70 | return; 71 | xComponent.OnSurfaceChanged(); 72 | } 73 | 74 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] 75 | public static void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window) 76 | { 77 | if (XComponents.TryGetValue((nint)component, out var xComponent) == false) 78 | return; 79 | xComponent.OnSurfaceDestroyed(); 80 | XComponents.Remove((nint)component); 81 | } 82 | 83 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] 84 | public static void DispatchTouchEvent(OH_NativeXComponent* component, void* window) 85 | { 86 | if (XComponents.TryGetValue((nint)component, out var xComponent) == false) 87 | return; 88 | xComponent.DispatchTouchEvent(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Src/Entry/napi_init.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Runtime.InteropServices; 3 | 4 | using Avalonia.OpenHarmony; 5 | 6 | using OpenHarmony.NDK.Bindings.Native; 7 | 8 | namespace Entry; 9 | 10 | public class napi_init 11 | { 12 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)], EntryPoint = "RegisterEntryModule")] 13 | public static unsafe void RegisterEntryModule() 14 | { 15 | try 16 | { 17 | const string moduleName = "entry"; 18 | var moduleNamePtr = Marshal.StringToHGlobalAnsi(moduleName); 19 | var demoModule = new napi_module 20 | { 21 | nm_version = 1, 22 | nm_flags = 0, 23 | nm_filename = null, 24 | nm_modname = (sbyte*)moduleNamePtr, 25 | nm_priv = null, 26 | napi_addon_register_func = &Init, 27 | reserved_0 = null, 28 | reserved_1 = null, 29 | reserved_2 = null, 30 | reserved_3 = null 31 | }; 32 | 33 | node_api.napi_module_register(&demoModule); 34 | } 35 | catch (Exception e) 36 | { 37 | Hilog.OH_LOG_ERROR(LogType.LOG_APP, "csharp", e.Message); 38 | Hilog.OH_LOG_ERROR(LogType.LOG_APP, "csharp", e.StackTrace); 39 | } 40 | } 41 | 42 | [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] 43 | public static unsafe napi_value Init(napi_env env, napi_value exports) 44 | { 45 | napi_value exportInstance = default; 46 | OH_NativeXComponent* nativeXComponent = null; 47 | int ret = default; 48 | var xcomponentName = "__NATIVE_XCOMPONENT_OBJ__"; 49 | var xcomponentNamePtr = Marshal.StringToHGlobalAnsi(xcomponentName); 50 | if (node_api.napi_get_named_property(env, exports, (sbyte*)xcomponentNamePtr, &exportInstance) == 51 | napi_status.napi_ok) 52 | { 53 | if (node_api.napi_unwrap(env, exportInstance, (void**)&nativeXComponent) == napi_status.napi_ok) 54 | { 55 | var p = Marshal.AllocHGlobal(sizeof(OH_NativeXComponent_Callback)); 56 | ref var g_ComponentCallback = ref Unsafe.AsRef((void*)p); 57 | g_ComponentCallback.OnSurfaceCreated = &XComponentEntry.OnSurfaceCreated; 58 | g_ComponentCallback.OnSurfaceChanged = &XComponentEntry.OnSurfaceChanged; 59 | g_ComponentCallback.OnSurfaceDestroyed = &XComponentEntry.OnSurfaceDestroyed; 60 | g_ComponentCallback.DispatchTouchEvent = &XComponentEntry.DispatchTouchEvent; 61 | Ace.OH_NativeXComponent_RegisterCallback(nativeXComponent, (OH_NativeXComponent_Callback*)p); 62 | } 63 | } 64 | 65 | Marshal.FreeHGlobal(xcomponentNamePtr); 66 | try 67 | { 68 | const int methodNamesLength = 5; 69 | var desc = stackalloc napi_property_descriptor[methodNamesLength] 70 | { 71 | Create((sbyte*)Marshal.StringToHGlobalAnsi("setStartDocumentViewPicker"), 72 | &OpenHarmonyStorageProvider.SetStartDocumentViewPicker), 73 | Create((sbyte*)Marshal.StringToHGlobalAnsi("setStartDocumentViewPickerSaveMode"), 74 | &OpenHarmonyStorageProvider.SetStartDocumentViewPickerSaveMode), 75 | Create((sbyte*)Marshal.StringToHGlobalAnsi("setPickerResult"), 76 | &OpenHarmonyStorageProvider.SetPickerResult), 77 | Create((sbyte*)Marshal.StringToHGlobalAnsi("setColor"), 78 | &OpenHarmonyPlatformSettings.SetColor), 79 | Create((sbyte*)Marshal.StringToHGlobalAnsi("setInputPaneHeight"), 80 | &OpenHarmonyInputPane.SetInputPaneHeight), 81 | }; 82 | 83 | napi_property_descriptor Create(sbyte* methodName, 84 | delegate* unmanaged[Cdecl] method) 85 | { 86 | return new() 87 | { 88 | utf8name = methodName, 89 | name = default, 90 | method = method, 91 | getter = null, 92 | setter = null, 93 | value = default, 94 | attributes = napi_property_attributes.napi_default, 95 | data = null 96 | }; 97 | } 98 | 99 | node_api.napi_define_properties(env, exports, methodNamesLength, desc); 100 | for (int i = 0; i < methodNamesLength; i++) 101 | Marshal.FreeHGlobal((IntPtr)desc[i].utf8name); 102 | } 103 | catch (Exception e) 104 | { 105 | Hilog.OH_LOG_ERROR(LogType.LOG_APP, "testTag", $"{e}"); 106 | } 107 | 108 | return exports; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Src/Entry/rd.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libHarfBuzzSharp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libHarfBuzzSharp.so -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libSkiaSharp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libSkiaSharp.so -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libbrotlicommon.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libbrotlicommon.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libbrotlicommon.so.1.1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libbrotlicommon.so.1.1.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libbrotlidec.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libbrotlidec.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libbrotlidec.so.1.1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libbrotlidec.so.1.1.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libbrotlienc.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libbrotlienc.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libbrotlienc.so.1.1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libbrotlienc.so.1.1.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libbz2.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libbz2.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libbz2.so.1.0.8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libbz2.so.1.0.8 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libexpat.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libexpat.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libexpat.so.1.9.3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libexpat.so.1.9.3 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libfontconfig.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libfontconfig.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libfontconfig.so.1.12.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libfontconfig.so.1.12.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libfreetype.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libfreetype.so.6 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libfreetype.so.6.20.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libfreetype.so.6.20.2 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libpng16.so.16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libpng16.so.16 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libpng16.so.16.44.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libpng16.so.16.44.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libz.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libz.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/arm64-v8a/libz.so.1.3.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/arm64-v8a/libz.so.1.3.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libHarfBuzzSharp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libHarfBuzzSharp.so -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libSkiaSharp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libSkiaSharp.so -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libbrotlicommon.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libbrotlicommon.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libbrotlicommon.so.1.1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libbrotlicommon.so.1.1.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libbrotlidec.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libbrotlidec.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libbrotlidec.so.1.1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libbrotlidec.so.1.1.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libbrotlienc.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libbrotlienc.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libbrotlienc.so.1.1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libbrotlienc.so.1.1.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libbz2.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libbz2.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libbz2.so.1.0.8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libbz2.so.1.0.8 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libexpat.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libexpat.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libexpat.so.1.10.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libexpat.so.1.10.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libfontconfig.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libfontconfig.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libfontconfig.so.1.12.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libfontconfig.so.1.12.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libfreetype.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libfreetype.so.6 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libfreetype.so.6.20.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libfreetype.so.6.20.2 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libpng16.so.16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libpng16.so.16 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libpng16.so.16.44.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libpng16.so.16.44.0 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libz.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libz.so.1 -------------------------------------------------------------------------------- /Src/Entry/runtimes/x86_64/libz.so.1.3.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Entry/runtimes/x86_64/libz.so.1.3.1 -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery.Desktop/AOOH_Gallery.Desktop.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | enable 7 | enable 8 | app.manifest 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery.Desktop/Program.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.ReactiveUI; 3 | 4 | namespace AOOH_Gallery; 5 | 6 | internal sealed class Program 7 | { 8 | // Initialization code. Don't use any Avalonia, third-party APIs or any 9 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 10 | // yet and stuff might break. 11 | [STAThread] 12 | public static void Main(string[] args) 13 | { 14 | BuildAvaloniaApp() 15 | .StartWithClassicDesktopLifetime(args); 16 | } 17 | 18 | // Avalonia configuration, don't remove; also used by visual designer. 19 | public static AppBuilder BuildAvaloniaApp() 20 | { 21 | return AppBuilder.Configure() 22 | .UsePlatformDetect() 23 | .LogToTrace() 24 | .UseReactiveUI(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery.Desktop/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/AOOH_Gallery.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | enable 5 | true 6 | true 7 | preview 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | None 21 | All 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | all 30 | runtime; build; native; contentfiles; analyzers; buildtransitive 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ..\..\Avalonia.OpenHarmony\libs\SkiaSharp\SkiaSharp.dll 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/App.axaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | HarmonyOS Sans SC 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using AOOH_Gallery.ViewModels; 2 | using AOOH_Gallery.Views; 3 | 4 | using Avalonia; 5 | using Avalonia.Controls.ApplicationLifetimes; 6 | using Avalonia.Markup.Xaml; 7 | 8 | namespace AOOH_Gallery; 9 | 10 | public class App : Application 11 | { 12 | public override void Initialize() 13 | { 14 | AvaloniaXamlLoader.Load(this); 15 | } 16 | 17 | public override void OnFrameworkInitializationCompleted() 18 | { 19 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 20 | desktop.MainWindow = new MainWindow 21 | { 22 | DataContext = new MainViewViewModel() 23 | }; 24 | else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) 25 | singleViewPlatform.MainView = new MainView 26 | { 27 | DataContext = null 28 | }; 29 | 30 | base.OnFrameworkInitializationCompleted(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Assets/Gallery Home 背景图片.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AOOH_Gallery/Assets/Gallery Home 背景图片.png -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Assets/OpenHarmony.Net组织头像.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AOOH_Gallery/Assets/OpenHarmony.Net组织头像.png -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Assets/avalonia-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AOOH_Gallery/Assets/avalonia-logo.ico -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/ViewLocator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using AOOH_Gallery.ViewModels; 4 | 5 | using Avalonia.Controls; 6 | using Avalonia.Controls.Templates; 7 | 8 | namespace AOOH_Gallery; 9 | 10 | public class ViewLocator : IDataTemplate 11 | { 12 | public Control? Build(object? param) 13 | { 14 | if (param is null) 15 | return null; 16 | 17 | var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); 18 | var type = Type.GetType(name); 19 | 20 | if (type != null) return (Control)Activator.CreateInstance(type)!; 21 | 22 | return new TextBlock { Text = "Not Found: " + name }; 23 | } 24 | 25 | public bool Match(object? data) 26 | { 27 | return data is ViewModelBase; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/ViewModels/MainViewViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace AOOH_Gallery.ViewModels; 2 | 3 | public class MainViewViewModel : ViewModelBase 4 | { 5 | public string Greeting { get; } = "Welcome to Avalonia!"; 6 | } -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace AOOH_Gallery.ViewModels; 4 | 5 | public class ViewModelBase : ReactiveObject 6 | { 7 | } -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/FQA.axaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/FQA.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace AOOH_Gallery.Views; 4 | 5 | public partial class FQA : UserControl 6 | { 7 | public static string FQA_1 = 8 | """ 9 | 我们正在寻找一个包含丰富 Avalonia 基础内容的控件库用于展示,Semi 和 Ursa 恰好能够满足我们的要求。 10 | 以下是作者对它们的介绍: 11 | 12 | Hello大家好,我是Avalonia中文社区的发起人和主理人董彬。 13 | 14 | 今天通过这次简单的闪电演讲简单介绍一下我们的开源项目大熊Ursa以及其中所包含的设计理念。 15 | 16 | 关于Avalonia我这边就不过多介绍了,前面孙策老师的session大家应该都听到了。 17 | 18 | 在今年我们的开源贡献主要是聚焦在Semi和Ursa两个项目中。想要了解Ursa的设计理念,我首先要谈一谈Semi的设计理念。Semi是我们的一个样式库,他为Avalonia的所有内置控件提供了基于字节跳动Semi Design风格的主题。Semi Avalonia是一个非常纯粹的样式库,他只有样式,没有功能。 19 | 20 | Semi在设计之初就是针对Avalonia V11的新世界打造,充分利用了ControlTheme+Style结合的样式体系,于是我们不需要derive一个子类增加关于样式的属性,也不需要声明很多附加属性,单单凭借StyleClass,就可以让控件的外观拥有更多的可能性。 21 | 22 | Semi这个样式库在理论上可以实现的另一个原因是Avalonia控件充分支持无样式设计。Avalonia的原生控件的功能与样式是完全分离的,只要控件的模板内包含必须的功能相关的元素,那么他在哪里,如何布局,用什么类型去实现,都不重要。 23 | 24 | 那么我一方面出于探索Avalonia样式系统的目的,另一方面考虑到公司的整体产品规划,Semi Avalonia主要遵循了以下几个设计理念: 25 | 第一,Semi Avalonia完全不引入自定义控件,所有的视觉风格全部都使用Avalonia内置的元素实现,尤其是不会使用内部类。这主要是为了方便开发者基于Semi Avalonia进行二次开发。如果你需要在自己的项目中开发一个自定义控件,那么Semi Avalonia的所有视觉效果都应该可以直接仿照实现。这是我们和Material、FluentAvalonia等项目最大的区别。我们始终承诺,一个程序可以无缝地在内置Fluent主题和Semi Avalonia之间切换,他运行起来可能看起来不太舒服,但绝对不会跑不起来。虽然我们是Semi的开发维护者,虽然我们非常希望大家更多地去使用Semi,但我们设计这个项目最先考虑的问题,就是当大家不想用Semi主题的时候,如何帮助大家潇洒地转身离开。 26 | 第二,Semi Avalonia采用了非常细粒度的DesignToken。Design Token是一个在UI设计界比较常见的概念。比如我的设计体系中有基础的色板提供颜色的Token,比如Blue12345,Red12345,然后我可能会有一层业务相关的抽象token,比如我的Primary,我的Warning。最终我可能会有一层代码相关的token,比如我的ButtonHoverBackground,TextForeground等等。在Semi Avalonia中我们暴论给控件的是最细粒度的Token。我们采取这样的设计,主要是为了实现UI最细粒度的资源变更。在Semi Avalonia中,你可以在UI的任何一个节点通过重新定义动态资源的方式对控件中引用的动态资源进行覆盖。完全不影响视觉树中的其他元素。并且由于我们前期对DesignToken做了非常正确的规划,因此我们几乎没有对控件模板的基础施舍做修改,就顺利地引入了高对比度配色的四种配色方案,这也证明了Semi Avalonia在配色方面的灵活性 27 | 28 | Semi Avalonia本身是一次非常成功的尝试,但这种设计理念导致我们没有办法在功能上对Avalonia进行拓展,于是我们就开启了第二个开源项目Ursa。Ursa本身在定位上可以说是与与Semi Avalonia完全相反的。Semi只有样式,没有功能,而Ursa只有功能,没有样式。他完全遵守Avalonia控件无样式设计的理念,只在代码中定义最核心的与功能相关的模板子元素,而完全不在代码包含任何与样式相关的内容。 29 | 30 | Ursa在设计的时候还进行了以下几个方面的考量,也算是Ursa的设计理念。这里要提前说明的是,Ursa的这些所谓的设计理念,是从控件库设计的角度考虑,和真正的应用开发并不一样。 31 | 首先,Ursa整体上是视图模型中立的。一方面呢,Ursa中的控件通常并不规定用户的ViewModel应该如何实现,如果我们用接口去规定一个VM应该有什么属性,那会导致你的VM不得不包含一个名字已经确定的,但与业务有关的属性。我们在设计中或是支持让用户通过编译绑定路径的方式去自定义,或者是保证我们限定的接口完全与实际业务无关 32 | 另外一方面呢,Ursa的实现并不依赖任何MVVM框架。无论是Prism还是CommunityToolkit或是ReactiveUI,都可以和Ursa配合使用,并不会出现您使用的MVVM框架和Ursa内置的什么东西产生冲突的情况。 33 | 但这样会导致有些MVVM框架内置的一些优秀设计没有办法利用起来,那么就引入了Ursa的第二个特点: 34 | 35 | 易于与第三方框架实现桥接。比如我们的Dialog,OverlayDialog其实很好用,和WPF MessageBox一样用静态类就能调用出来。但是就是有人希望不要在VM里面直接去使用一个静态类,比如和Prism集成使用之后,我希望能够用依赖注入的方法调用Dialog。那么针对这些情况,Ursa就会提供相应的基础设施和拓展包,方便使用Prism开发者注册和调用Dialog都能够无感地使用Prism相关的开发范式。同样我们也针对ReactiveUI提供了兼容ReactiveWindow和UrsaWindow的拓展包。 36 | 37 | 第三个特点,就是原生支持NativeAOT。我们全部使用编译绑定来开发,没有反射的需求,因此Ursa的控件都自然支持NativeAOT,你甚至不需要针对Semi Avalonia和Ursa进行任何剪裁的配置,就可以实现NativeAOT 编译。 38 | 39 | 当我们实现了这些功能的之后,终归还是需要给他一个外观,于是作为Semi Avalonia的维护团队,我们默认提供的是基于Semi Design设计风格的主题。但是,Ursa的Semi主题并不与Semi Avalonia这个库强绑定,实际上如果你有一个基于Semi Avalonia的Design Token实现了自己的主题库,那么即便不引用Semi Avalonia本体,Ursa 的Semi主题依然可以生效。并且Ursa大量复用Semi Avalonia的semantic token,比如Ursa中的多选ComboBox,那么他所使用的动态资源都是原生ComboBox相关的,这样您基于自己公司业务打造的主题在Ursa的Semi主题中也是和谐的。也正式因为这个良好的基础设施,Ursa很快就完成了Semi高对比度配色的适配。 40 | 41 | 可惜的是由于我们人力有限,很多人会认为Ursa与Semi是强绑定的。但这是一种错误的认知。Ursa本身作为一个无样式控件库,是可以基于任何设计风格进行设计的。为了打破这种错误的认知,我们也是加班加点打造了一个Ursa的全新样式库。这就是与Classic Avalonia联合开发的Ursa Classic主题,应用这个主题,你可以重现Windows95时代的控件样式。我们只需要利用Classic Avalonia项目中提供的图元,就可以将Ursa打造成Classic风格的控件。 42 | 43 | 并且,这并不是一个必须全局使用的主题,他甚至可以在任何局部范围内使用,比如我们这个Demo程序本身是使用Semi主题来进行打造的,但这并不妨碍我们直接对其中一个部分应用Classic主题,这就是我们无样式设计理念所能够达到的效果。 44 | 45 | 这个Classic主题我们仍在开发当中,但是很快就能和大家见面了。 46 | 47 | 那么以上就是我们过去一年中重点开发的Semi 和 Ursa两个开源项目,希望大家能够对我们的设计体系有进一步的了解,我们的项目已经支持了很多企业项目落地,欢迎您的下一个跨平台桌面应用使用Semi 和Ursa实现生产力的美学进化。 48 | """; 49 | 50 | public FQA() 51 | { 52 | InitializeComponent(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/IMEPage.axaml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/IMEPage.axaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reactive.Linq; 3 | 4 | using Avalonia.Controls; 5 | using Avalonia.Interactivity; 6 | 7 | using ReactiveMarbles.ObservableEvents; 8 | 9 | namespace AOOH_Gallery.Views; 10 | 11 | public partial class IMEPage : UserControl 12 | { 13 | public IMEPage() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | protected override void OnLoaded(RoutedEventArgs e) 19 | { 20 | base.OnLoaded(e); 21 | var inputPane = TopLevel.GetTopLevel(this)!.InputPane; 22 | inputPane.Events().StateChanged.Do(_ => { Rectangle.Height = inputPane!.OccludedRect.Height; }).Subscribe(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/MainView.axaml: -------------------------------------------------------------------------------- 1 |  13 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 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 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/MainView.axaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Specialized; 3 | using System.Reactive.Linq; 4 | 5 | using Avalonia.Controls; 6 | using Avalonia.Data.Converters; 7 | using Avalonia.OpenHarmony; 8 | using Avalonia.Threading; 9 | 10 | using ReactiveMarbles.ObservableEvents; 11 | 12 | namespace AOOH_Gallery.Views; 13 | 14 | public partial class MainView : UserControl 15 | { 16 | public static FuncValueConverter GetPaneHeightConverter = new(input => input / 3 * 2); 17 | 18 | public MainView() 19 | { 20 | InitializeComponent(); 21 | (OHDebugHelper.Logs as INotifyCollectionChanged).Events().CollectionChanged 22 | .Do(_ => Dispatcher.UIThread.Post(() => ListBox.ScrollIntoView(OHDebugHelper.Logs.Count - 1))) 23 | .Subscribe(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/MainWindow.axaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace AOOH_Gallery.Views; 4 | 5 | public partial class MainWindow : Window 6 | { 7 | public MainWindow() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/StorgePage.axaml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 文件夹多选问题 17 | 18 | 当前文件夹不支持多选。原因如下:当前只有ArkTS的documentSelectOptions.selectMode=MIXED文件夹才能多选。而Avalonia的存储服务接口并未要求实现混合选择模式。 19 | 20 | 文件操作权限 21 | 22 | 你只能对用户文件进行读写,你无权执行移动、删除或创建。 23 | 24 | 综上所述,不实现如下接口的方法: 25 | 26 | - IStorageBookmarkItem的DeleteAsync、MoveAsync、GetParentAsync方法。 27 | 28 | - IStorageBookmarkFolder的CreateFileAsync、CreateFolderAsync方法。 29 | 30 | 31 | 32 | 33 | 34 | 35 | [x] 调用系统提供的文件选取。 36 | 37 | [x] 文件与文件夹的选取。 38 | 39 | [x] 文件的保存。 40 | 41 | [] 书签能力。 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/StorgePage.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace AOOH_Gallery.Views; 4 | 5 | public partial class StorgePage : UserControl 6 | { 7 | public StorgePage() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/SystemFonts.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 你能够直接使用的系统字体如下 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Src/Example/AOOH_Gallery/Views/SystemFonts.axaml.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | using Avalonia.Controls; 4 | using Avalonia.Interactivity; 5 | using Avalonia.Media; 6 | 7 | namespace AOOH_Gallery.Views; 8 | 9 | public partial class SystemFonts : UserControl 10 | { 11 | public SystemFonts() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | protected override void OnLoaded(RoutedEventArgs e) 17 | { 18 | base.OnLoaded(e); 19 | ListBox.ItemsSource = FontManager.Current.SystemFonts.Select(x => x.Name); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp.Desktop/AvaloniaApp.Desktop.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | WinExe 4 | 6 | net8.0 7 | enable 8 | true 9 | 10 | 11 | 12 | app.manifest 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp.Desktop/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Avalonia; 4 | 5 | namespace AvaloniaApp.Desktop; 6 | 7 | public sealed class Program 8 | { 9 | // Initialization code. Don't use any Avalonia, third-party APIs or any 10 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 11 | // yet and stuff might break. 12 | [STAThread] 13 | public static void Main(string[] args) 14 | { 15 | BuildAvaloniaApp() 16 | .StartWithClassicDesktopLifetime(args); 17 | } 18 | 19 | // Avalonia configuration, don't remove; also used by visual designer. 20 | public static AppBuilder BuildAvaloniaApp() 21 | { 22 | return AppBuilder.Configure() 23 | .UsePlatformDetect() 24 | .WithInterFont() 25 | .LogToTrace(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp.Desktop/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "AvaloniaExample.Desktop": { 4 | "commandName": "Project" 5 | }, 6 | "WSL": { 7 | "commandName": "WSL2", 8 | "distributionName": "" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp.Desktop/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/App.axaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Data.Core.Plugins; 4 | using Avalonia.Markup.Xaml; 5 | 6 | using AvaloniaApp.ViewModels; 7 | using AvaloniaApp.Views; 8 | 9 | namespace AvaloniaApp; 10 | 11 | public class App : Application 12 | { 13 | public override void Initialize() 14 | { 15 | AvaloniaXamlLoader.Load(this); 16 | } 17 | 18 | public override void OnFrameworkInitializationCompleted() 19 | { 20 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 21 | { 22 | // Line below is needed to remove Avalonia data validation. 23 | // Without this line you will get duplicate validations from both Avalonia and CT 24 | BindingPlugins.DataValidators.RemoveAt(0); 25 | desktop.MainWindow = new MainWindow 26 | { 27 | DataContext = new MainViewModel() 28 | }; 29 | } 30 | else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) 31 | { 32 | singleViewPlatform.MainView = new MainView 33 | { 34 | DataContext = new MainViewModel() 35 | }; 36 | } 37 | 38 | base.OnFrameworkInitializationCompleted(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/O1CN01T2ugeo1gJT57UONrC_!!0-item_pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/O1CN01T2ugeo1gJT57UONrC_!!0-item_pic.jpg -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/appreciate_fill_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/appreciate_fill_light.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/apps (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/apps (1).png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/avalonia-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/avalonia-logo.ico -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/deliver_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/deliver_fill.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/emoji1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/emoji1.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/emoji2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/emoji2.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/emoji3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/emoji3.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/emoji4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/emoji4.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/group (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/group (1).png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/home.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/home_fill_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/home_fill_light.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/mark.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/mark_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/mark_fill.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/money_bag_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/money_bag_fill.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/news_hot_fill_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/news_hot_fill_light.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/news_hot_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/news_hot_light.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/people.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/people_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/people_fill.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/right.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/round_right_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/round_right_fill.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/search (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/search (1).png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/search.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Assets/test_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHarmony-NET/OpenHarmony.Avalonia/c5d2c17470f032aac2023a2bd716807fa18cf739/Src/Example/AvaloniaApp/Assets/test_image.png -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/AvaloniaApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | enable 5 | latest 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/ViewLocator.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Controls.Templates; 3 | 4 | using AvaloniaApp.ViewModels; 5 | using AvaloniaApp.Views; 6 | 7 | namespace AvaloniaApp; 8 | 9 | public class ViewLocator : IDataTemplate 10 | { 11 | public Control? Build(object? data) 12 | { 13 | if (data is null) 14 | return null; 15 | if (data is HomePageViewModel) 16 | return new HomePageView(); 17 | if (data is NewsPageViewModel) 18 | return new NewsPageView(); 19 | if (data is MessagePageViewModel) 20 | return new MessagePageView(); 21 | if (data is ProfilePageViewModel) 22 | return new ProfilePageView(); 23 | 24 | return new TextBlock { Text = "Not Found: " + data.GetType().FullName }; 25 | } 26 | 27 | public bool Match(object? data) 28 | { 29 | return data is ViewModelBase; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/ViewModels/HomePageViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace AvaloniaApp.ViewModels; 2 | 3 | public class HomePageViewModel : ViewModelBase 4 | { 5 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace AvaloniaApp.ViewModels; 4 | 5 | public partial class MainViewModel : ViewModelBase 6 | { 7 | [ObservableProperty] private ViewModelBase _currentViewModel; 8 | 9 | [ObservableProperty] private HomePageViewModel _homePageViewModel = new(); 10 | 11 | [ObservableProperty] private MessagePageViewModel _messagePageViewModel = new(); 12 | 13 | [ObservableProperty] private NewsPageViewModel _newsPageViewModel = new(); 14 | 15 | [ObservableProperty] private ProfilePageViewModel _profilePageViewModel = new(); 16 | 17 | 18 | [ObservableProperty] public bool _showHome = true; 19 | 20 | [ObservableProperty] public bool _showMessage; 21 | 22 | [ObservableProperty] public bool _showNews; 23 | 24 | [ObservableProperty] public bool _showProfile; 25 | 26 | public MainViewModel() 27 | { 28 | _currentViewModel = _homePageViewModel; 29 | ChangeTo(0); 30 | } 31 | 32 | public void ChangeTo(int i) 33 | { 34 | ShowHome = false; 35 | ShowNews = false; 36 | ShowMessage = false; 37 | ShowProfile = false; 38 | if (i == 0) 39 | { 40 | CurrentViewModel = HomePageViewModel; 41 | ShowHome = true; 42 | } 43 | else if (i == 1) 44 | { 45 | CurrentViewModel = NewsPageViewModel; 46 | ShowNews = true; 47 | } 48 | else if (i == 2) 49 | { 50 | CurrentViewModel = MessagePageViewModel; 51 | ShowMessage = true; 52 | } 53 | else if (i == 3) 54 | { 55 | CurrentViewModel = ProfilePageViewModel; 56 | ShowProfile = true; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/ViewModels/MessagePageViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace AvaloniaApp.ViewModels; 2 | 3 | public class MessagePageViewModel : ViewModelBase 4 | { 5 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/ViewModels/NewsPageViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace AvaloniaApp.ViewModels; 2 | 3 | public class NewsPageViewModel : ViewModelBase 4 | { 5 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/ViewModels/ProfilePageViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace AvaloniaApp.ViewModels; 2 | 3 | public class ProfilePageViewModel : ViewModelBase 4 | { 5 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace AvaloniaApp.ViewModels; 4 | 5 | public abstract class ViewModelBase : ObservableObject 6 | { 7 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/HomePageView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace AvaloniaApp.Views; 4 | 5 | public partial class HomePageView : UserControl 6 | { 7 | public HomePageView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/MainView.axaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 13 | 14 | 15 | 18 | 22 | 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 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/MainView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Input; 3 | using Avalonia.Input.TextInput; 4 | 5 | using AvaloniaApp.ViewModels; 6 | 7 | namespace AvaloniaApp.Views; 8 | 9 | public partial class MainView : UserControl 10 | { 11 | public MainView() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | private void OnShowHomeClick(object sender, PointerPressedEventArgs e) 17 | { 18 | var viewmodel = DataContext as MainViewModel; 19 | if (viewmodel == null) 20 | return; 21 | viewmodel.ChangeTo(0); 22 | } 23 | 24 | private void OnShowNewsClick(object sender, PointerPressedEventArgs e) 25 | { 26 | var viewmodel = DataContext as MainViewModel; 27 | if (viewmodel == null) 28 | return; 29 | viewmodel.ChangeTo(1); 30 | } 31 | 32 | private void OnShowMessageClick(object sender, PointerPressedEventArgs e) 33 | { 34 | var viewmodel = DataContext as MainViewModel; 35 | if (viewmodel == null) 36 | return; 37 | viewmodel.ChangeTo(2); 38 | } 39 | 40 | private void OnShowProfileClick(object sender, PointerPressedEventArgs e) 41 | { 42 | var viewmodel = DataContext as MainViewModel; 43 | if (viewmodel == null) 44 | return; 45 | viewmodel.ChangeTo(3); 46 | } 47 | 48 | private void InputElement_OnTextInput(object? sender, TextInputEventArgs e) 49 | { 50 | } 51 | 52 | private void InputElement_OnTextInputMethodClientRequested(object? sender, 53 | TextInputMethodClientRequestedEventArgs e) 54 | { 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/MainWindow.axaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace AvaloniaApp.Views; 4 | 5 | public partial class MainWindow : Window 6 | { 7 | public MainWindow() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/MessagePageView.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 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 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 54 | 55 | 56 | 58 | 59 | 60 | 61 | 62 | 63 | 65 | 66 | 67 | 68 | 69 | 70 | 72 | 73 | 74 | 75 | 76 | 77 | 79 | 80 | 81 | 82 | 83 | 84 | 86 | 87 | 88 | 89 | 90 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 106 | 107 | 108 | 109 | 110 | 111 | 113 | 114 | 115 | 116 | 117 | 118 | 120 | 121 | 122 | 123 | 124 | 125 | 127 | 128 | 129 | 130 | 131 | 132 | 134 | 135 | 136 | 137 | 138 | 139 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/MessagePageView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace AvaloniaApp.Views; 4 | 5 | public partial class MessagePageView : UserControl 6 | { 7 | public MessagePageView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/NewsPageView.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 79 | 80 | 81 | 82 | 83 | 84 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 99 | 100 | 101 | 102 | 103 | 104 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 119 | 120 | 121 | 122 | 123 | 124 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/NewsPageView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace AvaloniaApp.Views; 4 | 5 | public partial class NewsPageView : UserControl 6 | { 7 | public NewsPageView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/ProfilePageView.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | 67 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 81 | 82 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 96 | 97 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 111 | 112 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 126 | 127 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /Src/Example/AvaloniaApp/Views/ProfilePageView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace AvaloniaApp.Views; 4 | 5 | public partial class ProfilePageView : UserControl 6 | { 7 | public ProfilePageView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } --------------------------------------------------------------------------------