[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [muak]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n---\nname: Bug report\nabout: Create a report to help us improve\n---\n\n### Description\n\n### Steps to Reproduce\n\n1. \n2. \n3. \n\n### Expected Behavior\n\n### Actual Behavior\n\n### Platforms\n\n- [ ] Android\n- [ ] iOS\n\n### Basic Information\n\n- AiForms.SettingsView x.x.x\n- Xamarin.Forms x.x.x\n- Android Support Library Version: <!-- if applicable -->\n- Affected Devices:\n\n### Screenshots\n\n<!-- If the issue is a visual issue, please include screenshots showing the problem if possible -->\n\n### Reproduction Link\n\n<!-- Please upload or provide a link to a reproduction case -->\n\n### Workaround\n\n<!-- Did you find any workaround for this issue? This can unblock other people while waiting for this issue to be resolved -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"[Enhancement] YOUR IDEA!\"\n---\n\n## Summary\nPlease provide a brief summary of your proposal. Two to three sentences is best here.\n\n## API Changes\n\nInclude a list of all API changes, additions, subtractions as would be required by your proposal. These APIs should be considered placeholders, so the naming is not as important as getting the concepts correct. If possible you should include some \"example\" code of usage of your new API.\n\ne.g.\n\nIn order to facilitate the new Shiny Button api, a bool is added to the Button class. This is done as a bool because it is simpler to data bind and other reasons...\n\n    var button = new Button ();\n    button.MakeShiny = true; // new API\n\nThe MakeShiny API works even if the button is already visible.\n\n## Intended Use Case\nProvide a detailed example of where your proposal would be used and for what purpose.\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n.vs/\n.vscode/\nmono_crash.*\n.idea/\n\n# User-specific files\n*.suo\n*.user\n*.sln.docstates\n*.userprefs\n\n# ignore Xamarin.Android Resource.Designer.cs files\n**/*.Droid/**/[Rr]esource.[Dd]esigner.cs\n**/*.Android/**/[Rr]esource.[Dd]esigner.cs\n**/Android/**/[Rr]esource.[Dd]esigner.cs\n\n# Xamarin Components\nComponents/\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\nx64/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n#NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding addin-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n*.ncrunch*\n_NCrunch_*\n.*crunch*.local.xml\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n\n# NuGet Packages Directory\npackages/\n## TODO: If the tool you use requires repositories.config uncomment the next line\n#!packages/repositories.config\n\n# Enable \"build/\" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets\n# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)\n!packages/build/\n\n# Windows Azure Build Output\ncsx/\n*.build.csdef\n\n# Windows Store app package directory\nAppPackages/\n\n# Others\nsql/\n*.Cache\nClientBin/\n[Ss]tyle[Cc]op.*\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\n.DS_Store\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file to a newer\n# Visual Studio version. Backup files are not needed, because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\nproject.lock.json\n"
  },
  {
    "path": "AiForms.Maui.SettingsView.slnx",
    "content": "<Solution>\n  <Folder Name=\"/Solution Items/\" />\n  <Project Path=\"Sample/Sample.csproj\" />\n  <Project Path=\"SettingsView/SettingsView.csproj\" />\n</Solution>\n"
  },
  {
    "path": "CONTRIBUTING-ja.md",
    "content": "# How to contribute\n\n[English contribution guideline is here！](CONTRIBUTING.md)\n\n我々は皆さんの AiForms.SettingsView へ貢献を歓迎します。\n我々は、皆さんによる貢献を出来るだけ簡単にできるようにしたいと考えています。\nその為に、貢献しようとする人は以下の方針に従うよう、お願いします。\n\n## Getting Started\n\n* AiForms.SettingsView に貢献する為には [GitHub アカウント](https://github.com/signup/free) が必要です。\n* 問題や機能要望には Issue を作ってください（まだ Issue が作られていない場合）。\n  * Issue や Pull request を送るのに、事前の連絡は必要ありません。\n  * バグを issue で報告する場合、バグを再現する為の説明、エラーの情報、環境を書いてください。\n  * Issue のタイトルと本文はできるだけ英語で書いてください（不可能な場合は日本語でも OK です）。\n  * [Issue テンプレート](https://github.com/muak/AiForms.SettingsView/issues/new/choose) が用意されているので、必要な箇所を切り取って使用してください。\n* GitHub でリポジトリの fork を作ってください。\n* ローカルにクローンしたあと、 ``git config user.name yourname`` と ``git config user.email your@ema.il`` を設定してください。特に、``user.email`` は必ず GitHub のアカウントで使用している e-mail アドレスを設定してください。\n\n## Making Changes\n\n* コードやドキュメントを AiForms.SettingsView に貢献するにはベースとなるブランチから、トピック・ブランチを作ってください。\n  * 通常、これ(ベースとなるブランチ)は development ブランチです。\n  * development ブランチから、トピック・ブランチを作るには： `git branch\n    issue_999 development` してから `git\n    checkout issue_999`で新しいブランチに切り替えます。development ブランチ上で作業するのを避けてください。\n* commit は合理的(ロジック単位)に分けてください。また目的と関係のないコードの変更は含めないでください(コードフォーマットの変更、不要コードの削除など)。\n* commit メッセージが正しいフォーマットにあることを確認してください。commit メッセージはできるだけ英語でお願いします。\n\n````\n必須なコミット情報はここに（できるだけ英語で）。\n\n上にある最初の列はパッチ/コミットの概要を説明します。\nこの本文はパッチが無い状態のプログラムの行動、なんでこの行動は問題なのか、どうやってパッチが問題を解決するのかを説明します。\n````\n\n* 変更の為にテストが必要ならそのテストが追加されているよう確認してください。\n\n## Coding Style\n\n我々は [.NET Foundation](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md) のコーディングスタイルを使用します。ただし、1点違いがあります。\n\n> We use Allman style braces, where each brace begins on a new line. ~~A single line statement block can go without braces~~\n\n我々は、**常に** 中括弧を使用します、1行の ``if/for/while/etc`` でも ``{ }`` を省略しないでください。\n\n**例:**\n\n```csharp\n// 👎🏽 DO NOT USE\nif (source == null) \n    throw new ArgumentNullException(\"source\");\n\n// 👍🏽 GOOD\nif (source == null)\n{\n    throw new ArgumentNullException(\"source\");\n}\n```\n\nコード中には、コメントも含めて日本語は使わないでください。\n\n## Submitting Changes\n\n* 自分の fork で、変更をトピック・ブランチに push してください。\n* AiForms.SettingsView のリポジトリに pull request を投稿してください。\n\npull request は、以下のように作成してください。\n\n* タイトルは変更の要約を分かりやすく書いてください。\n* 本文には、関連する issue の番号を本文に含めてください。( ref #199 など)\n* 本文には、その変更が確認できるコードの場所を明記してください。通常これは [サンプルプログラム](https://github.com/muak/AiForms.SettingsView/tree/development/Sample) に追加することを推奨します。\n* 機能の追加・修正の場合は[ReadMe-ja.md](https://github.com/muak/AiForms.SettingsView/blob/development/README-ja.md)の対応する箇所に加筆・修正してください。\n* まだ作業中である場合、タイトルの先頭に [WIP] を付けてください。マージ可能になったら、[WIP] を除去し、コメントでお知らせください。\n  * 作業中に development ブランチが変更された場合は、コンフリクトを解消してから [WIP] を除去してください。\n  * その作業を予約する意味で、まず [WIP] の付いた pull request を投稿することを許可します。ただし、長い間活動が見られない場合は、クローズされる場合があります。\n\n# Thanks\n\nこのドキュメントは、[MMP/CONTRIBUTING.md · sn0w75/MMP](https://github.com/sn0w75/MMP/blob/master/CONTRIBUTING.md) と [CONTRIBUTING.md · amay077/\nXamarin.Forms.GoogleMaps](https://github.com/amay077/Xamarin.Forms.GoogleMaps/blob/master/CONTRIBUTING.md) をベースに作成しました。\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to contribute\n\n[日本語のコントリビューションガイドはこちら！](CONTRIBUTING-ja.md)\n\nThird-party contributions are essential for the future development of AiForms.SettingsView.\nWe would like to keep it as easy as possible to contribute changes that get things working\non your environment. There are some guidelines that we need contributors to follow\nso that we can keep on top of things.\n\n## Getting Started\n\n* Make sure you have a [GitHub account](https://github.com/signup/free).\n* Create an Issue for your problem, assuming one does not already exist.\n  * Clearly describe the issue including steps to reproduce, stacktrace and environments when it is a bug.\n  * We have an [issue template](https://github.com/muak/AiForms.SettingsView/issues/new/choose), you can use some part of it.\n* Fork the repository on GitHub.\n* After cloning your repogitory to local, you should set ``git config user.name`` and `` git config user.email your@ema.il`` . Especially you **MUST** set ``user.email`` as same as your GitHub account's e-mail.\n\n## Making Changes\n\n* Create a topic branch from where you want to base your work.\n  * It would be usually from the development branch.\n  * To quickly create a topic branch based on development; `git branch\n    issue_999 development` then checkout the new branch with `git\n    checkout issue_999`. Please avoid working directly on the\n    `development` branch.\n* Make commits of logical units. **Do not contain unrelated file changes(e.g. code formatting).**\n* Check for unnecessary whitespace with `git diff --check` before committing.\n* Make sure your commit messages are in the proper format.\n\n````\nEssential commit summary here.\n\nThe body paragraph describes the behavior without the patch,\nwhy this is a problem, and how the patch fixes the problem when applied.\n````\n\n* Make sure you have added the necessary tests for your changes.\n* Run _all_ the tests to assure nothing else was accidentally broken.\n\n### Coding Style\n\nWe follow the style used by the [.NET Foundation](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md), with one primary exception:\n\n> We use Allman style braces, where each brace begins on a new line. ~~A single line statement block can go without braces~~\n\nWe **always** need braces, you can not go without braces.\n\n**Examples:**\n\n```csharp\n// 👎🏽 DO NOT WRITE\nif (source == null) \n    throw new ArgumentNullException(\"source\");\n\n// 👍🏽 GOOD\nif (source == null)\n{\n    throw new ArgumentNullException(\"source\");\n}\n```\n\n## Submitting Changes\n\n* Push your changes to a topic branch in your fork of the repository.\n* Submit a pull request to the AiForms.SettingsView repository.\n\nMake pull request guide line\n\n* Write a summary of the changes in easy-to-understand manner for the title.\n* Show some usage or test code for your changes. We storongly recommend to add usage of new feature to the [sample apps](https://github.com/muak/AiForms.SettingsView/tree/development/Sample).\n* Reflect the changes on [ReadMe.md](https://github.com/muak/AiForms.SettingsView/blob/development/README.md).\n* Include related issue number for the contents. (e.g. ref #199)\n* If your changes are work in progress, the title should start with [WIP]. If you worked out, delete the [WIP] and please let us know.\n  * If we changed the development before you completed the work, you should resolve conflicts.\n  * We accept your [WIP] pull request first, which means issue reservation. But if you became no longer active, we will close it.\n\n# Thanks\n\nThis guide is based on [MMP/CONTRIBUTING.en.md · sn0w75/MMP](https://github.com/sn0w75/MMP/blob/master/CONTRIBUTING.en.md) and [CONTRIBUTING.md · amay077/\nXamarin.Forms.GoogleMaps](https://github.com/amay077/Xamarin.Forms.GoogleMaps/blob/master/CONTRIBUTING.md).\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "MIT License\n\nCopyright (c) 2022 kamu\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README-ja.md",
    "content": "# AiForms.SettingsView for .NET MAUI\n\nSettingViewは.NET MAUIで使用できる設定に特化した柔軟なTableViewです。  \nAndroidとiOSに対応しています。\n\n**現在プレビュー版です。動作は安定しませんので調査・検証用としてお使いください。**\n\n![Build status](https://dev.azure.com/kamusoft/NugetCI/_apis/build/status/AiForms.Maui.SettingsView)\n\n## SettingsViewでできること（標準のTableViewとの違い）\n\n### 全般\n\n* Separatorの色の設定\n* 選択された時の色の指定\n* リストの先頭・最後へのスクロール\n\n### セクション\n\n* セクションごとの表示・非表示の設定\n* セクションのフッターの設定\n* ヘッダーとフッターの様々な設定\n* ヘッダーとフッターにFormsのViewを設定\n* セクション内にDataTemplateおよびDataTemplateSelectorを適用\n* セクション内でドラッグドラッグによる並べ替え\n\n### Cells\n\n* すべてのセルの外観などをSettingsViewで一括で指定\n* 個別のセルの設定（個別の設定は全体の設定より優先されます）\n* Cell右上にヒントテキストの設定\n* 全てのセルでのアイコン設定、それらすべてにメモリキャッシュを適用\n* アイコンの角丸設定\n* 様々な定義済みCellの使用\n* Xamarin.FormsのViewCell、それ以外の定義済みCellの使用\n\n\n<img src=\"https://github.com/muak/AiForms.SettingsView/blob/f82cc9ef2a6db043a1278c6f8349e1bde805a6d1/images/iOS_SS.png\" height=\"1200\" /> <img src=\"https://github.com/muak/AiForms.SettingsView/blob/f82cc9ef2a6db043a1278c6f8349e1bde805a6d1/images/AndroidSS.png\" height=\"1200\" />\n\n### デモ動画\n\n[https://youtu.be/FTMOqNILxBE](https://youtu.be/FTMOqNILxBE)\n\n## 最小デバイス・バージョン等\n\niOS13  \nAndroid8.0\n\n## インストール\n\n[https://www.nuget.org/packages/AiForms.Maui.SettingsView/](https://www.nuget.org/packages/AiForms.Maui.SettingsView/)\n\n```bash\nInstall-Package AiForms.Maui.SettingsView\n```\n\n\n```cs\npublic static MauiApp CreateMauiApp()\n{\n    var builder = MauiApp.CreateBuilder();\n    builder\n        .UseMauiApp<App>()                    \n        .ConfigureMauiHandlers(handlers =>\n        {\n            handlers.AddSettingsViewHandler(); // write this\n        });\n    ...\n}\n```\n\n\n## Xamlでの使用方法\n\n```xml\n<ContentPage \n\txmlns=\"http://xamarin.com/schemas/2014/forms\" \n\txmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\" \n\txmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n\tx:Class=\"Sample.Views.SettingsViewPage\">\n    \n<sv:SettingsView HasUnevenRows=\"true\">\n    \n    <sv:Section Title=\"Header1\" FooterText=\"Footer1\">\n        <sv:CommandCell IconSource=\"icon.png\" IconSize=\"60,60\" IconRadius=\"30\"\n            Title=\"Xam Xamarin\" Description=\"hoge@fuga.com\"\n            Command=\"{Binding ToProfileCommand}\" CommandParameter=\"{Binding Parameter}\"\n            KeepSelectedUntilBack=\"true\"            \n        />\n        <sv:ButtonCell Title=\"Toggle Section\" TitleColor=\"{StaticResource TitleTextColor}\"\n             TitleAlignment=\"Center\" Command=\"{Binding SectionToggleCommand}\" />\n        <sv:LabelCell Title=\"Label\" ValueText=\"value\" />\n        <sv:SwitchCell Title=\"Switch\" On=\"true\" \n            Description=\"This is description.\" />\n        <sv:CheckboxCell Title=\"Checkbox\" Checked=\"true\" />\n    </sv:Section>\n\n    <sv:Section Title=\"Header2\" FooterText=\"Footer2\" IsVisible=\"{Binding SctionIsVisible}\">\n        <sv:PickerCell Title=\"Favorites\" ItemsSource=\"{Binding ItemsSource}\" DisplayMember=\"Name\" MaxSelectedNumber=\"3\" \n        SelectedItems=\"{Binding SelectedItems}\" KeepSelectedUntilBack=\"true\" PageTitle=\"select 3 items\" />\n        <sv:NumberPickerCell Title=\"NumberPicker\" Min=\"0\" Max=\"99\" Number=\"15\" PickerTitle=\"Select number\" />\n        <sv:TimePickerCell Title=\"TimePicker\" Format=\"HH:mm\" Time=\"15:30\" PickerTitle=\"Select time\" />\n        <sv:DatePickerCell Title=\"DatePicker\" Format=\"yyyy/MM/dd (ddd)\" Date=\"2017/11/11\" MinimumDate=\"2015/1/1\" MaximumDate=\"2018/12/15\" TodayText=\"Today's date\"/>\n        <sv:EntryCell Title=\"EntryCell\" ValueText=\"{Binding InputText.Value}\" Placeholder=\"Input text\" Keyboard=\"Email\" TextAlignment=\"End\" HintText=\"{Binding InputError.Value}\" />\n    </sv:Section>\n    \n</sv:SettingsView>\n</ContentPage>\n```\nSettingsViewのプロパティ設定はApp.xamlに記述した方が良いかもしれません。\n\n\n```xml\n<Application xmlns=\"http://xamarin.com/schemas/2014/forms\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n             xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n             x:Class=\"Sample.App\">\n    <Application.Resources>\n        <ResourceDictionary>\n            <Color x:Key=\"AccentColor\">#FFBF00</Color>\n            <Color x:Key=\"DisabledColor\">#E6DAB9</Color>\n            <Color x:Key=\"TitleTextColor\">#CC9900</Color>\n            <Color x:Key=\"PaleBackColorPrimary\">#F2EFE6</Color>\n            <Color x:Key=\"PaleBackColorSecondary\">#F2EDDA</Color>\n            <Color x:Key=\"DeepTextColor\">#555555</Color>\n            <Color x:Key=\"NormalTextColor\">#666666</Color>\n            <Color x:Key=\"PaleTextColor\">#999999</Color>\n            <x:Double x:Key=\"BaseFontSize\">12</x:Double>\n            <x:Double x:Key=\"BaseFontSize+\">14</x:Double>\n            <x:Double x:Key=\"BaseFontSize++\">17</x:Double>\n            <x:Double x:Key=\"BaseFontSize-\">11</x:Double>\n\n            <Style TargetType=\"sv:SettingsView\">\n                <Setter Property=\"SeparatorColor\" Value=\"{StaticResource DisabledColor}\" />\n                <Setter Property=\"BackgroundColor\" Value=\"{StaticResource PaleBackColorPrimary}\" />\n                <Setter Property=\"HeaderBackgroundColor\" Value=\"{StaticResource PaleBackColorPrimary}\" />\n                <Setter Property=\"CellBackgroundColor\" Value=\"{StaticResource AppBackground}\" />\n                <Setter Property=\"CellTitleColor\" Value=\"{StaticResource DeepTextColor}\" />\n                <Setter Property=\"CellValueTextColor\" Value=\"{StaticResource NormalTextColor}\" />\n                <Setter Property=\"CellTitleFontSize\" Value=\"{StaticResource BaseFontSize++}\" />\n                <Setter Property=\"CellValueTextFontSize\" Value=\"{StaticResource BaseFontSize}\" />\n                <Setter Property=\"CellDescriptionColor\" Value=\"{StaticResource NormalTextColor}\" />\n                <Setter Property=\"CellDescriptionFontSize\" Value=\"{StaticResource BaseFontSize-}\" />\n                <Setter Property=\"CellAccentColor\" Value=\"{StaticResource AccentColor}\" />\n                <Setter Property=\"SelectedColor\" Value=\"#50FFBF00\" />\n                <Setter Property=\"HeaderTextColor\" Value=\"{StaticResource TitleTextColor}\" />\n                <Setter Property=\"FooterFontSize\" Value=\"{StaticResource BaseFontSize-}\" />\n                <Setter Property=\"FooterTextColor\" Value=\"{StaticResource PaleTextColor}\" />\n            </Style>\n        </ResourceDictionary>\n    </Application.Resources>\n</Application>\n\n```\n\nこんな感じに書くことでアプリ内の全てのSettingsViewを同じ設定にすることができます。\n\n## SettingsViewのプロパティ\n\n* BackgroundColor\n\t* View全体と領域外の背景色。ヘッダーやフッターの背景色も含みます。（Androidの場合はCellの背景色も）\n* SeparatorColor\n    * セパレータの線の色\n* SelectedColor\n    * 行（セル）を選択した時の背景色（AndroidはRipple色も含む）\n    > AndroidのRipple効果はセルの背景色が設定されていない(透明の)場合は発動しません。\n* HeaderPadding\n* HeaderTextColor\n* HeaderFontSize\n* HeaderFontFamily\n* HeaderFontAttributes\n* HeaderTextVerticalAlign\n  > HeaderHeightを設定した場合のみ有効です。\n* HeaderBackgroundColor\n* HeaderHeight\n    * ヘッダーに関する設定\n* FooterTextColor\n* FooterFontSize\n* FooterFontFamily\n* FooterFontAttributes\n* FooterBackgroundColor\n* FooterPadding\n    * フッターに関する設定\n* RowHeight\n\t* HasUnevenRowがfalseの時は、全行の高さ\n\t* それ以外は最小の行の高さ\n* HasUnevenRows\n\t* 行の高さを固定にするかどうか。デフォルトはfalse。true推奨。\n* CellTitleColor\n* CellTitleFontSize\n* CellTitleFontFamily\n* CellTitleFontAttributes\n* CellValueTextColor\n* CellValueTextFontSize\n* CellValueTextFontFamily\n* CellValueTextFontAttributes\n* CellDescriptionColor\n* CellDescriptionFontSize\n* CellDescriptionFontFamily\n* CellDescriptionFontAttributes\n* CellBackgroundColor\n* CellIconSize\n* CellIconRadius\n* CellAccentColor\n* CellHintTextColor\n* CellHintFontSize\n* CellHintFontFamily\n* CellHintFontAttributes\n    * 一括セル設定。どこがどのパーツかは後述のLayoutを参照。\n* UseDescriptionAsValue (Androidのみ有効)\n\t* Description項目をValue項目として使用するかどうか。\n\t* （一般的なAndroidアプリにありがちな設定値を下に書くレイアウトにするかどうか）\n\t* デフォルトはfalse（DescriptionとValueは個別に使う）\n* ShowSectionTopBottomBorder (Androidのみ有効)\n\t* 行の境界線をセクションの上と下にも表示するかどうか\n\t* （一般的なAndroidアプリでありがちな上と下は表示しないようにしないかどうか）\n\t* デフォルトはtrue（表示する）\n* ShowArrowIndicatorForAndroid\n  * CommandCell や PickerCell で 右端の矢印アイコンを Android でも表示するかどうか\n  * デフォルトは false (表示しない)\n* ScrollToTop\n* ScrollToBottom\n\t* このプロパティにtrueをセットすると先頭または末尾までスクロールします。\n\t* スクロール完了後は自動でfalseがセットされます。\n* VisibleContentHeight\n    * 表示されているコンテンツの高さです。この値を使って SettingsView 自体の高さを表示されているセルの合計の高さに合わせることができます。\n* ItemsSource\n* ItemTemplate\n    * SettingsView全体のDataTemplateを使用できます。SectionのDataTemplateと組み合わせることで単純な構造のセルを短いコードで実現できます。\n* TemplateStartIndex\n  * Templateの挿入を開始するインデックスを指定。デフォルトは0で最初からTemplateを適用します。1以上の値を指定すると、その位置からTemplateが挿入されるようになり、XAML等で挿入したデータはそのままの状態で残ります。任意の位置から繰り返しのセクションを設置した場合などに利用できます。\n\n### SettingsView の高さを内容の高さに合わせるには\n\nSettingsView の内容のセルの合計の高さが、親のViewよりも低い場合は、次のように HeightRequest と VisibleContentHeight を使って、自身の高さを内容の高さに合わせることができます。\n\n```xml\n<sv:SettingsView x:Name=\"settings\" HeightRequest=\"{Binding VisibleContentHeight,Source={x:Reference settings}}\">\n</sv:SettingsView>\n```\n\n### SetttingsView自身のItemsSourceとItemTemplateの使用例\n\n```csharp\npublic class SomeViewModel\n{\n    public List<MenuSection> ItemsSource {get;set;}\n\n    public SomeViewModel()\n    {\n        ItemsSource = new List<MenuSection>{\n            new new MenuSection(\"Select number\",3){\n                new MenuItem{Title = \"3\",Value=3},\n                new MenuItem{Title = \"4\",Value=4},\n            },\n            new MenuSection(\"Select mode\",1){\n                new MenuItem{Title = \"A\",Value = 1},\n                new MenuItem{Title = \"B\",Value = 2}\n            }\n        }\n    }\n}\npublic class MenuItem\n{\n    public string Title { get; set; }\n    public int Value { get; set; }\n}\n\npublic class MenuSection:List<MenuItem>\n{\n    public string SectionTitle { get; set; }\n    public bool Selected { get;set; } // must implement INotifyPropertyChanged by some way\n\n    public MenuSection(string title,int initalSelectedValue)\n    {\n        SectionTitle = title;\n    }\n}\n```\n\n```xml\n<sv:SettingsView x:Name=\"Settings\" ItemsSource=\"{Binding ItemsSource}\">\n    <sv:SettingsView.ItemTemplate>\n        <DataTemplate>\n            <sv:Section Title=\"{Binding SectionTitle}\" ItemsSource=\"{Binding}\" sv:RadioCell.SelectedValue=\"{Binding Selected}\">\n                <sv:Section.ItemTemplate>\n                    <DataTemplate>\n                        <sv:RadioCell Title=\"{Binding Title}\" Value=\"{Binding Value}\" />\n                    </DataTemplate>\n                </sv:Section.ItemTemplate>\n            </sv:Section>\n        </DataTemplate>\n    </sv:SettingsView.ItemTemplate>\n</sv:SettingsView>\n```\n\n## SettingsViewのメソッド\n\n* ClearCache (static)\n\t* 全ての画像メモリキャッシュをクリアする\n\n## Section プロパティ\n\n* Title\n\t* セクションのヘッダー文字列。Xamarin.FormsのTableSectionと同じです。\n* FooterText\n\t* セクションのフッター文字列。\n* IsVisible\n\t* セクションを表示するかどうか。\n* HeaderHeight\n\t* セクションのヘッダーの個別の高さを指定します。\n\t* SettingsViewのHeaderHeightよりも優先されます。\n* ItemsSource\n\t* DataTemplateのソースを指定します。\n* ItemTemplate\n\t* DataTemplateを指定します。\n* TemplateStartIndex\n  * Templateの挿入を開始するインデックスを指定。デフォルトは0で最初からTemplateを適用します。1以上の値を指定すると、その位置からTemplateが挿入されるようになり、XAML等で挿入したデータはそのままの状態で残ります。任意の位置から繰り返しの Cell を設置した場合などに利用できます。\n* UseDragSort\n\t* セクション内のセルをDragDropで並べ替え可能にします。\n\t* UseDragSortがtrueのセクション間でのみ移動が可能です。\n\t* iOS11以降とそれ以外で外観が異なります。\n\t* iOS10以下は三本線のアイコンを掴むと移動でき、iOS11はセル全体を長押しすると移動できるようになります。\n* HeaderView\n* FooterView\n  * Header または Footer に Forms の View を指定します。\n  > こちらを設定すると Title や FooterText も文字列は無効になります。\n  > HeaderView と FooterView を使用するとセルの高さは自動になります。\n* FooterVisible\n  * FooterViewの表示・非表示を指定します。default true。\n\n### Section HeaderView FooterView XAMLからの使用例\n\n```xml\n<sv:Section>\n    <sv:Section.HeaderView>\n        <StackLayout>\n            <Label Text=\"Header\" />\n        </StackLayout>\n    </sv:Section.HeaderView>\n    <sv:Section.FooterView>\n        <Label Text=\"{Binding FooterText}\" />\n    </sv:Section.FooterView>\n</sv:Section>\n```\n\n### SectionのItemsSourceとItemTemplateの使用例\n\n```csharp\npublic class SomeModel\n{\n   // 動的なリストを使う場合はObservableCollectionを使った方が良いです。\n   public ObservableCollection<Option> Options {get;set;}\n   public void SomeMethod()\n   {\n       Options = new ObservableCollection(GetServerData());\n   }\n}\npublic class Option\n{\n   public string Name {get;set;}\n   public string Address {get;set;}\n}\n```\n\n```xml\n<sv:Section ItemsSource=\"{Binding Options}\">\n    <sv:Section.ItemTemplate>\n        <DataTemplate>\n            <sv:LabelCell Title=\"{Binding Name}\" Value=\"{Binding Address}\" />\n        </DataTemplate>\n    </sv:Section.ItemTemplate>\n</sv:Section>\n```\n\n## Cells\n\n* [CellBase](#cellbase)\n* [LabelCell](#labelcell)\n* [CommandCell](#commandcell)\n* [ButtonCell](#buttoncell)\n* [SwitchCell](#switchcell)\n* [CheckboxCell](#checkboxcell)\n* [RadioCell](#radiocell)\n* [NumberPickerCell](#numberpickercell)\n* [TimePickerCell](#timepickercell)\n* [DatePickerCell](#datepickercell)\n* [TextPickerCell](#textpickercell)\n* [PickerCell](#pickercell)\n* [EntryCell](#entrycell)\n* [CustomCell](#customcell)\n\n## CellBase\n\n### 基本セルのレイアウト\n\n![cell layout](./images/cell_layout.png)\n\n* Icon\n    * アイコンを使わない場合はこの領域は非表示になります。\n* Description\n    * Descriptionを使わない場合はこの領域は非表示になります。\n* Accessory\n    * CheckboxCellやSwitchCellで使用されます。それ以外は非表示です。\n\n### プロパティ (全セル共通)\n\n* Title\n    * Title部分の文字列\n* TitleColor\n    * Title部分の文字色\n* TitleFontSize\n* TitleFontFamily\n* TitleFontAttributes\n    * Title部分のフォント設定\n* Description\n    * Description部分の文字列\n* DescriptionColor\n    * Description部分の文字色\n* DescriptionFontSize\n* DescriptionFontFamily\n* DescriptionFontAttributes\n    * Description部分のフォント設定\n* HintText\n    * Hint部分の文字列（何らかの情報やバリデーションのエラーなど、右上に表示）\n* HintTextColor\n    * Hint部分の文字色\n* HintFontSize\n* HintFontFamily\n* HintFontAttributes\n    * Hint部分のフォント設定\n* BackgroundColor\n    * セルの背景色\n* IconSource\n    * アイコンのImageSource\n* IconSize\n    * アイコンサイズ（幅,高さ指定）\n* IconRadius\n    * アイコンの角丸半径。\n* IsEnabled\n  * セルを有効にするかどうか。無効にした場合はセル全体の色が薄くなり操作を受け付けなくなります。\n* IsVisible\n  * セルの表示・非表示\n\n### メソッド\n\n* Reload\n  * セルを強制的にリロードします。CustomCell等で動的に内容を変更した後などに使用します。\n\n### SVGイメージを使用するには\n\nSvgImageSourceのnugetパッケージをインストールすればSVG画像を使用できるようになります。\n\nhttps://github.com/muak/SvgImageSource  \nhttps://www.nuget.org/packages/Xamarin.Forms.Svg/\n\n```bash\nInstall-Package Xamain.Forms.Svg -pre\n```\n\n## LabelCell\n\nテキスト表示専用のセルです。\n\n### Properties\n\n* ValueText\n    * 何らかの値を示す文字列（何に使っても問題ありません）\n* ValueTextColor\n    * ValueText部分の文字色\n* ValueTextFontSize\n* ValueTextFontFamily\n* ValueTextFontAttributes\n    * ValueText部分のフォント設定\n* IgnoreUseDescriptionAsValue\n\t* UseDescriptionAsValueの値がtrueだった場合、その設定を無視するかどうか。\n\t* 例えば全体としてはValueは下に置きたいが、あるセルだけは通常のレイアウトで使用したい時などに使います。\n\n## CommandCell\n\nタップした時のコマンドを指定できるLabelCellです。\n例えばページ遷移の時などに使用します。\n\n### Properties\n\n* Command\n* CommandParameter\n* KeepSelectedUntilBack\n\t* タップして次のページに遷移した時、遷移先ページから戻ってくるまで選択状態をそのままにしておくかの設定\n\t* trueの場合は選択状態をキープして、falseの場合は選択はすぐに解除されます。\n* HideArrowIndicator\n  * 右端の矢印アイコンを非表示にします。\n  * 親のShowArrowIndicatorForAndroidがtrueの場合でもこちらのプロパティが優先されます。\n\n他はLabelCellと同じです。\n\n## ButtonCell\n\nボタンのようにタップするとコマンドを実行するだけのシンプルなセルです。\nCommandCellとの違いは以下のとおりです。\n* 右端にインジケーターが表示されない(iOS)\n* ValueやDescriptioが使用不可\n* ButtonCellは文字の水平位置を指定可能\n\n### Properties\n\n* TitleAlignment\n    * ボタンタイトルの水平位置属性\n* Command\n* CommandParameter\n\n\n## SwitchCell\n\nSwitchを備えたLabelCellです。\n\n### Properties\n\n* On\n    * Switchのオンオフ。OnがtrueでOffがfalse。 \n* AccentColor\n    * Switchのアクセントカラー。背景色やつまみ部分の色などプラットフォームによって異なる。\n\n## CheckboxCell\n\nCheckboxを備えたLabelCellです。\n\n### Properties\n\n* Checked\n    * Checkのオンオフ。OnがtrueでOffがfalse。\n* AccentColor\n    * Checkboxのアクセントカラー。（枠や背景色） \n\n## RadioCell\n\nセクション単位またはSettingsView全体で1つのアイテムを選択するCellです。PickerCellと違い選択項目を1階層目に配置する場合などに使用します。\n\n### Properties\n\n* Value\n    * セルに対応する選択候補値。\n* AccentColor\n    * チェックマークの色。\n\n### 添付プロパティ\n\n* SelectedValue\n    * 現在の選択値。\n    * このプロパティをSectionに設定した場合は、そのSectionから1つだけ選択できるようになり、SettingsView自体に設定した場合は、View全体から1つだけ選択できるようになります。\n    > SectionとSettingsViewの両方に設定して動作させることはできません。両方に設定した場合はSection側が使用されます。\n\n### XAML サンプル\n\n#### セクション単位\n\n```xml\n<sv:SettingsView>\n    <sv:Section Title=\"Sound\" sv:RadioCell.SelectedValue=\"{Binding SelectedItem}\">\n        <sv:RadioCell Title=\"Sound1\" Value=\"{Binding Items[0]}\">\n        <sv:RadioCell Title=\"Sound2\" Value=\"{Binding Items[1]}\">\n    </sv:Section>\n</sv:SettingsView>\n```\n\n#### コントロール全体\n\n```xml\n<sv:SettingsView sv:RadioCell.SelectedValue=\"{Binding GlobalSelectedItem}\">\n    <sv:Section Title=\"Effect\">\n        <sv:RadioCell Title=\"Sound1\" Value=\"{Binding Items[0]}\">\n        <sv:RadioCell Title=\"Sound2\" Value=\"{Binding Items[1]}\">\n    </sv:Section>\n    <sv:Section Title=\"Melody\">\n        <sv:RadioCell Title=\"Melody1\" Value=\"{Binding Items[2]}\">\n        <sv:RadioCell Title=\"Melody2\" Value=\"{Binding Items[3]}\">\n    </sv:Section>\n</sv:SettingsView>\n```\n\n## NumberPickerCell\n\nセルタップ時にNumberPickerを呼び出すことができるLabelCellです。\n\n### Properties\n\n* Number\n    * 現在の数値（default two way binding)\n* Min\n    * 最小値\n* Max\n    * 最大値\n* PickerTitle\n    * Pikerのタイトル文字列\n* SelectedCommand\n    * 数値を選択した時に発火させるCommand。\n* Unit\n  * 数値の単位文字列。\n\nValueTextは使用できません。\n\n## TimePickerCell\n\nセルタップ時にTimePickerを呼び出すことができるLabelCellです。\n\n### Properties\n\n* Time\n    * 現在選択中の時刻 (default two way binding)\n* Format\n    * 時刻の書式 (\"hh時mm分\"など)\n* PickerTitle\n    * Pikerのタイトル文字列\n\nValueTextは使用できません。\n\n## DatePickerCell\n\nセルタップ時にDatePickerを呼び出すことができるLabelCellです。\n\n### Properties\n\n* Date\n    * 現在選択中の日付 (default two way binding)\n* MinimumDate\n* MaximumDate\n* Format\n    * 日付の書式 (\"yyyy年MM月dd日 ddd曜日\"など)\n* TodayText\n\t* 今日の日付を選択するためのボタンのタイトル文字列（iOSのみ）\n    * 空の場合はボタン自体が非表示になります。\n* InitialDate\n  * Dateがnullだった場合に、ピッカーの初期値として設定される日付\n* IsAndroidSpinnerStyle\n  * AndroidでカレンダーではなくスピナーUIを使用する場合にTrue\n* AndroidButtonColor\n  * Androidのダイアログのボタン文字色\n\nValueTextは使用できません。\n\n## TextPickerCell\n\nセルタップ時にテキストを選択できるピッカーを呼び出すことができるLabelCellです。\nNumberPickerCellをNumber以外に対応させたもので、データソースにListを設定できます。\n\n### Properties\n\n* Items\n\t* IListを実装したデータソース。\n\t* このプロパティには組み込みの型のList\\<T>等が設定できます。（List\\<string>, List\\<int>,List\\<double> など）\n\t* ピッカーの表示テキストにはToString()の結果が使用されます。\n* SelectedItem\n\t* 選択したアイテム。 (two-way binding)\n* SelectedCommand\n    * アイテム選択時に発火するコマンド。\n* IsCircularPicker\n    * ピッカーのアイテムを循環させるかどうか。(Android のみ)\n    * デフォルト true\n\nValueTextは使用できません。\n\n## PickerCell\n\nセルタップ時に複数選択可能なピッカーを呼び出すことができるLabelCellです。\niOSではタップ時にページ遷移し遷移先ページでピッカーが表示されます。\nAndroidではタップ時にダイアログでピッカーが表示されます。\n\n### Properties\n\n* PageTitle\n    * ピッカーのタイトル文字列\n* ItemsSource\n    * IEnumerableを実装したPickerのDataSource（List<T>やObservableCollection<T>など）\n    * nullを指定することはできません。\n* DisplayMember\n    * Pickerに選択肢として表示させるメンバー名（プロパティ名）。省略時はToStringの値が使用されます。\n* SubDisplayMember\n\t* Pickerに表示させる二番目のメンバー名（プロパティ名）。指定するとセルは2行表示となり、1行目にDisplayMemberが、2行目にSubDisplayMemberが表示されるようになります。\n* SelectionMode\n  * 複数選択か単一選択かのモードを Single / Multiple から選択。デフォルト Multiple。\n* SelectedItem\n  * 単一選択の場合の選択されたアイテム。\n* SelectedItems\n  * 複数選択の場合の選択されたアイテム。\n  * 選択したItemを保存するためのIList。ItemsSourceと同じ型のものを指定。\n  * 選択済み要素をあらかじめ設定する場合は、ItemsSourceの要素と同一インスタンスの要素にする必要があります。\n  * 指定する場合は必ずnullではなくインスタンス設定済みのものを指定する。\n* SelectedItemsOrderKey\n\t* 選択済みItemを文字列として表示する時のソートのキーとなるメンバー（プロパティ）名\n* SelectedCommand\n\t* 選択が完了した時に発火するコマンド\n\t* iOSの場合はピッカーページから戻る時、Androidの場合はダイアログのOKをタップした時に発火します。\n* MaxSelectedNumber\n    * 選択可能な最大数。\n\t* 0指定で無制限、1指定で単一選択モード（ラジオボタン的なやつ）、2以上は制限付きの複数選択となります。\n* KeepSelectedUntilBack\n\t* タップして次のページに遷移した時またはダイアログ表示時、戻ってくるまで選択状態をそのままにしておくかの設定\n\t* trueの場合は選択状態をキープして、falseの場合は選択はすぐに解除されます。\n* AccentColor\n    * Pickerのチェックマークの色\n* UseNaturalSort\n\t* 並べ替え方法にNaturalSortを使うかどうか。デフォルト false。\n\t* trueの場合、例えば通常 1,10,2,3,4 と並ぶところが 1,2,3,4,10 という並びになります。\n\t* 日本語以外の言語で使用する場合、誤動作する可能性があります。\n* UsePickToClose\n\t* 選択がMaxSelectedNumberに達したら自動的にPickerを閉じるかどうかを指定します。\n* UseAutoValueText\n\t* 通常は選択アイテムが自動でValueTextに表示されますが、このプロパティにfalseを指定すると自動表示が解除され、ValueTextを普通に使うことができるようになります。\n\n\n## EntryCell\n\n文字入力用のCellです。\nXamarin.Forms.EntryCellとは別物です。\n\n### Properties\n\n* ValueText\n    * 入力文字列 (default two way binding)\n* ValueTextColor\n    * 入力文字色\n* ValueTextFontSize\n* ValueTextFontFamily\n* ValueTextFontAttributes\n    * 入力文字列のフォント設定\n* MaxLength\n    * 最大文字列長\n* Keyboard\n    * キーボードの種類\n* Placeholder\n    * Placeholderの文字列\n* PlaceholderColor\n    * Placeholderの文字色\n* TextAlignment\n    * 入力文字列の水平位置属性\n* AccentColor\n    * 入力欄の下線の色（Androidのみ）\n* IsPassword\n    * パスワードなどのために入力文字を隠すかどうか。\n* CompletedCommand\n  * エンターによる文字入力の確定、またはフォーカス移動による確定時に発火するコマンド。\n\n### Methods\n\n* SetFocus\n  * フォーカスを設定します。\n\n## CustomCell\n\n真ん中の Title / ValueText / Description の部分を Forms View で自由に設定できるCellです。View部分はXAMLで指定することができます。\n基本的には CustomCell のサブクラスを作成し、それを利用する形で使用されることを想定しています。\n\n## Properties\n\n* ShowArrowIndicator\n  * セルの右端に矢印インジケータを表示するかどうか。\n  * true で iOS / Android に関わらず矢印を表示します。\n* IsSelectable\n  * 行を選択可能かどうか。true で Commandが発火するようになります。\n* IsMeasureOnce\n  * サイズ計算を1回だけ行うかどうか。デフォルト false。\n  * 高さが内容によって変わらないような場合にサイズ計算を省略することができます。\n* UseFullSize\n  * true で自由領域を範囲を余白なしで目一杯使うようにします。\n  > 有効にした場合、アイコンの設定は無効になります。\n* Command\n* CommandParameter\n* LongCommand\n  * 長押し時に発火するコマンド\n* KeepSelectedUntilBack\n\t* タップして次のページに遷移した時、遷移先ページから戻ってくるまで選択状態をそのままにしておくかの設定\n\t* trueの場合は選択状態をキープして、falseの場合は選択はすぐに解除されます。\n\n### CustomCellの使用例\n\n* https://github.com/muak/AiForms.SettingsView/tree/development/Sample/Sample/Views/Cells\n* https://github.com/muak/AiForms.SettingsView/blob/development/Sample/Sample/Views/CustomCellTest.xaml\n\n## Contribution\n\n私たちは、Xamarin.Forms.GoogleMaps への、あなたの貢献に大変感謝します。\n開発に参加して頂ける方は、[コントリビューション ガイドライン](CONTRIBUTING-ja.md) を読んで下さい。\n\n## Contributors\n\n* [codegrue](https://github.com/codegrue)\n* [cpraehaus](https://github.com/cpraehaus)\n* [dylanberry](https://github.com/dylanberry)\n* [RLittlesll](https://github.com/RLittlesII)\n* [ChaseFlorell](https://github.com/ChaseFlorell)\n* [OnTheFenceDevelopment](https://github.com/OnTheFenceDevelopment)\n* [SiNeumann](https://github.com/SiNeumann)\n* [akaegi](https://github.com/akaegi)\n\n\n## 謝辞\n\nNaturalSortの実装に以下のソースを利用させていただきました。\nありがとうございました。\n\n* NaturalComparer\n\t* https://qiita.com/tomochan154/items/1a3048f2cd9755233b4f\n    * https://github.com/tomochan154/toy-box/blob/master/NaturalComparer.cs\n\n## 寄付\n\n開発継続のため、寄付を募集しています。\n\n寄付をいただけるとやる気が非常にアップしますので、どうかよろしくお願いいたします🙇\n\n* [PayPalMe](https://paypal.me/kamusoftJP?locale.x=ja_JP)\n\n## スポンサー\n\nスポンサーも募集しています。\nこちらはサブスクリプション制になります。\n\n* [GitHub Sponsors](https://github.com/sponsors/muak)\n\n\n## License\n\nMIT Licensed.\n\nSome code is taken from [.NET MAUI](https://github.com/dotnet/maui).\n\n[Material design icons](https://github.com/google/material-design-icons) - [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)"
  },
  {
    "path": "README.md",
    "content": "# AiForms.SettingsView for .NET MAUI\n\nThis is a flexible TableView specialized in settings for Android / iOS.\n\n**This is currently a preview version. It is not stable, so please use it for research and verification purposes only.**\n\n[Japanese](./README-ja.md)\n\n![Build status](https://dev.azure.com/kamusoft/NugetCI/_apis/build/status/AiForms.Maui.SettingsView)\n\n## What SettingsView can do.\n\n### General\n\n* To set separator color.\n* To set selected cell color.\n* To scroll to screen top and bottom.\n\n### Sections\n\n* To set IsVisible each section.\n* To set section a footer.\n* To set various options of a header and  a footer.\n* To set Forms View to a section header and footer.\n* To use DataTemplate and DataTemplateSelector in a section.\n* To reorder items by drag and drop in a section.\n\n### Cells\n\n* To set options of all the cells as SettingsView options at once.\n* To set indivisual cell options. (indivisual cell options  is superior to SettingsView options.)\n* To set a cell HintText.\n* To use an icon  cached in memory at all cells.\n* To change corner radius of an icon.\n* To use various defined cells.\n* To use Xamarin.Forms.ViewCell and the others.\n\n\n<img src=\"https://github.com/muak/AiForms.SettingsView/blob/f82cc9ef2a6db043a1278c6f8349e1bde805a6d1/images/iOS_SS.png\" height=\"1200\" /> <img src=\"https://github.com/muak/AiForms.SettingsView/blob/f82cc9ef2a6db043a1278c6f8349e1bde805a6d1/images/AndroidSS.png\" height=\"1200\" />\n\n### Demo movie\n\n[https://youtu.be/FTMOqNILxBE](https://youtu.be/FTMOqNILxBE)\n\n## Minimum Device and Version etc\n\niOS:iPhone5s,iPod touch6,iOS9.3  \nAndroid:version 5.1.1 (only FormsAppcompatActivity) / API22\n\n## Installation\n\n[https://www.nuget.org/packages/AiForms.Maui.SettingsView/](https://www.nuget.org/packages/AiForms.Maui.SettingsView/)\n\n```bash\nInstall-Package AiForms.Maui.SettingsView\n```\n\n```cs\npublic static MauiApp CreateMauiApp()\n{\n    var builder = MauiApp.CreateBuilder();\n    builder\n        .UseMauiApp<App>()   \n        .UseSettingsView() // write this\n    ...\n}\n```\n\nOR\n\n```cs\npublic static MauiApp CreateMauiApp()\n{\n    var builder = MauiApp.CreateBuilder();\n    builder\n        .UseMauiApp<App>()   \n        .ConfigureMauiHandlers(handlers =>\n        {\n            handlers.AddSettingsViewHandler(); // write this\n        });\n    ...\n}\n```\n\n## Options\n\nMAUI has a fatal flaw in that the DisconnectHandler of the control is not automatically called.  \n(https://github.com/dotnet/maui/issues/18366)  \nSettingsView has an option to call DisconnectHandler on PageUnload to clean up.  \nTo enable this, do the following.\n\n```cs\n...\n.UseSettingsView(true)\n...\n```\n\n## How to write with xaml\n\n```xml\n<ContentPage \n\txmlns=\"http://xamarin.com/schemas/2014/forms\" \n\txmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\" \n\txmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n\tx:Class=\"Sample.Views.SettingsViewPage\">\n    \n<sv:SettingsView HasUnevenRows=\"true\">\n    \n    <sv:Section Title=\"Header1\" FooterText=\"Footer1\">\n        <sv:CommandCell IconSource=\"icon.png\" IconSize=\"60,60\" IconRadius=\"30\"\n            Title=\"Xam Xamarin\" Description=\"hoge@fuga.com\"\n            Command=\"{Binding ToProfileCommand}\" CommandParameter=\"{Binding Parameter}\"\n            KeepSelectedUntilBack=\"true\"            \n        />\n        <sv:ButtonCell Title=\"Toggle Section\" TitleColor=\"{StaticResource TitleTextColor}\"\n             TitleAlignment=\"Center\" Command=\"{Binding SectionToggleCommand}\" />\n        <sv:LabelCell Title=\"Label\" ValueText=\"value\" />\n        <sv:SwitchCell Title=\"Switch\" On=\"true\" \n            Description=\"This is description.\" />\n        <sv:CheckboxCell Title=\"Checkbox\" Checked=\"true\" />\n    </sv:Section>\n\n    <sv:Section Title=\"Header2\" FooterText=\"Footer2\" IsVisible=\"{Binding SctionIsVisible}\">\n        <sv:PickerCell Title=\"Favorites\" ItemsSource=\"{Binding ItemsSource}\" DisplayMember=\"Name\" MaxSelectedNumber=\"3\" \n        SelectedItems=\"{Binding SelectedItems}\" KeepSelectedUntilBack=\"true\" PageTitle=\"select 3 items\" />\n        <sv:NumberPickerCell Title=\"NumberPicker\" Min=\"0\" Max=\"99\" Number=\"15\" PickerTitle=\"Select number\" />\n        <sv:TimePickerCell Title=\"TimePicker\" Format=\"HH:mm\" Time=\"15:30\" PickerTitle=\"Select time\" />\n        <sv:DatePickerCell Title=\"DatePicker\" Format=\"yyyy/MM/dd (ddd)\" Date=\"2017/11/11\" MinimumDate=\"2015/1/1\" MaximumDate=\"2018/12/15\" TodayText=\"Today's date\"/>\n        <sv:EntryCell Title=\"EntryCell\" ValueText=\"{Binding InputText.Value}\" Placeholder=\"Input text\" Keyboard=\"Email\" TextAlignment=\"End\" HintText=\"{Binding InputError.Value}\" />\n    </sv:Section>\n    \n</sv:SettingsView>\n</ContentPage>\n```\n\nSettingsView properties settings may as well be witten in App.xaml. \nFor example...\n\n```xml\n<Application xmlns=\"http://xamarin.com/schemas/2014/forms\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n             xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n             x:Class=\"Sample.App\">\n    <Application.Resources>\n        <ResourceDictionary>\n            <Color x:Key=\"AccentColor\">#FFBF00</Color>\n            <Color x:Key=\"DisabledColor\">#E6DAB9</Color>\n            <Color x:Key=\"TitleTextColor\">#CC9900</Color>\n            <Color x:Key=\"PaleBackColorPrimary\">#F2EFE6</Color>\n            <Color x:Key=\"PaleBackColorSecondary\">#F2EDDA</Color>\n            <Color x:Key=\"DeepTextColor\">#555555</Color>\n            <Color x:Key=\"NormalTextColor\">#666666</Color>\n            <Color x:Key=\"PaleTextColor\">#999999</Color>\n            <x:Double x:Key=\"BaseFontSize\">12</x:Double>\n            <x:Double x:Key=\"BaseFontSize+\">14</x:Double>\n            <x:Double x:Key=\"BaseFontSize++\">17</x:Double>\n            <x:Double x:Key=\"BaseFontSize-\">11</x:Double>\n\n            <Style TargetType=\"sv:SettingsView\">\n                <Setter Property=\"SeparatorColor\" Value=\"{StaticResource DisabledColor}\" />\n                <Setter Property=\"BackgroundColor\" Value=\"{StaticResource PaleBackColorPrimary}\" />\n                <Setter Property=\"HeaderBackgroundColor\" Value=\"{StaticResource PaleBackColorPrimary}\" />\n                <Setter Property=\"CellBackgroundColor\" Value=\"{StaticResource AppBackground}\" />\n                <Setter Property=\"CellTitleColor\" Value=\"{StaticResource DeepTextColor}\" />\n                <Setter Property=\"CellValueTextColor\" Value=\"{StaticResource NormalTextColor}\" />\n                <Setter Property=\"CellTitleFontSize\" Value=\"{StaticResource BaseFontSize++}\" />\n                <Setter Property=\"CellValueTextFontSize\" Value=\"{StaticResource BaseFontSize}\" />\n                <Setter Property=\"CellDescriptionColor\" Value=\"{StaticResource NormalTextColor}\" />\n                <Setter Property=\"CellDescriptionFontSize\" Value=\"{StaticResource BaseFontSize-}\" />\n                <Setter Property=\"CellAccentColor\" Value=\"{StaticResource AccentColor}\" />\n                <Setter Property=\"SelectedColor\" Value=\"#50FFBF00\" />\n                <Setter Property=\"HeaderTextColor\" Value=\"{StaticResource TitleTextColor}\" />\n                <Setter Property=\"FooterFontSize\" Value=\"{StaticResource BaseFontSize-}\" />\n                <Setter Property=\"FooterTextColor\" Value=\"{StaticResource PaleTextColor}\" />\n            </Style>\n        </ResourceDictionary>\n    </Application.Resources>\n</Application>\n\n```\nWhereby any SettingsView in App will become the same property setttings.\n\n## SettingsView Properties\n\n* BackgroundColor\n\t* A color of out of region and entire region. They contains header, footer and cell (in case android).\n* SeparatorColor\n    * Row separator color.\n* SelectedColor\n    * Backgraound color when row is selected.\n   > Note that cell's ripple effect is not worked on Android when the cell background color is not set.\n* HeaderPadding\n* HeaderTextColor\n* HeaderFontSize\n* HeaderFontFamily\n* HeaderFontAttributes\n* HeaderTextVerticalAlign\n  > Note that this property is enabled only when specifying HeaderHeight.\n* HeaderBackgroundColor\n* HeaderHeight\n    * They are section header options.\n* FooterTextColor\n* FooterFontSize\n* FooterFontFamily\n* FooterFontAttributes\n* FooterBackgroundColor\n* FooterPadding\n    * They are section footer options.\n* RowHeight\n\t* If HasUnevenRows is false, this value apply to each row height;\n\t* Otherwise this value is used as minimum row height. \n* HasUnevenRows\n\t* Whether row height is fixed. Default false.(recomend true)\n* CellTitleColor\n* CellTitleFontSize\n* CellTitleFontFamily\n* CellTitleFontAttributes\n* CellValueTextColor\n* CellValueTextFontSize\n* CellValueTextFontFamily\n* CellValueTextFontAttributes\n* CellDescriptionColor\n* CellDescriptionFontSize\n* CellDescriptionFontFamily\n* CellDescriptionFontAttributes\n* CellBackgroundColor\n* CellIconSize\n* CellIconRadius\n* CellAccentColor\n* CellHintTextColor\n* CellHintFontSize\n* CellHintFontFamily\n* CellHintFontAttributes\n    * They are bulk cell options.\n* UseDescriptionAsValue (for Android)\n\t* Whether description field  is used as value field. (like general android app)\n    * Default false\n* ShowSectionTopBottomBorder (for Android)\n\t* Whether a separator is shown at section top and bottom. (like general android app)\n    * Default true\n* ShowArrowIndicatorForAndroid\n  * Whether a right arrow icon is shown at the right side in a CommandCel and PickerCell on Android.\n* ScrollToTop\n* ScrollToBottom\n\t* When this property is set to true, the screen will be scrolled to first item position or last item position.\n\t* If scrolling has complete, it will be set to false automatically.\n* VisibleContentHeight\n    * The height of the visible content. This value allows SettingsView itself height to fit total cells height.\n* ItemsSource\n* ItemTemplate\n    * A DataTemplate for entire SettingsView can be used.\n* TemplateStartIndex\n  * This is the index that starts inserting the template. The default value is 0. If a specified value is greater or equal than 1, the template is inserted from its position and the section inserted with XAML remains. You can insert the repeating data wherever you want to do.\n\n### To fit SettingsView height to visible content\n\nIf SettingsView's total cells height is shorter than the parent view height, itself height can be fit total cells height as the following:\n\n```xml\n<sv:SettingsView x:Name=\"settings\" HeightRequest=\"{Binding VisibleContentHeight,Source={x:Reference settings}}\">\n</sv:SettingsView>\n```\n\n### Sample of ItemsSource and ItemTemplate for a root\n\n```csharp\npublic class SomeViewModel\n{\n    public List<MenuSection> ItemsSource {get;set;}\n\n    public SomeViewModel()\n    {\n        ItemsSource = new List<MenuSection>{\n            new new MenuSection(\"Select number\",3){\n                new MenuItem{Title = \"3\",Value=3},\n                new MenuItem{Title = \"4\",Value=4},\n            },\n            new MenuSection(\"Select mode\",1){\n                new MenuItem{Title = \"A\",Value = 1},\n                new MenuItem{Title = \"B\",Value = 2}\n            }\n        }\n    }\n}\npublic class MenuItem\n{\n    public string Title { get; set; }\n    public int Value { get; set; }\n}\n\npublic class MenuSection:List<MenuItem>\n{\n    public string SectionTitle { get; set; }\n    public bool Selected { get;set; } // must implement INotifyPropertyChanged by some way\n\n    public MenuSection(string title,int initalSelectedValue)\n    {\n        SectionTitle = title;\n    }\n}\n```\n\n```xml\n<sv:SettingsView x:Name=\"Settings\" ItemsSource=\"{Binding ItemsSource}\">\n    <sv:SettingsView.ItemTemplate>\n        <DataTemplate>\n            <sv:Section Title=\"{Binding SectionTitle}\" ItemsSource=\"{Binding}\" sv:RadioCell.SelectedValue=\"{Binding Selected}\">\n                <sv:Section.ItemTemplate>\n                    <DataTemplate>\n                        <sv:RadioCell Title=\"{Binding Title}\" Value=\"{Binding Value}\" />\n                    </DataTemplate>\n                </sv:Section.ItemTemplate>\n            </sv:Section>\n        </DataTemplate>\n    </sv:SettingsView.ItemTemplate>\n</sv:SettingsView>\n```\n\n## SettingsView Methods\n\n* ClearCache (static)\n\t* Clear all memory cache.\n\n## Section Properties\n\n* Title\n\t* Section header text. The same as Xamarin.Forms.TableSection.\n* FooterText\n\t* Section footer text.\n* IsVisible\n\t* Whether the section is visibled.\n* HeaderHeight\n\t* Individual section header height.\n\t* Superior to SettingsView HeaderHight.  \n* ItemsSource\n\t* Specify the source of a DataTemplate.\n* ItemTemplate\n\t * Specify a DataTemplate.\n* TemplateStartIndex\n  * This is the index that starts inserting the template. The default value is 0. If a specified value is greater or equal than 1, the template is inserted from its position and cells inserted with XAML remains. You can insert the repeating data wherever you want to do.\n* UseDragSort\n\t* Enable you to reorder cells in a section with drag and drop.\n\t* Items can move in sections that UseDragSort Property is true.\n\t* If iOS version is less than or equal to iOS10, the cells can be moved when grabbing the icon drawn three lines; Otherwise can be moved when doing long tap.\n* HeaderView\n* FooterView\n  * Set a Forms View to Header or Footer.\n  > Once these are set, Title or FooterText is disabled.\n  > If HeaderView or FooterView is used, the cell height turns auto size.\n* FooterVisible\n  * Specify a FooterView visibility. Default true.\n\n### Example for Section HeaderView FooterView with XAML\n\n```xml\n<sv:Section>\n    <sv:Section.HeaderView>\n        <StackLayout>\n            <Label Text=\"Header\" />\n        </StackLayout>\n    </sv:Section.HeaderView>\n    <sv:Section.FooterView>\n        <Label Text=\"{Binding FooterText}\" />\n    </sv:Section.FooterView>\n</sv:Section>\n```\n\n### How to use an ItemsSource and an ItemTemplate for a Section\n\n```csharp\npublic class SomeModel\n{\n   // you should use a ObservableCollection if you use a dynamic list.\n   public ObservableCollection<Option> Options {get;set;}\n   public void SomeMethod()\n   {\n       Options = new ObservableCollection(GetServerData());\n   }\n}\npublic class Option\n{\n   public string Name {get;set;}\n   public string Address {get;set;}\n}\n```\n\n```xml\n<sv:Section ItemsSource=\"{Binding Options}\">\n    <sv:Section.ItemTemplate>\n        <DataTemplate>\n            <sv:LabelCell Title=\"{Binding Name}\" Value=\"{Binding Address}\" />\n        </DataTemplate>\n    </sv:Section.ItemTemplate>\n</sv:Section>\n```\n\n## Cells\n\n* [CellBase](#cellbase)\n* [LabelCell](#labelcell)\n* [CommandCell](#commandcell)\n* [ButtonCell](#buttoncell)\n* [SwitchCell](#switchcell)\n* [CheckboxCell](#checkboxcell)\n* [RadioCell](#radiocell)\n* [NumberPickerCell](#numberpickercell)\n* [TimePickerCell](#timepickercell)\n* [DatePickerCell](#datepickercell)\n* [TextPickerCell](#textpickercell)\n* [PickerCell](#pickercell)\n* [EntryCell](#entrycell)\n* [CustomCell](#customcell)\n\n## CellBase\n\n### Layout of cellbase\n\n![cell layout](./images/cell_layout.png)\n\n* Icon\n    * If not specify a imagesource, icon will be hidden.\n* Description\n    * If not specify any text, description will be hidden.\n* Accessory\n    * Be used by a CheckboxCell and  a SwitchCell; Otherwise will be hidden. \n\n### Properties (all cell types)\n\n* Title\n    * Title text.\n* TitleColor\n    * Title text color.\n* TitleFontSize\n* TitleFontFamily\n* TitleFontAttributes\n    * Title text font size, family, attributes.\n* Description\n    * Description text.\n* DescriptionColor\n    * Description text color.\n* DescriptionFontSize\n* DescriptionFontSize\n* DescriptionFontFamily\n    * Description text font size, family, attributes.\n* HintText\n    * Hint text.(for some information, validation error and so on)\n* HintTextColor\n    * Hint text color.\n* HintFontSize\n* HintFontFamily\n* HintFontAttributes\n    * Hint text font size, family, attributes.\n* BackgroundColor\n    * Cell background color.\n* IconSource\n    * Icon image source. (any ImageSource object)\n* IconSize\n    * Icon size. (width,height)\n* IconRadius\n    * Icon corners radius.\n* IsEnabled\n\t* Whether a cell is enabled. If set to false, the entire cell color will turn translucent and the cell won't accept any operations.\n* IsVisible\n  * Whether a cell is visible or not.\n\n### Methods\n\n* Reload\n  * Reload forcely the cell. This is used after dynamically changing the contents of a cell, such as Custom Cell.\n\n### To use SVG image\n\nYou can use SVG image if SvgImageSource is installed.\n\nhttps://github.com/muak/SvgImageSource  \nhttps://www.nuget.org/packages/Xamarin.Forms.Svg/\n\n```bash\nInstall-Package Xamain.Forms.Svg -pre\n```\n\n\n## LabelCell\n\nThis is a cell showing read only text.\n\n### Properties\n\n* ValueText\n    * Value text.\n* ValueTextColor\n    * Value text color.\n* ValueTextFontSize\n* ValueTextFontFamily\n* ValueTextFontAttributes\n    * Value text font size, family, attributes.\n* IgnoreUseDescriptionAsValue\n    * Whether ignore the setting that SettingsView property of UseDescriptionAsValue.\n\n## CommandCell\n\nThis is a Labelcell invoked an action.\n\n### Properties\n\n* Command\n    * Invoked action.\n* CommandParameter\n* KeepSelectedUntilBack\n    * When moving next page, whether keep the cell selected until being back to the page.\n* HideArrowIndicator\n  * Hide a right arrow icon on the right side.\n  * Even if ShowArrowIndicatorForAndroid is true, this property gives priority to.\n\nThe others are the same as LabelText.\n\n## ButtonCell\n\nThis is a simple cell invoked an action like a button. \n\n### Properties\n\n* TitleAlignment\n    * Button title horizontal alignment.\n* Command\n* CommandParameter\n\nThis cell don't use Description property.\n\n## SwitchCell\n\nThis is a LabelCell equipped a switch.\n\n### Properties\n\n* On\n    * Switch toggle on / off. On is true, Off is false. \n* AccentColor\n    * Swich accent color. (background color and so on)\n\n## CheckboxCell\n\nThis is a LabelCell equipped a checkbox.\n\n### Properties\n\n* Checked\n    * Check on / off. On is true, Off is false.\n* AccentColor\n    * Checkbox accent color. (frame and background)\n\n## RadioCell\n\nThis is the cell that can be selected just one item from in a Section or a SettingsView.\n\n### Properties\n\n* Value\n    * A value that can be selected.\n* AccentColor\n    * Check mark color.\n\n### Attached Bindable Property\n\n* SelectedValue\n    * Current selected value.\n    * If this property is set to a section, the item can be selected just one from the section, and if set to SettingsView itself, the item can be selected just one from entire SettingsView.\n    > Note that this property can't be set to both entire and a section. If it is set to both, a section side is used.\n\n### XAML Example\n\n#### For a section\n\n```xml\n<sv:SettingsView>\n    <sv:Section Title=\"Sound\" sv:RadioCell.SelectedValue=\"{Binding SelectedItem}\">\n        <sv:RadioCell Title=\"Sound1\" Value=\"{Binding Items[0]}\">\n        <sv:RadioCell Title=\"Sound2\" Value=\"{Binding Items[1]}\">\n    </sv:Section>\n</sv:SettingsView>\n```\n\n#### For global\n\n```xml\n<sv:SettingsView sv:RadioCell.SelectedValue=\"{Binding GlobalSelectedItem}\">\n    <sv:Section Title=\"Effect\">\n        <sv:RadioCell Title=\"Sound1\" Value=\"{Binding Items[0]}\">\n        <sv:RadioCell Title=\"Sound2\" Value=\"{Binding Items[1]}\">\n    </sv:Section>\n    <sv:Section Title=\"Melody\">\n        <sv:RadioCell Title=\"Melody1\" Value=\"{Binding Items[2]}\">\n        <sv:RadioCell Title=\"Melody2\" Value=\"{Binding Items[3]}\">\n    </sv:Section>\n</sv:SettingsView>\n```\n\n## NumberPickerCell\n\nThis is a LabelCell calling a number picker.\n\n### Properties\n\n* Number\n    * Current number.(default two way binding)\n* Min\n    * Minimum number.\n* Max\n    * Maximum number.\n* PickerTitle\n    * Picker title text.\n* SelectedCommand\n    * A command invoked when a number is selected.\n* Unit\n  * Unit string.\n\nThis cell can't use ValueText property.\n\n## TimePickerCell\n\nThis is a LabelCell calling a time picker.\n\n### Properties\n\n* Time\n    * Current time (default two way binding)\n* Format\n    * Time format. (for example \"hh:mm\")\n* PickerTitle\n    * Picker title text.\n\nThis cell can't use ValueText property.\n\n## DatePickerCell\n\nThis is a LabelCell calling a date picker.\n\n### Properties\n\n* Date\n    * Current date. (default two way binding)\n* MinimumDate\n* MaximumDate\n* Format\n    * Date format. (for example \"ddd MMM d yyyy\")\n* TodayText\n    * Text of the button selecting  today's date. (only iOS)\n    * If this text is empty, the button will be hidden.\n* InitialDate\n  * Date to be set as the initial value of the picker if Date is null.\n* IsAndroidSpinnerStyle\n  * True for Android when using spinner UI instead of calendar.\n* AndroidButtonColor\n  * Button text color in Android dialog.\n\n\nThis cell can't use ValueText property.\n\n## TextPickerCell\n\nThis is a LabelCell calling a text picker.\n\n### Properties\n\n* Items\n\t* Picker data source implementing IList.\n\t* This property can be set a list of built-in type. (e.g. List\\<string>, List\\<int>, List\\<double>)\n\t* The result of ToString method is used as appearance text.\n* SelectedItem\n\t* Selected item is set. (two-way binding)\n* SelectedCommand\n    * A command invoked when an item is selected.\n* IsCircularPicker\n    * Whether the picker items are circulated. (for Android) \n    * Default true\n\nThis cell can't use ValueText property.\n\n## PickerCell\n\nThis is a LabelCell calling a multiple select picker.\nWhen tapped on iOS, move next page and show picker there.\nWhen tapped on Android, show the picker on a dialog. \n\n### Properties\n\n* PageTitle\n    * Picker page title text.\n* ItemsSource\n    * Picker data source implementing IEnumerable.\n    * This have to assing a instance and must not null.\n* DisplayMember\n    * Class member(property) name Displayed on the picker.\n* SubDisplayMember\n\t * Class member(property) name secondary displayed on the Picker. If this property is set, the cell will be two line and the first line will display DisplayMember and the second line will display SubDisplayMember.\n* SelectionMode\n  * Whether SelectionMode is Single or Multiple. Default Multiple.\n* SelectedItem\n  * If SelectionMode is Single, a selected item assigned.\n* SelectedItems\n  * If SelectionMode is Multiple, selected items assigned.\n  * IList where selected items is stored.\n  * This have to assing a instance and must not null.\n* SelectedItemsOrderKey\n    * Class member(Property) name that becomes a order key when selected items is displayed  as text.\n* SelectedCommand\n\t* A command invoked When finished being selected items. \n* MaxSelectedNumber\n    * Selectable items number.\n    * If zero, unlimited multi select mode. Else if One, single select mode. Otherwise limited multi select mode.\n* KeepSelectedUntilBack\n    * When moving next page or showing a dialog, whether keep the cell selected until being back to the page.\n* AccentColor\n    * Picker checkbox color.\n* UseNaturalSort\n\t* Whether use NaturalSort as sort method. default false.\n\t* If true, for example, if  the order is normally  \"1,10,2,3,4\", is \"1,2,3,4,10\".\n\t* This option may not correctly work if not used Japanese language.\n* UsePickToClose\n\t* Whether closing the Picker automatically if the number of selected items come to MaxSelectedNumber. \n* UseAutoValueText\n\t* Normally, selected items string is automatically displayed in the ValueText. If the value of this property is specified false, the auto display will be cleared and ValueText will be available as usual.\n\n## EntryCell\n\nThis is a cell inputing some text.\n\n### Properties\n\n* ValueText\n    * Input text. (default two way binding)\n* ValueTextColor\n    * Input text color.\n* ValueTextFontSize\n* ValueTextFontFamily\n* ValueTextFontAttributes\n    * Input text font size, family, attributes.\n* MaxLength\n    * Input text maximum length.\n* Keyboard\n    * Keyboard type.\n* Placeholder\n    * Placeholder text.\n* PlaceholderColor\n    * Placeholder color.\n* TextAlignment\n    * Input text horizontal alignment.\n* AccentColor\n    * Under line color on focus. (only android)\n* IsPassword\n    * Whether the input text is hidden or not for password.\n* CompletedCommand\n  * A command invoked When completing to input or losing the focus.\n\n### Methods\n\n* SetFocus\n  * Set the EntryCell focus to show the soft keyboard.\n\n## CustomCell\n\nThis is a cell that custom layout can be freely set in the center of Layout (blocks of the Title and ValueText and Description).\nThe forms view can be specified with XAML.\n\nIt is envisaged that makes use of subclass of CustomCell.\n\n## Properties\n\n* ShowArrowIndicator\n  * Whether the arrow indicator is shown at the right side.\n  * If true, the arrow is shown regardless of iOS and Android.\n* IsSelectable\n  * Whether a row can be selected. If true, the Command can be invoked.\n* IsMeasureOnce\n  * Whether a size calculation does just once. Default false.\n  * If the height doesn't change depending on the cell contents, a size calculation can be omitted.\n* UseFullSize\n  * If true, the custom area uses full of the layout without paddings.\n  > If this property is enabled, the icon settings turn disabled.\n* Command\n    * Invoked action.\n* CommandParameter\n* LongCommand\n  * Long tap command action.\n* KeepSelectedUntilBack\n    * When moving next page, whether keep the cell selected until being back to the page.\n\n### Example for CustomCell\n\n* https://github.com/muak/AiForms.SettingsView/tree/development/Sample/Sample/Views/Cells\n* https://github.com/muak/AiForms.SettingsView/blob/development/Sample/Sample/Views/CustomCellTest.xaml\n\n## Contribution\n\nWe really appreciate your contribution.\nPlease read the [contribution guideline](CONTRIBUTING.md).\n\n## Contributors\n\n* [codegrue](https://github.com/codegrue)\n* [cpraehaus](https://github.com/cpraehaus)\n* [dylanberry](https://github.com/dylanberry)\n* [RLittlesll](https://github.com/RLittlesII)\n* [ChaseFlorell](https://github.com/ChaseFlorell)\n* [OnTheFenceDevelopment](https://github.com/OnTheFenceDevelopment)\n* [SiNeumann](https://github.com/SiNeumann)\n* [akaegi](https://github.com/akaegi)\n\n## Thanks \n\n* NaturalComparer\n    * https://github.com/tomochan154/toy-box/blob/master/NaturalComparer.cs\n\n## Donation\n\nI am asking for your donation for continuous development🙇\n\nYour donation will allow me to work harder and harder.\n\n* [PayPalMe](https://paypal.me/kamusoftJP?locale.x=ja_JP)\n\n## Sponsors\n\nI am asking for sponsors too.\nThis is a subscription.\n\n* [GitHub Sponsors](https://github.com/sponsors/muak)\n\n## License\n\nMIT Licensed.\n\nSome code is taken from [.NET MAUI](https://github.com/dotnet/maui).\n\n[Material design icons](https://github.com/google/material-design-icons) - [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)"
  },
  {
    "path": "Sample/App.xaml",
    "content": "﻿<?xml version = \"1.0\" encoding = \"UTF-8\" ?>\n<Application xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n             xmlns:local=\"clr-namespace:Sample\"\n             x:Class=\"Sample.App\">\n    <Application.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <ResourceDictionary Source=\"Resources/Styles/Colors.xaml\" />\n                <ResourceDictionary Source=\"Resources/Styles/Styles.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n        </ResourceDictionary>\n    </Application.Resources>\n</Application>\n\n"
  },
  {
    "path": "Sample/App.xaml.cs",
    "content": "﻿namespace Sample;\n\npublic partial class App : Application\n{\n    public App()\n    {\n        InitializeComponent();        \n    }\n}\n\n"
  },
  {
    "path": "Sample/MauiProgram.cs",
    "content": "﻿using System.Globalization;\nusing System.Reflection;\nusing AiForms.Settings;\nusing Microsoft.Maui;\nusing Prism;\nusing Prism.Navigation;\nusing Sample.ViewModels;\nusing Sample.Views;\n\nnamespace Sample;\n\npublic static class MauiProgram\n{\n    public static MauiApp CreateMauiApp()\n    {\n        var builder = MauiApp.CreateBuilder();\n        builder\n            .UseMauiApp<App>()            \n            .UsePrism(prism =>\n            {\n                prism.RegisterTypes(containerRegistry =>\n                {\n                    containerRegistry.RegisterForNavigation<MyNavigationPage>();\n                    containerRegistry.RegisterForNavigation<MainPage, MainViewModel>();\n                    containerRegistry.RegisterForNavigation<ContentPage>();\n                    containerRegistry.RegisterForNavigation<ListPage, ListViewModel>();\n                    containerRegistry.RegisterForNavigation<CustomHeaderPage, CustomHeaderViewModel>();\n                    containerRegistry.RegisterForNavigation<TapSurveyPage, TapSurveyViewModel>();\n                    containerRegistry.RegisterForNavigation<HeaderSurveyPage, HeaderSurveyViewModel>();\n                    containerRegistry.RegisterForNavigation<DynamicHeaderSizePage, DynamicHeaderSizeViewModel>();\n                    containerRegistry.RegisterForNavigation<SurveyPage, SurveyViewModel>();\n                })\n                .OnAppStart(async(container, navigation) =>\n                {\n                    await navigation.CreateBuilder()\n                    .AddSegment(nameof(MyNavigationPage))\n                    .AddSegment<MainViewModel>()\n                    .NavigateAsync();\n                })\n                .OnInitialized(container =>\n                {\n                    TaskScheduler.UnobservedTaskException += (s, e) =>\n                    {\n                        System.Diagnostics.Debug.WriteLine(e.Exception);\n                    };\n                    AppDomain.CurrentDomain.UnhandledException += (s, e) =>\n                    {\n                        System.Diagnostics.Debug.WriteLine(e.ExceptionObject);\n                    };\n                });\n            })\n            .ConfigureMauiHandlers(handlers =>\n            {\n                handlers.AddSettingsViewHandler();\n            })\n            .ConfigureFonts(fonts =>\n            {\n                fonts.AddFont(\"OpenSans-Regular.ttf\", \"OpenSansRegular\");\n                fonts.AddFont(\"OpenSans-Semibold.ttf\", \"OpenSansSemibold\");\n            });        \n\n        return builder.Build();\n    }\n}\n\n"
  },
  {
    "path": "Sample/Platforms/Android/AndroidManifest.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" package=\"jp.kamusoft.settingsview\" android:versionCode=\"1\" android:versionName=\"1.0\">\n\t<application android:allowBackup=\"true\" android:icon=\"@mipmap/appicon\" android:supportsRtl=\"true\" android:label=\"Sample\"></application>\n\t<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n\t<uses-permission android:name=\"android.permission.INTERNET\" />\n\t<uses-sdk android:minSdkVersion=\"27\" android:targetSdkVersion=\"34\" />\n</manifest>"
  },
  {
    "path": "Sample/Platforms/Android/MainActivity.cs",
    "content": "﻿using System.Reflection;\r\nusing Android.App;\nusing Android.Content;\nusing Android.Content.PM;\nusing Android.OS;\nusing Google.Android.Material.AppBar;\nusing Microsoft.Maui.Platform;\n\nnamespace Sample;\n\n[Activity(Theme = \"@style/Maui.SplashTheme\", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]\npublic class MainActivity : MauiAppCompatActivity\n{\n    protected override void OnCreate(Bundle savedInstanceState)\n    {\n        base.OnCreate(savedInstanceState);\n\n        var layout = FindViewById<AppBarLayout>(Resource.Id.navigationlayout_appbar);\n        layout.Elevation = this.ToPixels(1);\n    }\n}\n\n"
  },
  {
    "path": "Sample/Platforms/Android/MainApplication.cs",
    "content": "﻿using Android.App;\nusing Android.Runtime;\n\nnamespace Sample;\n\n[Application]\npublic class MainApplication : MauiApplication\n{\n    public MainApplication(IntPtr handle, JniHandleOwnership ownership)\n        : base(handle, ownership)\n    {\n    }\n\n    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();\n}\n\n"
  },
  {
    "path": "Sample/Platforms/Android/Resources/values/colors.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#512BD4</color>\n    <color name=\"colorPrimaryDark\">#2B0B98</color>\n    <color name=\"colorAccent\">#2B0B98</color>\n</resources>\n\n"
  },
  {
    "path": "Sample/Platforms/iOS/AppDelegate.cs",
    "content": "﻿using Foundation;\n\nnamespace Sample;\n\n[Register(\"AppDelegate\")]\npublic class AppDelegate : MauiUIApplicationDelegate\n{\n    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();\n}\n\n"
  },
  {
    "path": "Sample/Platforms/iOS/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UIDeviceFamily</key>\n\t<array>\n\t\t<integer>1</integer>\n\t\t<integer>2</integer>\n\t</array>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>arm64</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>XSAppIconAssets</key>\n\t<string>Assets.xcassets/appicon.appiconset</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>SettingsView</string>\n\t<key>CFBundleName</key>\n\t<string>SettingsView</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Sample/Platforms/iOS/Program.cs",
    "content": "﻿using ObjCRuntime;\nusing UIKit;\n\nnamespace Sample;\n\npublic class Program\n{\n    // This is the main entry point of the application.\n    static void Main(string[] args)\n    {\n        // if you want to use a different Application Delegate class from \"AppDelegate\"\n        // you can specify it here.\n        UIApplication.Main(args, null, typeof(AppDelegate));\n    }\n}\n\n"
  },
  {
    "path": "Sample/Properties/launchSettings.json",
    "content": "﻿{\n  \"profiles\": {\n    \"Windows Machine\": {\n      \"commandName\": \"MsixPackage\",\n      \"nativeDebugging\": false\n    }\n  }\n}\n"
  },
  {
    "path": "Sample/Resources/Raw/AboutAssets.txt",
    "content": "﻿Any raw assets you want to be deployed with your application can be placed in\nthis directory (and child directories). Deployment of the asset to your application\nis automatically handled by the following `MauiAsset` Build Action within your `.csproj`.\n\n    <MauiAsset Include=\"Resources\\Raw\\**\" LogicalName=\"%(RecursiveDir)%(Filename)%(Extension)\" />\n\nThese files will be deployed with you package and will be accessible using Essentials:\n\n    async Task LoadMauiAsset()\n    {\n        using var stream = await FileSystem.OpenAppPackageFileAsync(\"AboutAssets.txt\");\n        using var reader = new StreamReader(stream);\n\n        var contents = reader.ReadToEnd();\n    }\n\n\n"
  },
  {
    "path": "Sample/Resources/Styles/Colors.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<?xaml-comp compile=\"true\" ?>\n<ResourceDictionary \n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\">\n\n    <Color x:Key=\"Primary\">#512BD4</Color>\n    <Color x:Key=\"Secondary\">#DFD8F7</Color>\n    <Color x:Key=\"Tertiary\">#2B0B98</Color>\n    <Color x:Key=\"White\">White</Color>\n    <Color x:Key=\"Black\">Black</Color>\n    <Color x:Key=\"Gray100\">#E1E1E1</Color>\n    <Color x:Key=\"Gray200\">#C8C8C8</Color>\n    <Color x:Key=\"Gray300\">#ACACAC</Color>\n    <Color x:Key=\"Gray400\">#919191</Color>\n    <Color x:Key=\"Gray500\">#6E6E6E</Color>\n    <Color x:Key=\"Gray600\">#404040</Color>\n    <Color x:Key=\"Gray900\">#212121</Color>\n    <Color x:Key=\"Gray950\">#141414</Color>\n    <SolidColorBrush x:Key=\"PrimaryBrush\" Color=\"{StaticResource Primary}\"/>\n    <SolidColorBrush x:Key=\"SecondaryBrush\" Color=\"{StaticResource Secondary}\"/>\n    <SolidColorBrush x:Key=\"TertiaryBrush\" Color=\"{StaticResource Tertiary}\"/>\n    <SolidColorBrush x:Key=\"WhiteBrush\" Color=\"{StaticResource White}\"/>\n    <SolidColorBrush x:Key=\"BlackBrush\" Color=\"{StaticResource Black}\"/>\n    <SolidColorBrush x:Key=\"Gray100Brush\" Color=\"{StaticResource Gray100}\"/>\n    <SolidColorBrush x:Key=\"Gray200Brush\" Color=\"{StaticResource Gray200}\"/>\n    <SolidColorBrush x:Key=\"Gray300Brush\" Color=\"{StaticResource Gray300}\"/>\n    <SolidColorBrush x:Key=\"Gray400Brush\" Color=\"{StaticResource Gray400}\"/>\n    <SolidColorBrush x:Key=\"Gray500Brush\" Color=\"{StaticResource Gray500}\"/>\n    <SolidColorBrush x:Key=\"Gray600Brush\" Color=\"{StaticResource Gray600}\"/>\n    <SolidColorBrush x:Key=\"Gray900Brush\" Color=\"{StaticResource Gray900}\"/>\n    <SolidColorBrush x:Key=\"Gray950Brush\" Color=\"{StaticResource Gray950}\"/>\n\n    <Color x:Key=\"Yellow100Accent\">#F7B548</Color>\n    <Color x:Key=\"Yellow200Accent\">#FFD590</Color>\n    <Color x:Key=\"Yellow300Accent\">#FFE5B9</Color>\n    <Color x:Key=\"Cyan100Accent\">#28C2D1</Color>\n    <Color x:Key=\"Cyan200Accent\">#7BDDEF</Color>\n    <Color x:Key=\"Cyan300Accent\">#C3F2F4</Color>\n    <Color x:Key=\"Blue100Accent\">#3E8EED</Color>\n    <Color x:Key=\"Blue200Accent\">#72ACF1</Color>\n    <Color x:Key=\"Blue300Accent\">#A7CBF6</Color>\n\n</ResourceDictionary>\n"
  },
  {
    "path": "Sample/Resources/Styles/Styles.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<?xaml-comp compile=\"true\" ?>\n<ResourceDictionary \n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\">\n\n    <Style TargetType=\"ActivityIndicator\">\n        <Setter Property=\"Color\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n    </Style>\n\n    <Style TargetType=\"IndicatorView\">\n        <Setter Property=\"IndicatorColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\"/>\n        <Setter Property=\"SelectedIndicatorColor\" Value=\"{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}\"/>\n    </Style>\n\n    <Style TargetType=\"Border\">\n        <Setter Property=\"Stroke\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"StrokeShape\" Value=\"Rectangle\"/>\n        <Setter Property=\"StrokeThickness\" Value=\"1\"/>\n    </Style>\n\n    <Style TargetType=\"BoxView\">\n        <Setter Property=\"Color\" Value=\"{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n    <Style TargetType=\"Button\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Primary}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\"/>\n        <Setter Property=\"FontSize\" Value=\"14\"/>\n        <Setter Property=\"CornerRadius\" Value=\"8\"/>\n        <Setter Property=\"Padding\" Value=\"14,10\"/>\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}\" />\n                            <Setter Property=\"BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"CheckBox\">\n        <Setter Property=\"Color\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"Color\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"DatePicker\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\"/>\n        <Setter Property=\"FontSize\" Value=\"14\"/>\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Editor\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\"/>\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"PlaceholderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Entry\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\"/>\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"PlaceholderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Frame\">\n        <Setter Property=\"HasShadow\" Value=\"False\" />\n        <Setter Property=\"BorderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"CornerRadius\" Value=\"8\" />\n    </Style>\n\n    <Style TargetType=\"ImageButton\">\n        <Setter Property=\"Opacity\" Value=\"1\" />\n        <Setter Property=\"BorderColor\" Value=\"Transparent\"/>\n        <Setter Property=\"BorderWidth\" Value=\"0\"/>\n        <Setter Property=\"CornerRadius\" Value=\"0\"/>\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"Opacity\" Value=\"0.5\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Label\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"ListView\">\n        <Setter Property=\"SeparatorColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"RefreshControlColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n    <Style TargetType=\"Picker\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"TitleColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\"/>\n        <Setter Property=\"FontSize\" Value=\"14\"/>\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"TitleColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"ProgressBar\">\n        <Setter Property=\"ProgressColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"ProgressColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"RadioButton\">\n        <Setter Property=\"Background\" Value=\"Transparent\"/>\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\"/>\n        <Setter Property=\"FontSize\" Value=\"14\"/>\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"RefreshView\">\n        <Setter Property=\"RefreshColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n    <Style TargetType=\"SearchBar\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"PlaceholderColor\" Value=\"{StaticResource Gray500}\" />\n        <Setter Property=\"CancelButtonColor\" Value=\"{StaticResource Gray500}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"PlaceholderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"SearchHandler\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"PlaceholderColor\" Value=\"{StaticResource Gray500}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"PlaceholderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Shadow\">\n        <Setter Property=\"Radius\" Value=\"15\" />\n        <Setter Property=\"Opacity\" Value=\"0.5\" />\n        <Setter Property=\"Brush\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Offset\" Value=\"10,10\" />\n    </Style>\n\n    <Style TargetType=\"Slider\">\n        <Setter Property=\"MinimumTrackColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"MaximumTrackColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}\" />\n        <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"MinimumTrackColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\"/>\n                            <Setter Property=\"MaximumTrackColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\"/>\n                            <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\"/>\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"SwipeItem\">\n        <Setter Property=\"BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}\" />\n    </Style>\n\n    <Style TargetType=\"Switch\">\n        <Setter Property=\"OnColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"ThumbColor\" Value=\"{StaticResource White}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"OnColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                    <VisualState x:Name=\"On\">\n                        <VisualState.Setters>\n                            <Setter Property=\"OnColor\" Value=\"{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}\" />\n                            <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                    <VisualState x:Name=\"Off\">\n                        <VisualState.Setters>\n                            <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"TimePicker\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Background\" Value=\"Transparent\"/>\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\"/>\n        <Setter Property=\"FontSize\" Value=\"14\"/>\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Page\" ApplyToDerivedTypes=\"True\">\n        <Setter Property=\"Padding\" Value=\"0\"/>\n        <Setter Property=\"BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}\" />\n    </Style>\n\n    <Style TargetType=\"Shell\" ApplyToDerivedTypes=\"True\">\n        <Setter Property=\"Shell.BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"Shell.ForegroundColor\" Value=\"{OnPlatform WinUI={StaticResource Primary}, Default={StaticResource White}}\"></Setter>\n        <Setter Property=\"Shell.TitleColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Shell.DisabledColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"Shell.UnselectedColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}\" />\n        <Setter Property=\"Shell.NavBarHasShadow\" Value=\"False\" />\n        <Setter Property=\"Shell.TabBarBackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}\" />\n        <Setter Property=\"Shell.TabBarForegroundColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Shell.TabBarTitleColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Shell.TabBarUnselectedColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n    <Style TargetType=\"NavigationPage\">\n        <Setter Property=\"BarBackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"BarTextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}\" />\n        <Setter Property=\"IconColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}\" />\n    </Style>\n\n    <Style TargetType=\"TabbedPage\">\n        <Setter Property=\"BarBackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"BarTextColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"UnselectedTabColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"SelectedTabColor\" Value=\"{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n</ResourceDictionary>\n\n"
  },
  {
    "path": "Sample/Sample.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\r\n\r\n\t<PropertyGroup>\r\n\t\t<TargetFrameworks>net9.0-android;net9.0-ios</TargetFrameworks>\r\n\t\t<OutputType>Exe</OutputType>\r\n\t\t<RootNamespace>Sample</RootNamespace>\r\n\t\t<UseMaui>true</UseMaui>\r\n\t\t<MauiVersion>9.0.120</MauiVersion>\r\n\t\t<SingleProject>true</SingleProject>\r\n\t\t<ImplicitUsings>enable</ImplicitUsings>\r\n\r\n\t\t<!-- Display name -->\r\n\t\t<ApplicationTitle>Sample</ApplicationTitle>\r\n\r\n\t\t<!-- App Identifier -->\r\n\t\t<ApplicationId>jp.kamusoft.settingsview</ApplicationId>\r\n\t\t<ApplicationIdGuid>60E379AA-F738-4400-9693-BC2CD84B27FB</ApplicationIdGuid>\r\n\r\n\t\t<!-- Versions -->\r\n\t\t<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>\r\n\t\t<ApplicationVersion>1</ApplicationVersion>\r\n\r\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'\">15.0</SupportedOSPlatformVersion>\r\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'\">27.0</SupportedOSPlatformVersion>\r\n\t</PropertyGroup>\r\n\r\n\t<PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\r\n\t\t<WarningLevel>4</WarningLevel>\r\n\t\t<AndroidUseSharedRuntime>true</AndroidUseSharedRuntime>\r\n\t</PropertyGroup>\r\n\r\n\t<PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net9.0-ios|AnyCPU'\">\r\n\t\t<CodesignKey>iPhone Developer</CodesignKey>\r\n\t\t<MtouchLink>None</MtouchLink>\r\n\t\t<CreatePackage>false</CreatePackage>\r\n\t</PropertyGroup>\r\n\t<PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-ios|AnyCPU'\">\r\n\t  <CodesignKey>iPhone Developer</CodesignKey>\r\n\t  <MtouchDebug>true</MtouchDebug>\r\n\t  <!--<CodesignProvision>自動</CodesignProvision>-->\r\n\t  <CreatePackage>false</CreatePackage>\r\n\t</PropertyGroup>\r\n\t<PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net9.0-android|AnyCPU'\">\r\n\t  <EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk>\t  \t  \t  \t  \t  \r\n\t</PropertyGroup>\r\n\t<ItemGroup>\r\n\t\t<!-- App Icon -->\r\n\t\t<MauiIcon Include=\"Resources\\AppIcon\\appicon.svg\" ForegroundFile=\"Resources\\AppIcon\\appiconfg.svg\" Color=\"#512BD4\" />\r\n\r\n\t\t<!-- Splash Screen -->\r\n\t\t<MauiSplashScreen Include=\"Resources\\Splash\\splash.svg\" Color=\"#512BD4\" BaseSize=\"128,128\" />\r\n\r\n\t\t<!-- Images -->\r\n\t\t<MauiImage Include=\"Resources\\Images\\*\" />\r\n\t\t<MauiFont Include=\"Resources\\Fonts\\*\" />\r\n\r\n\t\t<!-- Raw Assets (also remove the \"Resources\\Raw\" prefix) -->\r\n\t\t<MauiAsset Include=\"Resources\\Raw\\**\" LogicalName=\"%(RecursiveDir)%(Filename)%(Extension)\" />\r\n\t</ItemGroup>\r\n\t\r\n\t<ItemGroup>\r\n\t  <PackageReference Include=\"Prism.DryIoc.Maui\" Version=\"9.0.271-pre\" />\r\n\t  <PackageReference Include=\"ReactiveProperty\" Version=\"9.3.4\" />\r\n\t  <PackageReference Include=\"Microsoft.Maui.Controls\" Version=\"$(MauiVersion)\" />\r\n\t  <PackageReference Include=\"Microsoft.Maui.Controls.Compatibility\" Version=\"$(MauiVersion)\" />\r\n\t</ItemGroup>\r\n\t\r\n\t<ItemGroup>\r\n\t  <ProjectReference Include=\"..\\SettingsView\\SettingsView.csproj\" />\r\n\t</ItemGroup>\r\n</Project>\r\n"
  },
  {
    "path": "Sample/ViewModels/CustomHeaderViewModel.cs",
    "content": "﻿using System;\nusing Reactive.Bindings;\n\nnamespace Sample.ViewModels;\n\npublic class CustomHeaderViewModel:BindableBase\n{\n    public ReactivePropertySlim<string> Description { get; } = new ReactivePropertySlim<string>();\n    public ReactivePropertySlim<bool> IsAgree { get; } = new ReactivePropertySlim<bool>();\n\n    public CustomHeaderViewModel()\n    {        \n        Description.Value = \"Text TextText Text Text Text Text Text Text Text Text Text Text Text Text Text End\";\n    }\n}\n\n"
  },
  {
    "path": "Sample/ViewModels/DynamicHeaderSizeViewModel.cs",
    "content": "namespace Sample.ViewModels;\n\npublic class DynamicHeaderSizeViewModel: BindableBase, IInitializeAsync,IPageLifecycleAware\n{\n    public List<SampleHeaderModel> Items { get; set; }\n    \n    public Task InitializeAsync(INavigationParameters parameters)\n    {\n        Items = new List<SampleHeaderModel>\n        {\n            new SampleHeaderModel\n            {\n                HeaderTitle = \"Header 1\",\n                DataList = new List<SampleDataModel>()\n                {\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 1\",\n                        Data = \"Data 1\"\n                    },\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 2\",\n                        Data = \"Data 2\"\n                    },\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 3\",\n                        Data = \"Data 3\"\n                    },\n                }\n            },\n            new SampleHeaderModel()\n            {\n                HeaderTitle = \"Header 2\",\n                DataList = new List<SampleDataModel>()\n                {\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 1\",\n                        Data = \"Data 1\"\n                    },\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 2\",\n                        Data = \"Data 2\"\n                    },\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 3\",\n                        Data = \"Data 3\"\n                    },\n                }\n            },\n            new SampleHeaderModel()\n            {\n                HeaderTitle = \"Header 3\",\n                DataList = new List<SampleDataModel>()\n                {\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 1\",\n                        Data = \"Data 1\"\n                    },\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 2\",\n                        Data = \"Data 2\"\n                    },\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 3\",\n                        Data = \"Data 3\"\n                    },\n                }\n            },\n            new SampleHeaderModel()\n            {\n                HeaderTitle = \"Header 4\",\n                DataList = new List<SampleDataModel>()\n                {\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 1\",\n                        Data = \"Data 1\"\n                    },\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 2\",\n                        Data = \"Data 2\"\n                    },\n                    new SampleDataModel()\n                    {\n                        Title = \"Title 3\",\n                        Data = \"Data 3\"\n                    },\n                }\n            },\n        };\n        return Task.CompletedTask;\n    }\n\n    public async void OnAppearing()\n    {\n        await Task.Delay(250);\n        RaisePropertyChanged(nameof(Items));\n    }\n\n    public void OnDisappearing()\n    {\n    }\n}\n\npublic class SampleHeaderModel\n{\n    public List<SampleDataModel> DataList { get; set; }\n    public string HeaderTitle { get; set; }\n}\n\npublic class SampleDataModel\n{\n    public string Title { get; set; }\n    public string Data { get; set; }\n}"
  },
  {
    "path": "Sample/ViewModels/HeaderSurveyViewModel.cs",
    "content": "﻿using System;\nusing Reactive.Bindings;\n\nnamespace Sample.ViewModels;\n\npublic class HeaderSurveyViewModel: BindableBase\n{\n    public ReactivePropertySlim<bool> IsShow { get; } = new();\n\n    public HeaderSurveyViewModel()\n    {\n    }\n}\n\n"
  },
  {
    "path": "Sample/ViewModels/ListViewModel.cs",
    "content": "﻿using System;\nusing System.Collections.ObjectModel;\n\nnamespace Sample.ViewModels;\n\npublic class ListViewModel: BindableBase\n{\n    public ObservableCollection<string> ItemsSource { get; set; }\n\n    public ListViewModel()\n    {\n        var list = new List<string>\n        {\n            \"Item1\",\"Item2\",\"Item3\",\"Item4\",\"Item5\",\"Item6\",\"Item7\",\"Item8\",\"Item9\",\"Item10\",\n            \"Item11\",\"Item12\",\"Item13\",\"Item14\",\"Item15\",\"Item16\",\"Item17\",\"Item18\",\"Item19\",\"Item20\",\n        };\n\n        ItemsSource = new ObservableCollection<string>(list);\n    }\n}\n\n"
  },
  {
    "path": "Sample/ViewModels/MainViewModel.cs",
    "content": "﻿using System;\nusing System.Collections.ObjectModel;\nusing System.ComponentModel.DataAnnotations;\nusing System.Reactive.Linq;\nusing Reactive.Bindings;\n\nnamespace Sample.ViewModels\n{\n    public class MainViewModel: BindableBase\n    {\n        [Required(ErrorMessage = \"Required\")]\n        [StringLength(15, ErrorMessage = \"Input text less than or equal to 15 characters\")]\n        public ReactiveProperty<string> InputText { get; }\n        public ReadOnlyReactiveProperty<string> InputError { get; }\n\n        public ReactiveProperty<bool> InputSectionVisible { get; } = new ReactiveProperty<bool>(true);\n        public ReactivePropertySlim<string> Content { get; } = new ReactivePropertySlim<string>(\"\");\n        public ReactivePropertySlim<string> Description { get; } = new ReactivePropertySlim<string>(\"\");\n\n        public ReactiveCommand ToProfileCommand { get; set; } = new ReactiveCommand();\n        public AsyncReactiveCommand SectionToggleCommand { get; set; }\n        public ReactiveCommand ClearContentCommand { get; } = new ReactiveCommand();\n        public ReactiveCommand AddContentCommand { get; } = new ReactiveCommand();\n\n        public ObservableCollection<Person> ItemsSource { get; } = new ObservableCollection<Person>();\n        public ObservableCollection<Person> SelectedItems { get; } = new ObservableCollection<Person>();\n\n        public ObservableCollection<string> TextItems { get; } = new ObservableCollection<string>(new List<string> { \"Red\", \"Blue\", \"Green\", \"Pink\", \"Black\", \"White\" });\n        public ReactiveProperty<string> SelectedText { get; } = new ReactiveProperty<string>(\"Green\");\n\n        string[] languages = { \"Java\", \"C#\", \"JavaScript\", \"PHP\", \"Perl\", \"C++\", \"Swift\", \"Kotlin\", \"Python\", \"Ruby\", \"Scala\", \"F#\" };\n\n        public MainViewModel(INavigationService navigationService)\n        {\n            InputText = new ReactiveProperty<string>().SetValidateAttribute(() => this.InputText);\n\n            InputError = InputText.ObserveErrorChanged\n                                  .Select(x => x?.Cast<string>()?.FirstOrDefault())\n                                  .ToReadOnlyReactiveProperty();\n\n            SectionToggleCommand = InputText.ObserveHasErrors.Select(x => !x).ToAsyncReactiveCommand();\n            SectionToggleCommand.Subscribe(async _ => {\n                InputSectionVisible.Value = !InputSectionVisible.Value;\n                await Task.Delay(250);\n            });\n\n            ToProfileCommand.Subscribe(async _ => {\n\n                //Description.Value += \"01234567890\";\n                //await navigationService.NavigateAsync(\"ListPage\");\n                //await navigationService.NavigateAsync(\"TapSurveyPage\");\n                // await navigationService.NavigateAsync(\"HeaderSurveyPage\");\n                // await navigationService.NavigateAsync(\"DynamicHeaderSizePage\");\n                await navigationService.NavigateAsync(\"SurveyPage\");\n            });\n\n            AddContentCommand.Subscribe(_ =>\n            {\n                Content.Value += \"A\\n\";\n            });\n\n            ClearContentCommand.Subscribe(_ =>\n            {\n                Content.Value = \"\";\n            });\n\n            foreach (var item in languages)\n            {\n                ItemsSource.Add(new Person()\n                {\n                    Name = item,\n                    Age = 1\n                });\n            }\n\n            SelectedItems.Add(ItemsSource[1]);\n            SelectedItems.Add(ItemsSource[2]);\n            SelectedItems.Add(ItemsSource[3]);\n        }\n    }\n\n    public class Person\n    {\n        public string Name { get; set; }\n        public int Age { get; set; }\n    }\n}\n\n"
  },
  {
    "path": "Sample/ViewModels/SurveyViewModel.cs",
    "content": "using System.Collections.ObjectModel;\nusing Reactive.Bindings;\n\nnamespace Sample.ViewModels;\n\npublic class SurveyViewModel: BindableBase\n{\n    public ObservableCollection<string> ItemsSource { get; set; } = new();\n    public ObservableCollection<string> ItemsSource2 { get; set; } = new();\n    public ReactivePropertySlim<bool> IsShow { get; } = new();\n\n    public AsyncReactiveCommand SubmitCommand { get; } = new();\n    \n    public SurveyViewModel()\n    {\n        ItemsSource2.Add(\"X\");\n        ItemsSource2.Add(\"Y\");\n        ItemsSource2.Add(\"Z\");\n        \n        SubmitCommand.Subscribe(async () =>\n        {\n            ItemsSource.Clear();\n            await Task.Delay(500);\n            ItemsSource = new(new[] { \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\",\"n\",\"o\",\"p\",\"q\",\"r\",\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\",\"n\",\"o\",\"p\",\"q\",\"r\" });\n            IsShow.Value = true;\n            RaisePropertyChanged(nameof(ItemsSource));\n        });\n    }\n}"
  },
  {
    "path": "Sample/ViewModels/TapSurveyViewModel.cs",
    "content": "﻿using System;\nnamespace Sample.ViewModels;\n\npublic class TapSurveyViewModel:BindableBase\n{\n    public TapSurveyViewModel()\n    {\n    }\n}\n\n"
  },
  {
    "path": "Sample/Views/Cells/MyCellA.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sv:CustomCell\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    x:Class=\"Sample.Views.Cells.MyCellA\" ShowArrowIndicator=\"True\" IsMeasureOnce=\"True\" UseFullSize=\"True\"\n    x:Name=\"me\" >\n\n    <StackLayout BackgroundColor=\"Blue\" InputTransparent=\"True\">\n        <Label Text=\"{Binding Text,Source={x:Reference me}}\" InputTransparent=\"True\" HeightRequest=\"20\" />\n        <Label Text=\"Hoge\" />\n        <Label Text=\"Fuga\" />\n    </StackLayout>\n\n</sv:CustomCell>\n"
  },
  {
    "path": "Sample/Views/Cells/MyCellA.xaml.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing AiForms.Settings;\n\nnamespace Sample.Views.Cells;\n\r\n[XamlCompilation(XamlCompilationOptions.Compile)]\npublic partial class MyCellA : CustomCell\n{\n    public MyCellA()\n    {\n        InitializeComponent();\n    }\n\n    public static BindableProperty TextProperty =\n        BindableProperty.Create(\n            nameof(Text),\n            typeof(string),\n            typeof(MyCellA),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public string Text {\n        get { return (string)GetValue(TextProperty); }\n        set { SetValue(TextProperty, value); }\n    }\n}\n"
  },
  {
    "path": "Sample/Views/Cells/MyCellB.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sv:CustomCell\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    x:Class=\"Sample.Views.Cells.MyCellB\" IsSelectable=\"False\" ShowArrowIndicator=\"False\">\n\n    <StackLayout BackgroundColor=\"Green\">\n        <Button Text=\"Hoge\" />\n        <Button Text=\"Fuga\" />\n        <BoxView Color=\"Red\" HeightRequest=\"20\" />\n        <Label Text=\"AAAAAAAAAAAAAAA\" />\n    </StackLayout>      \n\n</sv:CustomCell>\n"
  },
  {
    "path": "Sample/Views/Cells/MyCellB.xaml.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing AiForms.Settings;\n\nnamespace Sample.Views.Cells;\n\r\n[XamlCompilation(XamlCompilationOptions.Compile)]\npublic partial class MyCellB : CustomCell\n{\n    public MyCellB()\n    {\n        InitializeComponent();\n    }\n}\n"
  },
  {
    "path": "Sample/Views/Cells/MyCellC.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sv:CustomCell\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n     x:Class=\"Sample.Views.Cells.MyCellC\"\n    IsMeasureOnce=\"True\" UseFullSize=\"True\" ShowArrowIndicator=\"False\">\n  \n    <StackLayout BackgroundColor=\"#999900\">\n        <Label Text=\"FullSize\" />\n    </StackLayout>\n</sv:CustomCell>\n"
  },
  {
    "path": "Sample/Views/Cells/MyCellC.xaml.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing AiForms.Settings;\n\nnamespace Sample.Views.Cells;\n\r\n[XamlCompilation(XamlCompilationOptions.Compile)]\npublic partial class MyCellC : CustomCell\n{\n    public MyCellC()\n    {\n        InitializeComponent();\n    }\n}\n"
  },
  {
    "path": "Sample/Views/Cells/SliderCell.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sv:CustomCell\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    x:Class=\"Sample.Views.Cells.SliderCell\"\n    IsSelectable=\"False\" IsMeasureOnce=\"True\" ShowArrowIndicator=\"False\" x:Name=\"me\">\n\n    <Slider Minimum=\"{Binding Min,Source={x:Reference me}}\" Maximum=\"{Binding Max,Source={x:Reference me}}\" Value=\"{Binding Value,Source={x:Reference me}}\"\n            ValueChanged=\"OnChanged\" MinimumTrackColor=\"Red\" MaximumTrackColor=\"Gray\" ThumbColor=\"Orange\"\nHorizontalOptions=\"FillAndExpand\" />\n\n</sv:CustomCell>\n"
  },
  {
    "path": "Sample/Views/Cells/SliderCell.xaml.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows.Input;\nusing AiForms.Settings;\n\nnamespace Sample.Views.Cells;\n\r\npublic partial class SliderCell : CustomCell\n{\n    public SliderCell()\n    {\n        InitializeComponent();\n    }\n\n    public static BindableProperty ValueProperty =\n        BindableProperty.Create(\n            nameof(Value),\n            typeof(double),\n            typeof(SliderCell),\n            default(double),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    public double Value {\n        get { return (double)GetValue(ValueProperty); }\n        set { SetValue(ValueProperty, value); }\n    }\n\n    public static BindableProperty MinProperty =\n        BindableProperty.Create(\n            nameof(Min),\n            typeof(double),\n            typeof(SliderCell),\n            default(double),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public double Min {\n        get { return (double)GetValue(MinProperty); }\n        set { SetValue(MinProperty, value); }\n    }\n\n    public static BindableProperty MaxProperty =\n        BindableProperty.Create(\n            nameof(Max),\n            typeof(double),\n            typeof(SliderCell),\n            1.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public double Max {\n        get { return (double)GetValue(MaxProperty); }\n        set { SetValue(MaxProperty, value); }\n    }\n\n    public static BindableProperty ChangedCommandProperty =\n        BindableProperty.Create(\n            nameof(ChangedCommand),\n            typeof(ICommand),\n            typeof(SliderCell),\n            default(ICommand),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public ICommand ChangedCommand {\n        get { return (ICommand)GetValue(ChangedCommandProperty); }\n        set { SetValue(ChangedCommandProperty, value); }\n    }\n\n    void OnChanged(object sender,ValueChangedEventArgs e)\n    {\n        if(ChangedCommand == null)\n        {\n            return;\n        }\n\n        if(ChangedCommand.CanExecute(null))\n        {\n            ChangedCommand.Execute(Value);\n        }\n    }\n}\n"
  },
  {
    "path": "Sample/Views/CustomHeaderPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    x:Class=\"Sample.Views.CustomHeaderPage\"\n    Title=\"CustomHeaderPage\">\n    <Grid RowDefinitions=\"*,Auto\" BackgroundColor=\"LightGray\">\n        <sv:SettingsView HeaderBackgroundColor=\"LightGray\" Grid.Row=\"0\">\n            <sv:Section>\n                <sv:Section.HeaderView>\n                   <Grid RowDefinitions=\"Auto,Auto\" Padding=\"16,8,16,8\">\n                        <Border Grid.Row=\"0\"\n                            Stroke=\"Red\"\n                            StrokeThickness=\"{OnPlatform iOS=3,Android=1}\"\n                            Padding=\"8\" BackgroundColor=\"#FFDDDD\"                                   \n                            Margin=\"0,8,0,8\" StrokeShape=\"RoundRectangle 16\">\n                        \n                            <Grid ColumnDefinitions=\"Auto,*,Auto\" RowDefinitions=\"Auto\">\n\n                                <Image Grid.Column=\"0\"\n                                        Source=\"dotnet_bot\"\n                                        WidthRequest=\"30\" HeightRequest=\"30\"\n                                        VerticalOptions=\"Center\" />\n                                <Label Grid.Column=\"1\" Text=\"{Binding Description.Value}\"\n                                        TextColor=\"Black\"\n                                        FontSize=\"18\"\n                                        LineBreakMode=\"WordWrap\"\n                                        />\n                                <Image Grid.Column=\"2\" Source=\"ic_close\"\n                                        WidthRequest=\"12\" HeightRequest=\"12\"\n                                        VerticalOptions=\"Center\" />\n                            </Grid>\n                        </Border>\n                        <StackLayout Orientation=\"Horizontal\" Spacing=\"0\" Grid.Row=\"1\"\n                                     >\n\n                            <CheckBox IsChecked=\"{Binding IsAgree.Value}\" Color=\"Orange\"\n                                        VerticalOptions=\"Center\" WidthRequest=\"36\" x:Name=\"agreeCheckbox\" />\n                            <Label Text=\"I Agree\"\n                                    TextColor=\"Black\"\n                                    FontSize=\"18\"\n                                    VerticalOptions=\"Center\" />\n                        </StackLayout>\n                    </Grid>\n                \n                </sv:Section.HeaderView>                \n            </sv:Section>\n\n            <sv:Section Title=\"TitleA\">\n                <sv:LabelCell Title=\"Label\" />\n            </sv:Section>\n\n            <sv:Section Title=\"TitleB\">\n                <sv:LabelCell Title=\"Label\" />\n            </sv:Section>\n\n        </sv:SettingsView>\n\n        <Button Grid.Row=\"1\" Text=\"Button\" Margin=\"32,16,32,16\" />\n    </Grid>\n</ContentPage>\n"
  },
  {
    "path": "Sample/Views/CustomHeaderPage.xaml.cs",
    "content": "﻿namespace Sample.Views;\n\npublic partial class CustomHeaderPage : ContentPage\n{\n    public CustomHeaderPage()\n    {\n        InitializeComponent();\n    }\n}\n"
  },
  {
    "path": "Sample/Views/DynamicHeaderSizePage.xaml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<ContentPage \n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    xmlns:vm=\"clr-namespace:Sample.ViewModels\"\n    x:Class=\"Sample.Views.DynamicHeaderSizePage\"\n    x:DataType=\"vm:DynamicHeaderSizeViewModel\"\n    BackgroundColor=\"#F2EFE6\">\n\n    <sv:SettingsView HasUnevenRows=\"True\">\n        \n        <sv:Section Title=\"Section\">\n            <sv:LabelCell Title=\"Hoge\" />\n        </sv:Section>\n        \n        <sv:Section Title=\"DynamicSection\">\n            <sv:Section.FooterView>\n                <VerticalStackLayout Spacing=\"4\"\n                                     BindableLayout.ItemsSource=\"{Binding Items}\">\n                    <BindableLayout.EmptyView>\n                        \n                        <ActivityIndicator\n                            WidthRequest=\"24\" HeightRequest=\"24\"\n                            IsRunning=\"True\"\n                            Color=\"Red\"\n                            />\n                    </BindableLayout.EmptyView>\n                    <BindableLayout.ItemTemplate>\n                        <DataTemplate x:DataType=\"vm:SampleHeaderModel\">\n                            <Border Stroke=\"Gray\" StrokeThickness=\"1\"\n                                    BackgroundColor=\"White\"\n                                    StrokeShape=\"RoundRectangle 16\"\n                                    Margin=\"16\" Padding=\"12\">\n                            <VerticalStackLayout>\n                                <Label\n                                    Text=\"{Binding HeaderTitle}\"\n                                    FontSize=\"24\"\n                                    FontAttributes=\"Bold\"\n                                    />\n                                <VerticalStackLayout BindableLayout.ItemsSource=\"{Binding DataList}\">\n                                    <BindableLayout.ItemTemplate>\n                                        <DataTemplate x:DataType=\"vm:SampleDataModel\">\n                                            <Grid ColumnDefinitions=\"*,Auto\">\n                                                <Label\n                                                    Grid.Column=\"0\"\n                                                    Text=\"{Binding Title}\"\n                                                    VerticalOptions=\"Center\"\n                                                    />\n                                                <Label\n                                                    Grid.Column=\"1\"\n                                                    Text=\"{Binding Data}\"\n                                                    VerticalOptions=\"Center\"\n                                                    />\n                                            </Grid>\n                                        </DataTemplate>\n                                    </BindableLayout.ItemTemplate>\n                                </VerticalStackLayout>\n                            </VerticalStackLayout>\n                            </Border>\n                        </DataTemplate>\n                    </BindableLayout.ItemTemplate>\n                </VerticalStackLayout>\n            </sv:Section.FooterView>\n        </sv:Section>\n        \n        <sv:Section Title=\"Section\">\n            <sv:LabelCell Title=\"A\" />\n            <sv:LabelCell Title=\"B\" />\n            <sv:LabelCell Title=\"C\" />\n            <sv:LabelCell Title=\"D\" />\n        </sv:Section>\n        \n    </sv:SettingsView>\n</ContentPage>"
  },
  {
    "path": "Sample/Views/DynamicHeaderSizePage.xaml.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Sample.Views;\n\npublic partial class DynamicHeaderSizePage : ContentPage\n{\n    public DynamicHeaderSizePage()\n    {\n        InitializeComponent();\n    }\n}"
  },
  {
    "path": "Sample/Views/HeaderSurveyPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    xmlns:vm=\"clr-namespace:Sample.ViewModels\"\n    x:Class=\"Sample.Views.HeaderSurveyPage\"\n    Title=\"HeaderSurveyPage\"\n    x:DataType=\"vm:HeaderSurveyViewModel\">\n\n    <sv:SettingsView HasUnevenRows=\"True\">\n\n        <sv:Section>\n            <sv:Section.HeaderView>                \n                <StackLayout Orientation=\"Horizontal\" Spacing=\"0\" Grid.Row=\"1\">\n                    <CheckBox IsChecked=\"{Binding IsShow.Value}\" \n                                VerticalOptions=\"Center\" WidthRequest=\"36\"/>\n                    <Label Text=\"Agree\"\n                            TextColor=\"Black\"\n                            FontSize=\"16\"\n                            VerticalOptions=\"Center\" />\n                </StackLayout>\n            </sv:Section.HeaderView>\n        </sv:Section>\n\n        <sv:Section IsVisible=\"{Binding IsShow.Value}\">               \n\n            <sv:Section.HeaderView>\n                <HorizontalStackLayout>\n                    <BoxView WidthRequest=\"30\" HeightRequest=\"30\" Color=\"Red\" />\n                    <Label Text=\"Header\" />\n                </HorizontalStackLayout>\n            </sv:Section.HeaderView>\n\n            <sv:PickerCell  />\n\n        </sv:Section>\n        \n\n        <sv:Section IsVisible=\"{Binding IsShow.Value}\">\n            \n            <sv:Section.HeaderView>\n                <HorizontalStackLayout>\n                    <BoxView WidthRequest=\"30\" HeightRequest=\"30\" Color=\"Bisque\" />\n                    <Label Text=\"Header\" />\n                </HorizontalStackLayout>\n            </sv:Section.HeaderView>\n\n            <sv:Section.FooterView>\n                <ContentView>\n                    <Button \n                            Text=\"Submit\"                                \n                            Margin=\"32,32,32,8\"\n                            />\n                </ContentView>\n            </sv:Section.FooterView>\n\n           <sv:CustomCell IsMeasureOnce=\"False\" IsSelectable=\"False\"\n                            ShowArrowIndicator=\"False\" UseFullSize=\"True\"\n                            >\n                <Grid Padding=\"16,8,24,8\">\n                    <Editor\n                        AutoSize=\"TextChanges\"\n                        MinimumHeightRequest=\"80\"\n                        MaxLength=\"300\"\n                        Placeholder=\"Input your text\"\n                         />\n                </Grid>\n            </sv:CustomCell>\n\n        </sv:Section>\n\n    </sv:SettingsView>\n\n</ContentPage>\n"
  },
  {
    "path": "Sample/Views/HeaderSurveyPage.xaml.cs",
    "content": "﻿namespace Sample.Views;\n\npublic partial class HeaderSurveyPage : ContentPage\n{\n    public HeaderSurveyPage()\n    {\n        InitializeComponent();\n    }\n}\n"
  },
  {
    "path": "Sample/Views/ListPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    x:Class=\"Sample.Views.ListPage\"\n    Title=\"ListPage\">\n\n    <sv:SettingsView ItemsSource=\"{Binding ItemsSource}\">\n        <sv:SettingsView.ItemTemplate>\n            <DataTemplate>\n                <sv:Section>\n                    <sv:Section.HeaderView>\n                        <Grid>\n                            <ImageButton Source=\"ic_close\"\n                                        WidthRequest=\"30\" HeightRequest=\"30\"\n                                        VerticalOptions=\"Center\" HorizontalOptions=\"End\"\n                                        Padding=\"0\" />                           \n                        </Grid>\n                    </sv:Section.HeaderView>\n                        \n                    <sv:LabelCell Title=\"{Binding}\" />\n                </sv:Section>\n            </DataTemplate>\n        </sv:SettingsView.ItemTemplate>     \n\n    </sv:SettingsView>\n   \n</ContentPage>\n"
  },
  {
    "path": "Sample/Views/ListPage.xaml.cs",
    "content": "﻿namespace Sample.Views;\n\npublic partial class ListPage : ContentPage\n{\n    public ListPage()\n    {\n        InitializeComponent();\n    }\n}\n"
  },
  {
    "path": "Sample/Views/MainPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    xmlns:cell=\"clr-namespace:Sample.Views.Cells\"\n    x:Class=\"Sample.Views.MainPage\"    \n    Title=\"SettingsView.Maui\">\n\n    <ContentPage.Resources>\n        <!-- アプリ全体の背景色 -->\n        <Color x:Key=\"AppBackground\">#ffffff</Color>\n        <!-- アクセントカラー -->\n        <Color x:Key=\"AccentColor\">#FFBF00</Color>\n        <!-- 非アクティブカラー -->\n        <Color x:Key=\"DisabledColor\">#E6DAB9</Color>\n        <!-- タイトルテキストカラー -->\n        <Color x:Key=\"TitleTextColor\">#CC9900</Color>\n        <!-- 薄い背景色1 -->\n        <Color x:Key=\"PaleBackColorPrimary\">#F2EFE6</Color>\n        <!-- 薄い背景色2 -->\n        <Color x:Key=\"PaleBackColorSecondary\">#F2EDDA</Color>\n        <!-- 濃いめの文字色 -->\n        <Color x:Key=\"DeepTextColor\">#555555</Color>\n        <!-- 通常文字色 -->\n        <Color x:Key=\"NormalTextColor\">#666666</Color>\n        <!-- 薄い文字色 -->\n        <Color x:Key=\"PaleTextColor\">#999999</Color>\n        <!-- 強調文字色 -->\n        <Color x:Key=\"EmphasisTextColor\">#FF0000</Color>\n\n         <Style TargetType=\"sv:SettingsView\">\n            <Setter Property=\"SeparatorColor\" Value=\"{StaticResource DisabledColor}\" />\n            <Setter Property=\"BackgroundColor\" Value=\"{StaticResource PaleBackColorPrimary}\" />\n            <Setter Property=\"HeaderBackgroundColor\" Value=\"{StaticResource PaleBackColorPrimary}\" />\n            <Setter Property=\"CellBackgroundColor\" Value=\"{StaticResource AppBackground}\" />\n            <Setter Property=\"CellTitleColor\" Value=\"{StaticResource DeepTextColor}\" />\n            <Setter Property=\"CellValueTextColor\" Value=\"{StaticResource NormalTextColor}\" />\n            <Setter Property=\"CellTitleFontSize\" Value=\"17\" />\n            <Setter Property=\"CellValueTextFontSize\" Value=\"12\" />\n            <Setter Property=\"CellDescriptionColor\" Value=\"{StaticResource NormalTextColor}\" />\n            <Setter Property=\"CellDescriptionFontSize\" Value=\"11\" />\n            <Setter Property=\"CellAccentColor\" Value=\"{StaticResource AccentColor}\" />\n            <Setter Property=\"SelectedColor\" Value=\"#50FFBF00\" />\n            <Setter Property=\"HeaderTextColor\" Value=\"{StaticResource TitleTextColor}\" />\n            <Setter Property=\"FooterFontSize\" Value=\"11\" />\n            <Setter Property=\"FooterTextColor\" Value=\"{StaticResource PaleTextColor}\" />\n        </Style>\n    </ContentPage.Resources>\n    <Grid RowDefinitions=\"*,Auto,Auto,Auto\">\n    <sv:SettingsView Grid.Row=\"0\" HasUnevenRows=\"True\" HeaderHeight=\"36\" HeaderPadding=\"14,0,0,6\" HeaderTextVerticalAlign=\"End\" FooterPadding=\"14,4,4,6\"                   ShowArrowIndicatorForAndroid=\"True\" \n        >\n     \n\t\t<sv:Section FooterText=\"This is a footer. optionaly you can write here.\">\n            \n            <sv:CommandCell IconSource=\"dotnet_bot\" IconSize=\"60,60\" IconRadius=\"30\" Title=\"Xam Xamarin\" Height=\"80\"\n                Description=\"hoge@fuga.com\" Command=\"{Binding ToProfileCommand}\" KeepSelectedUntilBack=\"False\"\n                IgnoreUseDescriptionAsValue=\"true\" \n            />\n\t\t</sv:Section>\n\n        <sv:Section Title=\"Test\">\n            <sv:CustomCell x:Name=\"testCell\">\n                <Grid Padding=\"16\" x:Name=\"grid\">\n                    <Label Text=\"{Binding Content.Value}\" LineBreakMode=\"CharacterWrap\" x:Name=\"innerLabel\" />\n                </Grid>\n            </sv:CustomCell>\n            <!--<sv:ButtonCell Title=\"Add\" Command=\"{Binding AddContentCommand}\" />\n            <sv:ButtonCell Title=\"Clear\" Command=\"{Binding ClearContentCommand}\" />-->\n        </sv:Section>\n\n        <sv:Section Title=\"LabelCell\">\n            <sv:LabelCell Title=\"Storage\" IconSource=\"dotnet_bot\" ValueText=\"3,065MB\" Description=\"{Binding Description.Value}\" />\n        </sv:Section>\n\n        <sv:Section Title=\"CheckableCell\">\n            <sv:SwitchCell Title=\"Switch\" On=\"true\" \n                Description=\"This is description. you can write detail explanation of the item here. long text wrap automatically.\" />\n            <sv:CheckboxCell Title=\"Checkbox\" Checked=\"true\" />\n        </sv:Section>\n\n        <sv:Section Title=\"MultiPicker\" FooterText=\"This is a multi select picker. you are free to select items until MaxSelectedNumber.\">\n            <sv:PickerCell Title=\"Favorites\" ItemsSource=\"{Binding ItemsSource}\" DisplayMember=\"Name\" MaxSelectedNumber=\"3\" UsePickToClose=\"True\" \n            SelectedItems=\"{Binding SelectedItems}\" KeepSelectedUntilBack=\"true\" PageTitle=\"select 3 items\" /> \n        </sv:Section>\n\n        <sv:Section Title=\"Picker 4 Brothers\">\n            <sv:NumberPickerCell Title=\"NumberPicker\" Min=\"0\" Max=\"99\" Number=\"15\" Unit=\"px\" PickerTitle=\"Select number\" />\n            <sv:TimePickerCell Title=\"TimePicker\" Format=\"HH:mm\" Time=\"15:30\" PickerTitle=\"Select time\" />\n            <sv:DatePickerCell Title=\"DatePicker\" Format=\"yyyy/MM/dd (ddd)\" Date=\"2017/11/11\" MinimumDate=\"2015/11/10\" MaximumDate=\"2025/12/31\" TodayText=\"Today's date\" IsAndroidSpinnerStyle=\"True\" />\n            <sv:TextPickerCell Title=\"TextPicker\" Items=\"{Binding TextItems}\" SelectedItem=\"{Binding SelectedText.Value}\" IsCircularPicker=\"False\" />\n        </sv:Section>  \n        \n        <sv:Section Title=\"RadioCell\" FooterText=\"You can select either TypeA or TypeB.\" sv:RadioCell.SelectedValue=\"1\">\n            <sv:RadioCell Title=\"TypeA\" Value=\"1\" />\n            <sv:RadioCell Title=\"TypeB\" Value=\"2\" />\n        </sv:Section>\n\n        <sv:Section Title=\"Input\" IsVisible=\"{Binding InputSectionVisible.Value}\">\n            <sv:EntryCell Title=\"EntryCell\" ValueText=\"{Binding InputText.Value}\" Placeholder=\"Input text\" TextAlignment=\"End\" HintText=\"{Binding InputError.Value}\" Keyboard=\"Default\" ShowDoneButtonOnIOS=\"True\" />\n        </sv:Section>\n\n        <sv:Section>\n            <sv:Section.HeaderView>\n                <FlexLayout Direction=\"Row\" JustifyContent=\"SpaceBetween\" AlignItems=\"End\" HeightRequest=\"50\" Padding=\"10,0,10,6\">                    \n                    <Label Text=\"CustomHeaderView\" TextColor=\"DeepSkyBlue\" />\n                    <ImageButton Source=\"icon.png\" WidthRequest=\"20\" HeightRequest=\"20\" />\n                </FlexLayout>                \n            </sv:Section.HeaderView>\n            <sv:Section.FooterView>\n                <Label Text=\"CustomFooterView. \" TextColor=\"DeepSkyBlue\" Padding=\"10,6,10,0\" />\n            </sv:Section.FooterView>\n            <cell:SliderCell Value=\"0.5\" HintText=\"CustomCell\" />            \n        </sv:Section>       \n\n        <sv:Section Title=\"ButtonCell\" FooterText=\"Change input section visibility.\">\n            <sv:ButtonCell Title=\"Toggle Section\" TitleColor=\"{StaticResource TitleTextColor}\" TitleAlignment=\"Center\" Command=\"{Binding SectionToggleCommand}\" />\n        </sv:Section>\n\t</sv:SettingsView>\n        <Button Grid.Row=\"1\" Text=\"Add\" Command=\"{Binding AddContentCommand}\" />\n        <Button Grid.Row=\"2\" Text=\"Clear\" Command=\"{Binding ClearContentCommand}\" />\n        <Button Grid.Row=\"3\" Text=\"Reload\" Clicked=\"Button_Clicked\" />\n    </Grid>\n</ContentPage>\n\n"
  },
  {
    "path": "Sample/Views/MainPage.xaml.cs",
    "content": "﻿using AiForms.Settings;\nusing Sample.ViewModels;\n\nnamespace Sample.Views;\n\npublic partial class MainPage : ContentPage\n{    \n    public MainPage()\n    {\n        InitializeComponent();        \n    }\n\n    protected override void OnBindingContextChanged()\n    {\n        base.OnBindingContextChanged();\n        if(BindingContext is MainViewModel vm)\n        {\n            vm.Content.Subscribe(async _ =>\n            {\n                //await Task.Delay(500);\n                //MainThread.BeginInvokeOnMainThread(() => testCell.Reload());\n                //MainThread.BeginInvokeOnMainThread(() => testCell.Reload());\n                //Dispatcher.DispatchDelayed(TimeSpan.FromMilliseconds(250),()=>testCell.Reload());\n            });            \n        }\n    }\n\n    void Button_Clicked(System.Object sender, System.EventArgs e)\n    {\n        MainThread.BeginInvokeOnMainThread(() => testCell.Reload());\n    }\n}\n\n\n"
  },
  {
    "path": "Sample/Views/MyNavigationPage.cs",
    "content": "﻿using System;\nnamespace Sample.Views\n{\n    public class MyNavigationPage : NavigationPage\n    {\n        public MyNavigationPage()\n        {\n            BarBackgroundColor = Colors.White;\n        }\n\n        public MyNavigationPage(Page root) : base(root)\n        {\n            BarBackgroundColor = Colors.White;\n        }\n    }\n}\n\n"
  },
  {
    "path": "Sample/Views/SurveyPage.xaml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ContentPage \n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n    xmlns:vm=\"clr-namespace:Sample.ViewModels\"\n    x:Class=\"Sample.Views.SurveyPage\"\n    x:DataType=\"vm:SurveyViewModel\">\n\n    <Grid RowDefinitions=\"Auto,*\">\n        <sv:SettingsView Grid.Row=\"1\">\n            \n            <sv:Section Title=\"A\" ItemsSource=\"{Binding ItemsSource}\" IsVisible=\"{Binding IsShow.Value}\">\n                <sv:Section.ItemTemplate>\n                    <DataTemplate x:DataType=\"x:String\">\n                        <sv:CommandCell \n                            HideArrowIndicator=\"True\"\n                            Title=\"{Binding .}\" />\n                    </DataTemplate>\n                </sv:Section.ItemTemplate>\n            </sv:Section>\n            \n            <sv:Section Title=\"B\" ItemsSource=\"{Binding ItemsSource2}\">\n               <sv:Section.ItemTemplate>\n                   <DataTemplate x:DataType=\"x:String\">\n                       <sv:CustomCell>\n                           <Grid ColumnDefinitions=\"*, Auto\">\n                               <Label\n                                   Grid.Column=\"0\"\n                                   Text=\"{Binding .}\"\n                                   FontAttributes=\"Bold\" />\n                               <ImageButton\n                                   Grid.Column=\"1\"\n                                   Source=\"dotnet_bot\"\n                                   WidthRequest=\"24\"\n                                   HeightRequest=\"24\"\n                               />\n                           </Grid>\n                       </sv:CustomCell>\n                   </DataTemplate>\n               </sv:Section.ItemTemplate>\n            </sv:Section>\n            \n            \n        </sv:SettingsView>\n        \n        <Button\n            Grid.Row=\"0\"\n            Text=\"Submit\"\n            Command=\"{Binding SubmitCommand}\"\n            />\n        \n    </Grid>\n    \n</ContentPage>"
  },
  {
    "path": "Sample/Views/SurveyPage.xaml.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Sample.Views;\n\npublic partial class SurveyPage : ContentPage\n{\n    public SurveyPage()\n    {\n        InitializeComponent();\n    }\n}"
  },
  {
    "path": "Sample/Views/TapSurveyPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n             xmlns:sv=\"clr-namespace:AiForms.Settings;assembly=SettingsView\"\n             x:Class=\"Sample.Views.TapSurveyPage\"\n             Title=\"TapSurveyPage\">\n    <sv:SettingsView>\n\n        <sv:Section>\n            <sv:Section.HeaderView>\n                <HorizontalStackLayout>\n                    <Label Text=\"Header\" HeightRequest=\"44\">\n                        <Label.GestureRecognizers>\n                            <TapGestureRecognizer Tapped=\"TapGestureRecognizer_Tapped_3\" />\n                        </Label.GestureRecognizers>\n                    </Label>\n                </HorizontalStackLayout>\n            </sv:Section.HeaderView>\n\n            <sv:Section.FooterView>\n                <HorizontalStackLayout>\n                    <Label Text=\"Footer\" HeightRequest=\"44\">\n                        <Label.GestureRecognizers>\n                            <TapGestureRecognizer Tapped=\"TapGestureRecognizer_Tapped_4\" />\n                        </Label.GestureRecognizers>\n                    </Label>\n                </HorizontalStackLayout>\n            </sv:Section.FooterView>\n\n            <sv:CustomCell IsSelectable=\"True\">\n\n                <Grid ColumnDefinitions=\"*,*,*\">\n                    <StackLayout Grid.Column=\"0\">\n                        <StackLayout.GestureRecognizers>\n                            <TapGestureRecognizer Tapped=\"TapGestureRecognizer_Tapped\" />\n                        </StackLayout.GestureRecognizers>\n                        <Image />\n                        <Label Text=\"A\"\n                               FontAttributes=\"Bold\"\n                               HorizontalOptions=\"Center\"/>\n                    </StackLayout>\n                    <StackLayout Grid.Column=\"1\">\n                        <StackLayout.GestureRecognizers>\n                            <TapGestureRecognizer Tapped=\"TapGestureRecognizer_Tapped_1\" />\n                        </StackLayout.GestureRecognizers>\n                        <Image />\n                        <Label Text=\"B\"\n                               FontAttributes=\"Bold\"\n                               HorizontalOptions=\"Center\"/>\n                    </StackLayout>\n                    <StackLayout Grid.Column=\"2\">\n                        <StackLayout.GestureRecognizers>\n                            <TapGestureRecognizer Tapped=\"TapGestureRecognizer_Tapped_2\" />\n                        </StackLayout.GestureRecognizers>\n                        <Image />\n                        <Label Text=\"C\"\n                               FontAttributes=\"Bold\"\n                               HorizontalOptions=\"Center\"/>\n                    </StackLayout>\n                </Grid>\n\n            </sv:CustomCell>\n\n        </sv:Section>\n\n    </sv:SettingsView>\n</ContentPage>\n"
  },
  {
    "path": "Sample/Views/TapSurveyPage.xaml.cs",
    "content": "﻿namespace Sample.Views;\n\npublic partial class TapSurveyPage : ContentPage\n{\n    public TapSurveyPage()\n    {\n        InitializeComponent();\n    }\n\n    void TapGestureRecognizer_Tapped(System.Object sender, Microsoft.Maui.Controls.TappedEventArgs e)\n    {\n    }\n\n    void TapGestureRecognizer_Tapped_1(System.Object sender, Microsoft.Maui.Controls.TappedEventArgs e)\n    {\n    }\n\n    void TapGestureRecognizer_Tapped_2(System.Object sender, Microsoft.Maui.Controls.TappedEventArgs e)\n    {\n    }\n\n    void TapGestureRecognizer_Tapped_3(System.Object sender, Microsoft.Maui.Controls.TappedEventArgs e)\n    {\n    }\n\n    void TapGestureRecognizer_Tapped_4(System.Object sender, Microsoft.Maui.Controls.TappedEventArgs e)\n    {\n    }\n}\n"
  },
  {
    "path": "SettingsView/BindableBase.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Runtime.CompilerServices;\n\nnamespace AiForms.Settings\n{\n    public abstract class BindableBase : INotifyPropertyChanged\n    {        \n        public event PropertyChangedEventHandler PropertyChanged;\n       \n        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(storage, value)) return false;\n\n            storage = value;\n            RaisePropertyChanged(propertyName);\n\n            return true;\n        }\n        \n        protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(storage, value)) return false;\n\n            storage = value;\n            onChanged?.Invoke();\n            RaisePropertyChanged(propertyName);\n\n            return true;\n        }\n       \n        protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)\n        {\n            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));\n        }\n        \n        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)\n        {\n            PropertyChanged?.Invoke(this, args);\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/CellPropertyChangedEventHandler.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\n\nnamespace AiForms.Settings;\n\r\npublic class CellPropertyChangedEventArgs : PropertyChangedEventArgs\n{\n    public Section Section { get; }\n\n    public CellPropertyChangedEventArgs(string propertyName, Section section) : base(propertyName)\n    {\n        Section = section;\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/ButtonCell.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Button cell.\n/// </summary>\npublic class ButtonCell:CellBase\n{\n\n    private new string Description { get; set; }\n    private new Color DescriptionColor { get; set; }\n    private new double DescriptionFontSize { get; set; }\n\n    /// <summary>\n    /// The title alignment property.\n    /// </summary>\n    public static BindableProperty TitleAlignmentProperty =\n        BindableProperty.Create(\n            nameof(TitleAlignment),\n            typeof(TextAlignment),\n            typeof(ButtonCell),\n            TextAlignment.Center,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the title alignment.\n    /// </summary>\n    /// <value>The title alignment.</value>\n    public TextAlignment TitleAlignment\n    {\n        get { return (TextAlignment)GetValue(TitleAlignmentProperty); }\n        set { SetValue(TitleAlignmentProperty, value); }\n    }\n\n    /// <summary>\n    /// The command property.\n    /// </summary>\n    public static BindableProperty CommandProperty =\n        BindableProperty.Create(\n            nameof(Command),\n            typeof(ICommand),\n            typeof(ButtonCell),\n            default(ICommand),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the command.\n    /// </summary>\n    /// <value>The command.</value>\n    public ICommand Command\n    {\n        get { return (ICommand)GetValue(CommandProperty); }\n        set { SetValue(CommandProperty, value); }\n    }\n\n    /// <summary>\n    /// The command parameter property.\n    /// </summary>\n    public static BindableProperty CommandParameterProperty =\n        BindableProperty.Create(\n            nameof(CommandParameter),\n            typeof(object),\n            typeof(ButtonCell),\n            default(object),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the command parameter.\n    /// </summary>\n    /// <value>The command parameter.</value>\n    public object CommandParameter\n    {\n        get { return (object)GetValue(CommandParameterProperty); }\n        set { SetValue(CommandParameterProperty, value); }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/CellBase.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings;\n\r\npublic class CellBase: Element, IImageSourcePart\n{\n    /// <summary>\n    /// Occurs when tapped.\n    /// </summary>\n    public event EventHandler Tapped;\n    internal void OnTapped()\n    {\n        if (Tapped != null)\n            Tapped(this, EventArgs.Empty);\n    }       \n\n    /// <summary>\n    /// The title property.\n    /// </summary>\n    public static BindableProperty TitleProperty =\n        BindableProperty.Create(\n            nameof(Title),\n            typeof(string),\n            typeof(CellBase),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the title.\n    /// </summary>\n    /// <value>The title.</value>\n    public string Title\n    {\n        get { return (string)GetValue(TitleProperty); }\n        set { SetValue(TitleProperty, value); }\n    }\n\n    /// <summary>\n    /// The title color property.\n    /// </summary>\n    public static BindableProperty TitleColorProperty =\n        BindableProperty.Create(\n            nameof(TitleColor),\n            typeof(Color),\n            typeof(CellBase),\n            KnownColor.Default,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the title.\n    /// </summary>\n    /// <value>The color of the title.</value>\n    public Color TitleColor\n    {\n        get { return (Color)GetValue(TitleColorProperty); }\n        set { SetValue(TitleColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The title font size property.\n    /// </summary>\n    public static BindableProperty TitleFontSizeProperty =\n        BindableProperty.Create(\n            nameof(TitleFontSize),\n            typeof(double),\n            typeof(CellBase),\n            -1.0,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the size of the title font.\n    /// </summary>\n    /// <value>The size of the title font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double TitleFontSize\n    {\n        get { return (double)GetValue(TitleFontSizeProperty); }\n        set { SetValue(TitleFontSizeProperty, value); }\n    }\n\n    public static BindableProperty TitleFontFamilyProperty = BindableProperty.Create(\n        nameof(TitleFontFamily),\n        typeof(string),\n        typeof(CellBase),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string TitleFontFamily\n    {\n        get { return (string)GetValue(TitleFontFamilyProperty); }\n        set { SetValue(TitleFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty TitleFontAttributesProperty = BindableProperty.Create(\n        nameof(TitleFontAttributes),\n        typeof(FontAttributes?),\n        typeof(CellBase),\n        null,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes? TitleFontAttributes\n    {\n        get { return (FontAttributes?)GetValue(TitleFontAttributesProperty); }\n        set { SetValue(TitleFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The description property.\n    /// </summary>\n    public static BindableProperty DescriptionProperty =\n        BindableProperty.Create(\n            nameof(Description),\n            typeof(string),\n            typeof(CellBase),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the description.\n    /// </summary>\n    /// <value>The description.</value>\n    public string Description\n    {\n        get { return (string)GetValue(DescriptionProperty); }\n        set { SetValue(DescriptionProperty, value); }\n    }\n\n    /// <summary>\n    /// The description color property.\n    /// </summary>\n    public static BindableProperty DescriptionColorProperty =\n        BindableProperty.Create(\n            nameof(DescriptionColor),\n            typeof(Color),\n            typeof(CellBase),\n            KnownColor.Default,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the description.\n    /// </summary>\n    /// <value>The color of the description.</value>\n    public Color DescriptionColor\n    {\n        get { return (Color)GetValue(DescriptionColorProperty); }\n        set { SetValue(DescriptionColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The description font size property.\n    /// </summary>\n    public static BindableProperty DescriptionFontSizeProperty =\n        BindableProperty.Create(\n            nameof(DescriptionFontSize),\n            typeof(double),\n            typeof(CellBase),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the size of the description font.\n    /// </summary>\n    /// <value>The size of the description font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double DescriptionFontSize\n    {\n        get { return (double)GetValue(DescriptionFontSizeProperty); }\n        set { SetValue(DescriptionFontSizeProperty, value); }\n    }\n\n    public static BindableProperty DescriptionFontFamilyProperty = BindableProperty.Create(\n        nameof(DescriptionFontFamily),\n        typeof(string),\n        typeof(CellBase),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string DescriptionFontFamily\n    {\n        get { return (string)GetValue(DescriptionFontFamilyProperty); }\n        set { SetValue(DescriptionFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty DescriptionFontAttributesProperty = BindableProperty.Create(\n        nameof(DescriptionFontAttributes),\n        typeof(FontAttributes?),\n        typeof(CellBase),\n        null,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes? DescriptionFontAttributes\n    {\n        get { return (FontAttributes?)GetValue(DescriptionFontAttributesProperty); }\n        set { SetValue(DescriptionFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The hint text property.\n    /// </summary>\n    public static BindableProperty HintTextProperty =\n        BindableProperty.Create(\n            nameof(HintText),\n            typeof(string),\n            typeof(CellBase),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the hint text.\n    /// </summary>\n    /// <value>The hint text.</value>\n    public string HintText\n    {\n        get { return (string)GetValue(HintTextProperty); }\n        set { SetValue(HintTextProperty, value); }\n    }\n\n    /// <summary>\n    /// The hint text color property.\n    /// </summary>\n    public static BindableProperty HintTextColorProperty =\n        BindableProperty.Create(\n            nameof(HintTextColor),\n            typeof(Color),\n            typeof(CellBase),\n            KnownColor.Default,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the hint text.\n    /// </summary>\n    /// <value>The color of the hint text.</value>\n    public Color HintTextColor\n    {\n        get { return (Color)GetValue(HintTextColorProperty); }\n        set { SetValue(HintTextColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The hint font size property.\n    /// </summary>\n    public static BindableProperty HintFontSizeProperty =\n        BindableProperty.Create(\n            nameof(HintFontSize),\n            typeof(double),\n            typeof(CellBase),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the size of the hint font.\n    /// </summary>\n    /// <value>The size of the hint font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double HintFontSize\n    {\n        get { return (double)GetValue(HintFontSizeProperty); }\n        set { SetValue(HintFontSizeProperty, value); }\n    }\n\n    public static BindableProperty HintFontFamilyProperty = BindableProperty.Create(\n        nameof(HintFontFamily),\n        typeof(string),\n        typeof(CellBase),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string HintFontFamily\n    {\n        get { return (string)GetValue(HintFontFamilyProperty); }\n        set { SetValue(HintFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty HintFontAttributesProperty = BindableProperty.Create(\n        nameof(HintFontAttributes),\n        typeof(FontAttributes?),\n        typeof(CellBase),\n        null,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes? HintFontAttributes\n    {\n        get { return (FontAttributes?)GetValue(HintFontAttributesProperty); }\n        set { SetValue(HintFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The background color property.\n    /// </summary>\n    public static BindableProperty BackgroundColorProperty =\n        BindableProperty.Create(\n            nameof(BackgroundColor),\n            typeof(Color),\n            typeof(CellBase),\n            KnownColor.Default,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the background.\n    /// </summary>\n    /// <value>The color of the background.</value>\n    public Color BackgroundColor\n    {\n        get { return (Color)GetValue(BackgroundColorProperty); }\n        set { SetValue(BackgroundColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The icon source property.\n    /// </summary>\n    public static BindableProperty IconSourceProperty =\n        BindableProperty.Create(\n            nameof(IconSource),\n            typeof(ImageSource),\n            typeof(CellBase),\n            default(ImageSource),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the icon source.\n    /// </summary>\n    /// <value>The icon source.</value>\n    [TypeConverter(typeof(ImageSourceConverter))]\n    public ImageSource IconSource\n    {\n        get { return (ImageSource)GetValue(IconSourceProperty); }\n        set { SetValue(IconSourceProperty, value); }\n    }\n\n    /// <summary>\n    /// The icon size property.\n    /// </summary>\n    public static BindableProperty IconSizeProperty =\n        BindableProperty.Create(\n            nameof(IconSize),\n            typeof(Size),\n            typeof(CellBase),\n            default(Size),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the size of the icon.\n    /// </summary>\n    /// <value>The size of the icon.</value>\n    [TypeConverter(typeof(SizeConverter))]\n    public Size IconSize\n    {\n        get { return (Size)GetValue(IconSizeProperty); }\n        set { SetValue(IconSizeProperty, value); }\n    }\n\n    /// <summary>\n    /// The icon radius property.\n    /// </summary>\n    public static BindableProperty IconRadiusProperty =\n        BindableProperty.Create(\n            nameof(IconRadius),\n            typeof(double),\n            typeof(CellBase),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the icon radius.\n    /// </summary>\n    /// <value>The icon radius.</value>\n    public double IconRadius\n    {\n        get { return (double)GetValue(IconRadiusProperty); }\n        set { SetValue(IconRadiusProperty, value); }\n    }\n\n    /// <summary>\n    /// The IsVisible property.\n    /// </summary>\n    public static BindableProperty IsVisibleProperty =\n        BindableProperty.Create(\n            nameof(IsVisible),\n            typeof(bool),\n            typeof(CellBase),\n            true,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"CellBase\"/> is visible.\n    /// </summary>\n    /// <value><c>true</c> if is visible; otherwise, <c>false</c>.</value>\n    public bool IsVisible\n    {\n        get { return (bool)GetValue(IsVisibleProperty); }\n        set { SetValue(IsVisibleProperty, value); }\n    }\n\n    public static BindableProperty HeightProperty = BindableProperty.Create(\n            nameof(Height),\n            typeof(double),\n            typeof(CellBase),\n            -1d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public double Height{\n        get { return (double)GetValue(HeightProperty); }\n        set { SetValue(HeightProperty, value); }\n    }\n\n    public static BindableProperty IsEnabledProperty = BindableProperty.Create(\n            nameof(IsEnabled),\n            typeof(bool),\n            typeof(CellBase),\n            true,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public bool IsEnabled{\n        get { return (bool)GetValue(IsEnabledProperty); }\n        set { SetValue(IsEnabledProperty, value); }\n    }\n\n    /// <summary>\n    /// Gets or sets the section.\n    /// </summary>\n    /// <value>The section.</value>\n    public Section Section { get; set; }\n\n    public IImageSource Source => IconSource;\n    public bool IsLoading { get; set; }\n\n    public bool IsAnimationPlaying { get; set; }\n\n    public void UpdateIsLoading(bool isLoading)\n    {\n        IsLoading = isLoading;\n    }\n\n    public void SetEnabledAppearance(bool isEnabled)\n    {\n        Handler?.Invoke(nameof(SetEnabledAppearance));\n    }\n\n    public virtual void Reload()\n    {\n        if (Section == null)\n        {\n            return;\n        }\n        var index = Section.IndexOf(this);\n        if (index < 0)\n        {\n            return;\n        }\n\n        // raise replase event manually.\n        var temp = Section[index];\n        Section[index] = temp;\n    }\n\n#if ANDROID\n    // This is used by ListView to pass data to the GetCell call\n    // Ideally we can pass these as arguments to ToHandler\n    // But we'll do that in a different smaller more targeted PR\n    internal Android.Views.View ConvertView { get; set; }\n\n#elif IOS || MACCATALYST\n\tinternal UIKit.UITableViewCell ReusableCell { get; set; }\n    internal Queue<UIKit.UITableViewCell> ReusableCellQueue { get; } = new Queue<UIKit.UITableViewCell>();\n\tinternal UIKit.UITableView TableView { get; set; }\n#endif\n\n}\n\n"
  },
  {
    "path": "SettingsView/Cells/CheckboxCell.cs",
    "content": "﻿using System;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Checkbox cell.\n/// </summary>\npublic class CheckboxCell:CellBase\n{\n    /// <summary>\n    /// The checked property.\n    /// </summary>\n    public static BindableProperty CheckedProperty =\n        BindableProperty.Create(\n            nameof(Checked),\n            typeof(bool),\n            typeof(CheckboxCell),\n            default(bool),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.CheckboxCell\"/> is checked.\n    /// </summary>\n    /// <value><c>true</c> if checked; otherwise, <c>false</c>.</value>\n    public bool Checked {\n        get { return (bool)GetValue(CheckedProperty); }\n        set { SetValue(CheckedProperty, value); }\n    }\n\n    /// <summary>\n    /// The accent color property.\n    /// </summary>\n    public static BindableProperty AccentColorProperty =\n        BindableProperty.Create(\n            nameof(AccentColor),\n            typeof(Color),\n            typeof(CheckboxCell),\n            default(Color),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the accent.\n    /// </summary>\n    /// <value>The color of the accent.</value>\n    public Color AccentColor {\n        get { return (Color)GetValue(AccentColorProperty); }\n        set { SetValue(AccentColorProperty, value); }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/CommandCell.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Command cell.\n/// </summary>\npublic class CommandCell:LabelCell\n{\n    /// <summary>\n    /// The command property.\n    /// </summary>\n    public static BindableProperty CommandProperty =\n        BindableProperty.Create(\n            nameof(Command),\n            typeof(ICommand),\n            typeof(CommandCell),\n            default(ICommand),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the command.\n    /// </summary>\n    /// <value>The command.</value>\n    public ICommand Command {\n        get { return (ICommand)GetValue(CommandProperty); }\n        set { SetValue(CommandProperty, value); }\n    }\n\n    /// <summary>\n    /// The command parameter property.\n    /// </summary>\n    public static BindableProperty CommandParameterProperty =\n        BindableProperty.Create(\n            nameof(CommandParameter),\n            typeof(object),\n            typeof(CommandCell),\n            default(object),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the command parameter.\n    /// </summary>\n    /// <value>The command parameter.</value>\n    public object CommandParameter {\n        get { return (object)GetValue(CommandParameterProperty); }\n        set { SetValue(CommandParameterProperty, value); }\n    }\n\n    /// <summary>\n    /// The keep selected until back property.\n    /// </summary>\n    public static BindableProperty KeepSelectedUntilBackProperty =\n        BindableProperty.Create(\n            nameof(KeepSelectedUntilBack),\n            typeof(bool),\n            typeof(CommandCell),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.CommandCell\"/> keep selected\n    /// until back.\n    /// </summary>\n    /// <value><c>true</c> if keep selected until back; otherwise, <c>false</c>.</value>\n    public bool KeepSelectedUntilBack {\n        get { return (bool)GetValue(KeepSelectedUntilBackProperty); }\n        set { SetValue(KeepSelectedUntilBackProperty, value); }\n    }\n\n    public static BindableProperty HideArrowIndicatorProperty = BindableProperty.Create(\n        nameof(HideArrowIndicator),\n        typeof(bool),\n        typeof(CommandCell),\n        default(bool),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public bool HideArrowIndicator\n    {\n        get { return (bool)GetValue(HideArrowIndicatorProperty); }\n        set { SetValue(HideArrowIndicatorProperty, value); }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/CustomCell.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Custom cell.\n/// </summary>\n[ContentProperty(\"Content\")]\npublic class CustomCell:CommandCell\n{\n    /// <summary>\n    /// The show arrow indicator property.\n    /// </summary>\n    public static BindableProperty ShowArrowIndicatorProperty =\n        BindableProperty.Create(\n            nameof(ShowArrowIndicator),\n            typeof(bool),\n            typeof(CustomCell),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.CustomCell\"/> show arrow indicator.\n    /// </summary>\n    /// <value><c>true</c> if show arrow indicator; otherwise, <c>false</c>.</value>\n    public bool ShowArrowIndicator {\n        get { return (bool)GetValue(ShowArrowIndicatorProperty); }\n        set { SetValue(ShowArrowIndicatorProperty, value); }\n    }\n\n    /// <summary>\n    /// The content property.\n    /// </summary>\n    public static BindableProperty ContentProperty =\n        BindableProperty.Create(\n            nameof(Content),\n            typeof(View),\n            typeof(CustomCell),\n            default(View),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the content.\n    /// </summary>\n    /// <value>The content.</value>\n    public View Content {\n        get { return (View)GetValue(ContentProperty); }\n        set { SetValue(ContentProperty, value); }\n    }\n\n    /// <summary>\n    /// The is selectable property.\n    /// </summary>\n    public static BindableProperty IsSelectableProperty =\n        BindableProperty.Create(\n            nameof(IsSelectable),\n            typeof(bool),\n            typeof(CustomCell),\n            true,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.CustomCell\"/> is selectable.\n    /// </summary>\n    /// <value><c>true</c> if is selectable; otherwise, <c>false</c>.</value>\n    public bool IsSelectable {\n        get { return (bool)GetValue(IsSelectableProperty); }\n        set { SetValue(IsSelectableProperty, value); }\n    }\n\n    /// <summary>\n    /// The is measure once property.\n    /// </summary>\n    public static BindableProperty IsMeasureOnceProperty =\n        BindableProperty.Create(\n            nameof(IsMeasureOnce),\n            typeof(bool),\n            typeof(CustomCell),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.CustomCell\"/> is measure once.\n    /// </summary>\n    /// <value><c>true</c> if is measure once; otherwise, <c>false</c>.</value>\n    public bool IsMeasureOnce {\n        get { return (bool)GetValue(IsMeasureOnceProperty); }\n        set { SetValue(IsMeasureOnceProperty, value); }\n    }\n\n    /// <summary>\n    /// The use full size property.\n    /// </summary>\n    public static BindableProperty UseFullSizeProperty =\n        BindableProperty.Create(\n            nameof(UseFullSize),\n            typeof(bool),\n            typeof(CustomCell),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.CustomCell\"/> use full size.\n    /// </summary>\n    /// <value><c>true</c> if use full size; otherwise, <c>false</c>.</value>\n    public bool UseFullSize {\n        get { return (bool)GetValue(UseFullSizeProperty); }\n        set { SetValue(UseFullSizeProperty, value); }\n    }\n\n    public static BindableProperty LongCommandProperty =\n        BindableProperty.Create(\n            nameof(LongCommand),\n            typeof(ICommand),\n            typeof(CustomCell),\n            default(ICommand),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public ICommand LongCommand\n    {\n        get { return (ICommand)GetValue(LongCommandProperty); }\n        set { SetValue(LongCommandProperty, value); }\n    }\n\n    /// <summary>\n    /// Ons the binding context changed.\n    /// </summary>\n    protected override void OnBindingContextChanged()\n    {\n        base.OnBindingContextChanged();\n        if(Content != null)\n        {\n            Content.BindingContext = BindingContext;\n        }\n    }\n\n    /// <summary>\n    /// Ons the parent set.\n    /// </summary>\n    protected override void OnParentSet()\n    {\n        base.OnParentSet();\n        if(Content != null)\n        {\n            Content.Parent = Parent;\n        }\n    }\n\n    public void SendLongCommand()\n    {\n        if (LongCommand == null)\n        {\n            return;\n        }\n\n        if (LongCommand.CanExecute(BindingContext))\n        {\n            LongCommand.Execute(BindingContext);\n        }\n    }\n\n    internal bool IsForceLayout = false;\n    public override void Reload()\n    {\n        IsForceLayout = true;\n        base.Reload();\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/DatePickerCell.cs",
    "content": "﻿using System;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Date picker cell.\n/// </summary>\npublic class DatePickerCell:LabelCell\n{\n    /// <summary>\n    /// The date property.\n    /// </summary>\n    public static BindableProperty DateProperty =\n        BindableProperty.Create(\n            nameof(Date),\n            typeof(DateTime?),\n            typeof(DatePickerCell),\n            default(DateTime?),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets the date.\n    /// </summary>\n    /// <value>The date.</value>\n    public DateTime? Date {\n        get { return (DateTime?)GetValue(DateProperty); }\n        set { SetValue(DateProperty, value); }\n    }\n\n    public static BindableProperty InitialDateProperty = BindableProperty.Create(\n        nameof(InitialDate),\n        typeof(DateTime),\n        typeof(DatePickerCell),\n        new DateTime(2000, 1, 1),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public DateTime InitialDate {\n        get { return (DateTime)GetValue(InitialDateProperty); }\n        set { SetValue(InitialDateProperty, value); }\n    }\n\n    /// <summary>\n    /// The maximum date property.\n    /// </summary>\n    public static BindableProperty MaximumDateProperty =\n        BindableProperty.Create(\n            nameof(MaximumDate),\n            typeof(DateTime),\n            typeof(DatePickerCell),\n            new DateTime(2100, 12, 31),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the maximum date.\n    /// </summary>\n    /// <value>The maximum date.</value>\n    public DateTime MaximumDate {\n        get { return (DateTime)GetValue(MaximumDateProperty); }\n        set { SetValue(MaximumDateProperty, value); }\n    }\n\n    /// <summary>\n    /// The minimum date property.\n    /// </summary>\n    public static BindableProperty MinimumDateProperty =\n        BindableProperty.Create(\n            nameof(MinimumDate),\n            typeof(DateTime),\n            typeof(DatePickerCell),\n            new DateTime(1900, 1, 1),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the minimum date.\n    /// </summary>\n    /// <value>The minimum date.</value>\n    public DateTime MinimumDate {\n        get { return (DateTime)GetValue(MinimumDateProperty); }\n        set { SetValue(MinimumDateProperty, value); }\n    }\n\n    /// <summary>\n    /// The format property.\n    /// </summary>\n    public static BindableProperty FormatProperty =\n        BindableProperty.Create(\n            nameof(Format),\n            typeof(string),\n            typeof(DatePickerCell),\n            \"d\",\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the format.\n    /// </summary>\n    /// <value>The format.</value>\n    public string Format {\n        get { return (string)GetValue(FormatProperty); }\n        set { SetValue(FormatProperty, value); }\n    }\n\n    /// <summary>\n    /// The today text property.\n    /// </summary>\n    public static BindableProperty TodayTextProperty =\n        BindableProperty.Create(\n            nameof(TodayText),\n            typeof(string),\n            typeof(DatePickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the today text.\n    /// </summary>\n    /// <value>The today text.</value>\n    public string TodayText {\n        get { return (string)GetValue(TodayTextProperty); }\n        set { SetValue(TodayTextProperty, value); }\n    }\n\n    public static BindableProperty IsAndroidSpinnerStyleProperty = BindableProperty.Create(\n        nameof(IsAndroidSpinnerStyle),\n        typeof(bool),\n        typeof(DatePickerCell),\n        default(bool),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public bool IsAndroidSpinnerStyle {\n        get { return (bool)GetValue(IsAndroidSpinnerStyleProperty); }\n        set { SetValue(IsAndroidSpinnerStyleProperty, value); }\n    }\n\n    public static BindableProperty AndroidButtonColorProperty = BindableProperty.Create(\n        nameof(AndroidButtonColor),\n        typeof(Color),\n        typeof(DatePickerCell),\n        default(Color),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public Color AndroidButtonColor {\n        get { return (Color)GetValue(AndroidButtonColorProperty); }\n        set { SetValue(AndroidButtonColorProperty, value); }\n    }\n\n    private new string ValueText { get; set; }\n}\n"
  },
  {
    "path": "SettingsView/Cells/EntryCell.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing System.Windows.Input;\nusing Microsoft.Maui.Converters;\n\nnamespace AiForms.Settings;\n\n/// <summary>\n/// Entry cell.\n/// </summary>\npublic class EntryCell:CellBase,IEntryCellController\n{\n    /// <summary>\n    /// The value text property.\n    /// </summary>\n    public static BindableProperty ValueTextProperty =\n        BindableProperty.Create(\n            nameof(ValueText),\n            typeof(string),\n            typeof(EntryCell),\n            default(string),\n            defaultBindingMode: BindingMode.TwoWay,\n            propertyChanging:ValueTextPropertyChanging\n\n        );\n\n    static void  ValueTextPropertyChanging(BindableObject bindable, object oldValue, object newValue)\n    {\n        var maxlength = (int)bindable.GetValue(MaxLengthProperty);\n        if (maxlength < 0) return;\n\n        var newString = newValue?.ToString() ?? string.Empty;\n        if (newString.Length > maxlength) {\n            var oldString = oldValue?.ToString() ?? string.Empty;\n            if(oldString.Length > maxlength){\n                var trimStr = oldString.Substring(0, maxlength);\n                bindable.SetValue(ValueTextProperty, trimStr);\n            }\n            else{\n                bindable.SetValue(ValueTextProperty, oldString);\n            }\n           \n        }\n    }\n\n    /// <summary>\n    /// Gets or sets the value text.\n    /// </summary>\n    /// <value>The value text.</value>\n    public string ValueText {\n        get { return (string)GetValue(ValueTextProperty); }\n        set { SetValue(ValueTextProperty, value); }\n    }\n\n    /// <summary>\n    /// The max length property.\n    /// </summary>\n    public static BindableProperty MaxLengthProperty =\n        BindableProperty.Create(\n            nameof(MaxLength),\n            typeof(int),\n            typeof(EntryCell),\n            -1,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the length of the max.\n    /// </summary>\n    /// <value>The length of the max.</value>\n    public int MaxLength {\n        get { return (int)GetValue(MaxLengthProperty); }\n        set { SetValue(MaxLengthProperty, value); }\n    }\n\n    /// <summary>\n    /// The value text color property.\n    /// </summary>\n    public static BindableProperty ValueTextColorProperty =\n        BindableProperty.Create(\n            nameof(ValueTextColor),\n            typeof(Color),\n            typeof(EntryCell),\n            default(Color),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the value text.\n    /// </summary>\n    /// <value>The color of the value text.</value>\n    public Color ValueTextColor {\n        get { return (Color)GetValue(ValueTextColorProperty); }\n        set { SetValue(ValueTextColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The value text font size property.\n    /// </summary>\n    public static BindableProperty ValueTextFontSizeProperty =\n        BindableProperty.Create(\n            nameof(ValueTextFontSize),\n            typeof(double),\n            typeof(EntryCell),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the size of the value text font.\n    /// </summary>\n    /// <value>The size of the value text font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double ValueTextFontSize {\n        get { return (double)GetValue(ValueTextFontSizeProperty); }\n        set { SetValue(ValueTextFontSizeProperty, value); }\n    }\n\n    public static BindableProperty ValueTextFontFamilyProperty = BindableProperty.Create(\n        nameof(ValueTextFontFamily),\n        typeof(string),\n        typeof(EntryCell),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string ValueTextFontFamily {\n        get { return (string)GetValue(ValueTextFontFamilyProperty); }\n        set { SetValue(ValueTextFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty ValueTextFontAttributesProperty = BindableProperty.Create(\n        nameof(ValueTextFontAttributes),\n        typeof(FontAttributes?),\n        typeof(EntryCell),\n        null,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes? ValueTextFontAttributes {\n        get { return (FontAttributes?)GetValue(ValueTextFontAttributesProperty); }\n        set { SetValue(ValueTextFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The keyboard property.\n    /// </summary>\n    public static BindableProperty KeyboardProperty =\n        BindableProperty.Create(\n            nameof(Keyboard),\n            typeof(Keyboard),\n            typeof(EntryCell),\n            Keyboard.Default,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the keyboard.\n    /// </summary>\n    /// <value>The keyboard.</value>\n    [TypeConverter(typeof(KeyboardTypeConverter))]\n    public Keyboard Keyboard {\n        get { return (Keyboard)GetValue(KeyboardProperty); }\n        set { SetValue(KeyboardProperty, value); }\n    }\n\n    /// <summary>\n    /// Occurs when completed.\n    /// </summary>\n    public event EventHandler Completed;\n    /// <summary>\n    /// Sends the completed.\n    /// </summary>\n    public void SendCompleted() \n    {\n        Completed?.Invoke(this, EventArgs.Empty);\n        if(CompletedCommand != null)\n        {\n            if(CompletedCommand.CanExecute(null)) \n            {\n                CompletedCommand.Execute(null);\n            }\n        }           \n    }\n\n    /// <summary>\n    /// The completed command property.\n    /// </summary>\n    public static BindableProperty CompletedCommandProperty =\n        BindableProperty.Create(\n            nameof(CompletedCommand),\n            typeof(ICommand),\n            typeof(EntryCell),\n            default(ICommand),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the completed command.\n    /// </summary>\n    /// <value>The completed command.</value>\n    public ICommand CompletedCommand {\n        get { return (ICommand)GetValue(CompletedCommandProperty); }\n        set { SetValue(CompletedCommandProperty, value); }\n    }\n\n    /// <summary>\n    /// The placeholder property.\n    /// </summary>\n    public static BindableProperty PlaceholderProperty =\n        BindableProperty.Create(\n            nameof(Placeholder),\n            typeof(string),\n            typeof(EntryCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the placeholder.\n    /// </summary>\n    /// <value>The placeholder.</value>\n    public string Placeholder {\n        get { return (string)GetValue(PlaceholderProperty); }\n        set { SetValue(PlaceholderProperty, value); }\n    }\n\n    public static BindableProperty PlaceholderColorProperty = BindableProperty.Create(\n        nameof(PlaceholderColor),\n        typeof(Color),\n        typeof(EntryCell),\n        default(Color),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public Color PlaceholderColor {\n        get { return (Color)GetValue(PlaceholderColorProperty); }\n        set { SetValue(PlaceholderColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The text alignment property.\n    /// </summary>\n    public static BindableProperty TextAlignmentProperty =\n        BindableProperty.Create(\n            nameof(TextAlignment),\n            typeof(TextAlignment),\n            typeof(EntryCell),\n            TextAlignment.End,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the text alignment.\n    /// </summary>\n    /// <value>The text alignment.</value>\n    public TextAlignment TextAlignment\n    {\n        get { return (TextAlignment)GetValue(TextAlignmentProperty); }\n        set { SetValue(TextAlignmentProperty, value); }\n    }\n\n    /// <summary>\n    /// The accent color property.\n    /// </summary>\n    public static BindableProperty AccentColorProperty =\n        BindableProperty.Create(\n            nameof(AccentColor),\n            typeof(Color),\n            typeof(EntryCell),\n            default(Color),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the accent.\n    /// </summary>\n    /// <value>The color of the accent.</value>\n    public Color AccentColor {\n        get { return (Color)GetValue(AccentColorProperty); }\n        set { SetValue(AccentColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The is password property.\n    /// </summary>\n    public static BindableProperty IsPasswordProperty =\n        BindableProperty.Create(\n            nameof(IsPassword),\n            typeof(bool),\n            typeof(EntryCell),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.EntryCell\"/> is password.\n    /// </summary>\n    /// <value><c>true</c> if is password; otherwise, <c>false</c>.</value>\n    public bool IsPassword {\n        get { return (bool)GetValue(IsPasswordProperty); }\n        set { SetValue(IsPasswordProperty, value); }\n    }\n\n    public static BindableProperty ShowDoneButtonOnIOSProperty =\n        BindableProperty.Create(\n            nameof(ShowDoneButtonOnIOS),\n            typeof(bool),\n            typeof(EntryCell),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public bool ShowDoneButtonOnIOS\n    {\n        get { return (bool)GetValue(ShowDoneButtonOnIOSProperty); }\n        set { SetValue(ShowDoneButtonOnIOSProperty, value); }\n    }\n\n    internal event EventHandler Focused;\n    /// <summary>\n    /// Sets the focus.\n    /// </summary>\n    public void SetFocus()\n    {\n        Focused?.Invoke(this,EventArgs.Empty);\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/LabelCell.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Label cell.\n/// </summary>\npublic class LabelCell:CellBase\n{\n    /// <summary>\n    /// The value text property.\n    /// </summary>\n    public static BindableProperty ValueTextProperty =\n        BindableProperty.Create(\n            nameof(ValueText),\n            typeof(string),\n            typeof(LabelCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the value text.\n    /// </summary>\n    /// <value>The value text.</value>\n    public string ValueText {\n        get { return (string)GetValue(ValueTextProperty); }\n        set { SetValue(ValueTextProperty, value); }\n    }\n\n    /// <summary>\n    /// The value text color property.\n    /// </summary>\n    public static BindableProperty ValueTextColorProperty =\n        BindableProperty.Create(\n            nameof(ValueTextColor),\n            typeof(Color),\n            typeof(LabelCell),\n            KnownColor.Default,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the value text.\n    /// </summary>\n    /// <value>The color of the value text.</value>\n    public Color ValueTextColor {\n        get { return (Color)GetValue(ValueTextColorProperty); }\n        set { SetValue(ValueTextColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The value text font size property.\n    /// </summary>\n    public static BindableProperty ValueTextFontSizeProperty =\n        BindableProperty.Create(\n            nameof(ValueTextFontSize),\n            typeof(double),\n            typeof(LabelCell),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the size of the value text font.\n    /// </summary>\n    /// <value>The size of the value text font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double ValueTextFontSize {\n        get { return (double)GetValue(ValueTextFontSizeProperty); }\n        set { SetValue(ValueTextFontSizeProperty, value); }\n    }\n\n    public static BindableProperty ValueTextFontFamilyProperty = BindableProperty.Create(\n        nameof(ValueTextFontFamily),\n        typeof(string),\n        typeof(LabelCell),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string ValueTextFontFamily {\n        get { return (string)GetValue(ValueTextFontFamilyProperty); }\n        set { SetValue(ValueTextFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty ValueTextFontAttributesProperty = BindableProperty.Create(\n        nameof(ValueTextFontAttributes),\n        typeof(FontAttributes?),\n        typeof(LabelCell),\n        null,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes? ValueTextFontAttributes {\n        get { return (FontAttributes?)GetValue(ValueTextFontAttributesProperty); }\n        set { SetValue(ValueTextFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The ignore use description as value property.\n    /// </summary>\n    public static BindableProperty IgnoreUseDescriptionAsValueProperty =\n        BindableProperty.Create(\n            nameof(IgnoreUseDescriptionAsValue),\n            typeof(bool),\n            typeof(LabelCell),\n            false,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.LabelCell\"/> ignore use\n    /// description as value.\n    /// </summary>\n    /// <value><c>true</c> if ignore use description as value; otherwise, <c>false</c>.</value>\n    public bool IgnoreUseDescriptionAsValue\n    {\n        get { return (bool)GetValue(IgnoreUseDescriptionAsValueProperty); }\n        set { SetValue(IgnoreUseDescriptionAsValueProperty, value); }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/NumberPickerCell.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Number picker cell.\n/// </summary>\npublic class NumberPickerCell:LabelCell\n{\n    /// <summary>\n    /// The number property.\n    /// </summary>\n    public static BindableProperty NumberProperty =\n        BindableProperty.Create(\n            nameof(Number),\n            typeof(int?),\n            typeof(NumberPickerCell),\n            null,\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets the number.\n    /// </summary>\n    /// <value>The number.</value>\n    public int? Number {\n        get { return (int?)GetValue(NumberProperty); }\n        set { SetValue(NumberProperty, value); }\n    }\n\n    /// <summary>\n    /// The minimum property.\n    /// </summary>\n    public static BindableProperty MinProperty =\n        BindableProperty.Create(\n            nameof(Min),\n            typeof(int),\n            typeof(NumberPickerCell),\n            0,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the minimum.\n    /// </summary>\n    /// <value>The minimum.</value>\n    public int Min {\n        get { return (int)GetValue(MinProperty); }\n        set { SetValue(MinProperty, value); }\n    }\n\n    /// <summary>\n    /// The max property.\n    /// </summary>\n    public static BindableProperty MaxProperty =\n        BindableProperty.Create(\n            nameof(Max),\n            typeof(int),\n            typeof(NumberPickerCell),\n            9999,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the max.\n    /// </summary>\n    /// <value>The max.</value>\n    public int Max {\n        get { return (int)GetValue(MaxProperty); }\n        set { SetValue(MaxProperty, value); }\n    }\n\n    /// <summary>\n    /// The picker title property.\n    /// </summary>\n    public static BindableProperty PickerTitleProperty =\n        BindableProperty.Create(\n            nameof(PickerTitle),\n            typeof(string),\n            typeof(NumberPickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the picker title.\n    /// </summary>\n    /// <value>The picker title.</value>\n    public string PickerTitle {\n        get { return (string)GetValue(PickerTitleProperty); }\n        set { SetValue(PickerTitleProperty, value); }\n    }\n\n    /// <summary>\n    /// The selected command property.\n    /// </summary>\n    public static BindableProperty SelectedCommandProperty =\n        BindableProperty.Create(\n            nameof(SelectedCommand),\n            typeof(ICommand),\n            typeof(NumberPickerCell),\n            default(ICommand),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the selected command.\n    /// </summary>\n    /// <value>The selected command.</value>\n    public ICommand SelectedCommand {\n        get { return (ICommand)GetValue(SelectedCommandProperty); }\n        set { SetValue(SelectedCommandProperty, value); }\n    }\n\n    public static BindableProperty UnitProperty\n        = BindableProperty.Create\n            (nameof (Unit), \n            typeof (string),\n            typeof (NumberPickerCell), \n            \"\", \n            defaultBindingMode: BindingMode.OneWay\n    );\n    \n    public string Unit\n    {\n        get { return (string) this.GetValue(UnitProperty); }\n        set { this.SetValue(UnitProperty, value); }\n    }\n\n    private new string ValueText { get; set; }\n}\n"
  },
  {
    "path": "SettingsView/Cells/PickerCell.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.Collections.Specialized;\nusing System.Linq;\nusing System.Linq.Expressions;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Windows.Input;\nusing AiForms.Settings.Pages;\nusing Microsoft.Maui.Controls;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Picker cell.\n/// </summary>\npublic class PickerCell : CommandCell\n{\n    /// <summary>\n    /// The page title property.\n    /// </summary>\n    public static BindableProperty PageTitleProperty =\n        BindableProperty.Create(\n            nameof(PageTitle),\n            typeof(string),\n            typeof(PickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the page title.\n    /// </summary>\n    /// <value>The page title.</value>\n    public string PageTitle {\n        get { return (string)GetValue(PageTitleProperty); }\n        set { SetValue(PageTitleProperty, value); }\n    }\n\n    /// <summary>\n    /// The items source property.\n    /// </summary>\n    public static BindableProperty ItemsSourceProperty =\n        BindableProperty.Create(\n            nameof(ItemsSource),\n            typeof(IList),\n            typeof(PickerCell),\n            default(IList),\n            defaultBindingMode: BindingMode.OneWay,\n            propertyChanging: ItemsSourceChanging\n        );\n\n    /// <summary>\n    /// Gets or sets the items source.\n    /// </summary>\n    /// <value>The items source.</value>\n    public IList ItemsSource {\n        get { return (IList)GetValue(ItemsSourceProperty); }\n        set { SetValue(ItemsSourceProperty, value); }\n    }\n\n    /// <summary>\n    /// The display member property.\n    /// </summary>\n    public static BindableProperty DisplayMemberProperty =\n        BindableProperty.Create(\n            nameof(DisplayMember),\n            typeof(string),\n            typeof(PickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the display member.\n    /// </summary>\n    /// <value>The display member.</value>\n    public string DisplayMember {\n        get { return (string)GetValue(DisplayMemberProperty); }\n        set { SetValue(DisplayMemberProperty, value); }\n    }\n\n    /// <summary>\n    /// The sub display member property.\n    /// </summary>\n    public static BindableProperty SubDisplayMemberProperty =\n        BindableProperty.Create(\n            nameof(SubDisplayMember),\n            typeof(string),\n            typeof(PickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the sub display member.\n    /// </summary>\n    /// <value>The sub display member.</value>\n    public string SubDisplayMember {\n        get { return (string)GetValue(SubDisplayMemberProperty); }\n        set { SetValue(SubDisplayMemberProperty, value); }\n    }\n\n    /// <summary>\n    /// The selected items property.\n    /// </summary>\n    public static BindableProperty SelectedItemsProperty =\n        BindableProperty.Create(\n            nameof(SelectedItems),\n            typeof(IList),\n            typeof(PickerCell),\n            default(IList),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets the selected items.\n    /// </summary>\n    /// <value>The selected items.</value>\n    public IList SelectedItems {\n        get { return (IList)GetValue(SelectedItemsProperty); }\n        set { SetValue(SelectedItemsProperty, value); }\n    }\n\n    /// <summary>\n    /// The selected item property.\n    /// </summary>\n    public static BindableProperty SelectedItemProperty =\n        BindableProperty.Create(\n            nameof(SelectedItem),\n            typeof(object),\n            typeof(PickerCell),\n            default(object),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets the selected item.\n    /// </summary>\n    /// <value>The selected item.</value>\n    public object SelectedItem {\n        get { return GetValue(SelectedItemProperty); }\n        set { SetValue(SelectedItemProperty, value); }\n    }\n\n    /// <summary>\n    /// The selection mode property.\n    /// </summary>\n    public static BindableProperty SelectionModeProperty =\n        BindableProperty.Create(\n            nameof(SelectionMode),\n            typeof(SelectionMode),\n            typeof(PickerCell),\n            SelectionMode.Multiple,\n            defaultBindingMode: BindingMode.OneWay,\n            propertyChanged: (bindable, oldValue, newValue) => {\n                if ((SelectionMode)newValue == SelectionMode.Single)\n                {\n                    bindable.SetValue(MaxSelectedNumberProperty, 1);\n                }\n            }\n        );\n\n    /// <summary>\n    /// Gets or sets the selection mode.\n    /// </summary>\n    /// <value>The selection mode.</value>\n    public SelectionMode SelectionMode {\n        get { return (SelectionMode)GetValue(SelectionModeProperty); }\n        set { SetValue(SelectionModeProperty, value); }\n    }\n\n    /// <summary>\n    /// The max selected number property.\n    /// </summary>\n    public static BindableProperty MaxSelectedNumberProperty =\n        BindableProperty.Create(\n            nameof(MaxSelectedNumber),\n            typeof(int),\n            typeof(PickerCell),\n            0,\n            defaultBindingMode: BindingMode.OneWay,\n            coerceValue: (bindable, value) => {\n                return (SelectionMode)bindable.GetValue(SelectionModeProperty) == SelectionMode.Single\n                    ? 1 : value;\n            }\n        );\n\n    /// <summary>\n    /// Gets or sets the max selected number.\n    /// </summary>\n    /// <value>The max selected number.</value>\n    public int MaxSelectedNumber {\n        get { return (int)GetValue(MaxSelectedNumberProperty); }\n        set { SetValue(MaxSelectedNumberProperty, value); }\n    }    \n\n    /// <summary>\n    /// The accent color property.\n    /// </summary>\n    public static BindableProperty AccentColorProperty =\n        BindableProperty.Create(\n            nameof(AccentColor),\n            typeof(Color),\n            typeof(PickerCell),\n            default(Color),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the accent.\n    /// </summary>\n    /// <value>The color of the accent.</value>\n    public Color AccentColor {\n        get { return (Color)GetValue(AccentColorProperty); }\n        set { SetValue(AccentColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The selected items order key property.\n    /// </summary>\n    public static BindableProperty SelectedItemsOrderKeyProperty =\n        BindableProperty.Create(\n            nameof(SelectedItemsOrderKey),\n            typeof(string),\n            typeof(PickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the selected items order key.\n    /// </summary>\n    /// <value>The selected items order key.</value>\n    public string SelectedItemsOrderKey {\n        get { return (string)GetValue(SelectedItemsOrderKeyProperty); }\n        set { SetValue(SelectedItemsOrderKeyProperty, value); }\n    }\n\n    /// <summary>\n    /// The selected command property.\n    /// </summary>\n    public static BindableProperty SelectedCommandProperty =\n        BindableProperty.Create(\n            nameof(SelectedCommand),\n            typeof(ICommand),\n            typeof(PickerCell),\n            default(ICommand),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the selected command.\n    /// </summary>\n    /// <value>The selected command.</value>\n    public ICommand SelectedCommand {\n        get { return (ICommand)GetValue(SelectedCommandProperty); }\n        set { SetValue(SelectedCommandProperty, value); }\n    }\n\n    /// <summary>\n    /// The use natural sort property.\n    /// </summary>\n    public static BindableProperty UseNaturalSortProperty =\n        BindableProperty.Create(\n            nameof(UseNaturalSort),\n            typeof(bool),\n            typeof(PickerCell),\n            false,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.PickerCell\"/> use natural sort.\n    /// </summary>\n    /// <value><c>true</c> if use natural sort; otherwise, <c>false</c>.</value>\n    public bool UseNaturalSort {\n        get { return (bool)GetValue(UseNaturalSortProperty); }\n        set { SetValue(UseNaturalSortProperty, value); }\n    }\n\n    /// <summary>\n    /// The use auto value text property.\n    /// </summary>\n    public static BindableProperty UseAutoValueTextProperty =\n        BindableProperty.Create(\n            nameof(UseAutoValueText),\n            typeof(bool),\n            typeof(PickerCell),\n            true,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.PickerCell\"/> use auto value text.\n    /// </summary>\n    /// <value><c>true</c> if use auto value text; otherwise, <c>false</c>.</value>\n    public bool UseAutoValueText {\n        get { return (bool)GetValue(UseAutoValueTextProperty); }\n        set { SetValue(UseAutoValueTextProperty, value); }\n    }\n\n    /// <summary>\n    /// The use pick to close property.\n    /// </summary>\n    public static BindableProperty UsePickToCloseProperty =\n        BindableProperty.Create(\n            nameof(UsePickToClose),\n            typeof(bool),\n            typeof(PickerCell),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.PickerCell\"/> use pick to close.\n    /// </summary>\n    /// <value><c>true</c> if use pick to close; otherwise, <c>false</c>.</value>\n    public bool UsePickToClose {\n        get { return (bool)GetValue(UsePickToCloseProperty); }\n        set { SetValue(UsePickToCloseProperty, value); }\n    }\n\n    /// <summary>\n    /// The padding property.\n    /// </summary>\n    public static BindableProperty PaddingProperty =\n        BindableProperty.Create(\n            nameof(Padding),\n            typeof(Thickness),\n            typeof(PickerCell),\n            new Thickness(0, 0, 0, 0),\n            defaultBindingMode: BindingMode.OneWay\n        );\n    \n    /// <summary>\n    /// Gets or sets the padding property.\n    /// </summary>\n    /// <value>Padding in device-independent pixels</value>\n    public Thickness Padding {\n        get { return (Thickness)GetValue(PaddingProperty); }\n        set { SetValue(PaddingProperty, value); }\n    }\n    \n    internal IList MergedSelectedList {\n        get {\n            if (SelectionMode == SelectionMode.Single) \n            {\n                var list = new ArrayList();\n                if(SelectedItem != null)\n                {\n                    list.Add(SelectedItem);\n                }\n                return list;\n            }\n            return SelectedItems;\n        }\n    }\n\n\n    //getters cache\n    static ConcurrentDictionary<Type, Dictionary<string,Func<object, object>>> DisplayValueCache = new ConcurrentDictionary<Type, Dictionary<string,Func<object, object>>>();\n\n    //DisplayMember getter\n    internal Func<object, object> DisplayValue{\n        get{\n            if(_getters == null || DisplayMember == null){\n                return (obj) => obj;\n            }\n            if(_getters.ContainsKey(DisplayMember)){\n                return _getters[DisplayMember];\n            }\n            else{\n                return (obj) => obj;\n            } \n        }\n    }\n\n    internal Func<object,object> SubDisplayValue{\n        get{\n            if(_getters == null || SubDisplayMember == null){\n                return (obj) => null;\n            }\n            if(_getters.ContainsKey(SubDisplayMember)){\n                return _getters[SubDisplayMember];\n            }\n            else{\n                return (obj) => null;\n            } \n        }\n    }\n\n    //OrderKey getter\n    internal Func<object, object> KeyValue{\n        get{\n            if(_getters == null || SelectedItemsOrderKey == null){\n                return null;\n            }\n           \n            if (_getters.ContainsKey(SelectedItemsOrderKey))\n            {\n                return _getters[SelectedItemsOrderKey];\n            }\n\n            return null;\n        }\n    }\n\n    INotifyCollectionChanged _notifyCollection;\n    INotifyCollectionChanged _selectedCollection;\n\n    public Command ShowCommand { get; } \n\n    public PickerCell()\n    {\n        ShowCommand = new Command(() =>\n        {\n            if (!HideArrowIndicator)\n            {\n                GetPage(this).Navigation.PushAsync(new PickerPage(this));\n            }\n        });\n\n\n        this.SetBinding(CommandProperty, new Binding(\"ShowCommand\", source: this));\n    }\n\n    Page GetPage(Element element)\n    {\n        if (element.Parent is Page page)\n        {\n            return page;\n        }\n        return GetPage(element.Parent);\n    }\n\n    internal string GetSelectedItemsText(){\n        List<string> sortedList = null;\n\n        if(MergedSelectedList == null){\n            return string.Empty;\n        }\n\n\n        if (KeyValue != null)\n        {\n            var dict = new Dictionary<object, string>();\n            foreach (var item in MergedSelectedList)\n            {\n                dict.Add(KeyValue(item), DisplayValue(item).ToString());\n            }\n            if(UseNaturalSort){\n                sortedList = dict.OrderBy(x => x.Key.ToString(),new NaturalComparer()).Select(x => x.Value).ToList();\n            }\n            else{\n                sortedList = dict.OrderBy(x => x.Key).Select(x => x.Value).ToList();\n            }\n        }\n        else\n        {\n            var strList = new List<string>();\n            foreach (var item in MergedSelectedList)\n            {\n                strList.Add(DisplayValue(item).ToString());\n            }\n            var comparer = UseNaturalSort ? new NaturalComparer() : null;\n            sortedList = strList.OrderBy(x => x, comparer).ToList();\n        }\n        \n        return string.Join(\", \", sortedList.ToArray());\n    }\n\n    internal void InvokeCommand()\n    {\n        SelectedCommand?.Execute(SelectionMode == SelectionMode.Single ? SelectedItem : SelectedItems);\n    }\n\n    Dictionary<string, Func<object, object>> _getters;\n\n    static void ItemsSourceChanging(BindableObject bindable, object oldValue, object newValue)\n    {\n        var controll = bindable as PickerCell;\n        if(newValue == null){\n            return;\n        }\n\n        controll.SetUpPropertyCache(newValue as IList);\n    }\n\n    // Create all propertiy getters\n    Dictionary<string,Func<object,object>> CreateGetProperty(Type t)\n    {           \n        var prop =t.GetRuntimeProperties()\n                            .Where(x => x.DeclaringType == t && !x.Name.StartsWith(\"_\", StringComparison.Ordinal));\n\n        var target = Expression.Parameter(typeof(object), \"target\");\n\n        var dictGetter = new Dictionary<string, Func<object, object>>();\n\n        foreach (var p in prop) {\n\n            var body = Expression.PropertyOrField(Expression.Convert(target,t), p.Name);\n\n            var lambda = Expression.Lambda<Func<object, object>>(\n                Expression.Convert(body,typeof(object)),target\n            );\n\n            dictGetter[p.Name] = lambda.Compile();\n        }\n\n        return dictGetter;\n    }\n\n    void SetUpPropertyCache(IList itemsSource)\n    {\n        var typeArg = itemsSource.GetType().GenericTypeArguments;\n\n        if(typeArg.Count() == 0){\n            throw new ArgumentException(\"ItemsSource must be GenericType.\");\n        }\n\n        // If the type is a system built-in-type, it doesn't create GetProperty.\n        if(IsBuiltInType(typeArg[0]))\n        {\n            _getters = null;\n            return;\n        }\n\n        _getters = DisplayValueCache.GetOrAdd(typeArg[0], CreateGetProperty);\n    }\n\n    bool IsBuiltInType(Type type)\n    {\n        var name = type.FullName;\n        switch (name)\n        {\n            case \"System.Boolean\":\n            case \"System.Byte\":\n            case \"System.SByte\":\n            case \"System.Char\":\n            case \"System.Int16\":\n            case \"System.UInt16\":\n            case \"System.Int32\":\n            case \"System.UInt32\":\n            case \"System.Int64\":\n            case \"System.UInt64\":\n            case \"System.Single\":\n            case \"System.Double\":\n            case \"System.Decimal\":\n            case \"System.String\":\n            case \"System.Object\":\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)\n    {\n        base.OnPropertyChanged(propertyName);\n        if (propertyName == PickerCell.SelectedItemsProperty.PropertyName ||\n                propertyName == PickerCell.SelectedItemProperty.PropertyName ||\n                propertyName == PickerCell.DisplayMemberProperty.PropertyName ||\n                propertyName == PickerCell.UseNaturalSortProperty.PropertyName ||\n                propertyName == PickerCell.SelectedItemsOrderKeyProperty.PropertyName)\n        {\n            UpdateSelectedItems();\n        }\n        if (propertyName == PickerCell.UseAutoValueTextProperty.PropertyName)\n        {\n            if (UseAutoValueText)\n            {\n                UpdateSelectedItems();\n            }            \n        }\n        if (propertyName == PickerCell.ItemsSourceProperty.PropertyName)\n        {\n            UpdateCollectionChanged();\n            UpdateSelectedItems();\n        }\n    }\n\n    void UpdateSelectedItems()\n    {\n        if (!UseAutoValueText)\n        {\n            return;\n        }\n\n        if (_selectedCollection != null)\n        {\n            _selectedCollection.CollectionChanged -= SelectedItems_CollectionChanged;\n        }\n\n        _selectedCollection = SelectedItems as INotifyCollectionChanged;\n\n        if (_selectedCollection != null)\n        {\n            _selectedCollection.CollectionChanged += SelectedItems_CollectionChanged;\n        }\n\n        ValueText = GetSelectedItemsText();\n    }\n\n    void UpdateCollectionChanged()\n    {\n        if (_notifyCollection != null)\n        {\n            _notifyCollection.CollectionChanged -= ItemsSourceCollectionChanged;\n        }\n\n        _notifyCollection = ItemsSource as INotifyCollectionChanged;\n\n        if (_notifyCollection != null)\n        {\n            _notifyCollection.CollectionChanged += ItemsSourceCollectionChanged;\n            ItemsSourceCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));\n        }\n    }\n\n\n    void SelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        UpdateSelectedItems();\n    }\n\n    void ItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        if (!IsEnabled)\n        {\n            return;\n        }\n\n        SetEnabledAppearance(ItemsSource.Count > 0);\n    }\n\n    \n}\n"
  },
  {
    "path": "SettingsView/Cells/RadioCell.cs",
    "content": "﻿using System;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Radio cell.\n/// </summary>\npublic class RadioCell:CellBase\n{\n    /// <summary>\n    /// The selected value property.\n    /// </summary>\n    public static readonly BindableProperty SelectedValueProperty =\n        BindableProperty.CreateAttached(\n                \"SelectedValue\",\n                typeof(object),\n                typeof(RadioCell),\n                default(object),\n                BindingMode.TwoWay\n            );\n\n    /// <summary>\n    /// Sets the selected value.\n    /// </summary>\n    /// <param name=\"view\">View.</param>\n    /// <param name=\"value\">Value.</param>\n    public static void SetSelectedValue(BindableObject view, object value)\n    {\n        view.SetValue(SelectedValueProperty, value);\n    }\n\n    /// <summary>\n    /// Gets the selected value.\n    /// </summary>\n    /// <returns>The selected value.</returns>\n    /// <param name=\"view\">View.</param>\n    public static object GetSelectedValue(BindableObject view)\n    {\n        return (object)view.GetValue(SelectedValueProperty);\n    }\n\n    /// <summary>\n    /// The value property.\n    /// </summary>\n    public static BindableProperty ValueProperty =\n        BindableProperty.Create(\n            nameof(Value),\n            typeof(object),\n            typeof(RadioCell),\n            default(object),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the value.\n    /// </summary>\n    /// <value>The value.</value>\n    public object Value {\n        get { return (object)GetValue(ValueProperty); }\n        set { SetValue(ValueProperty, value); }\n    }\n\n    /// <summary>\n    /// The accent color property.\n    /// </summary>\n    public static BindableProperty AccentColorProperty =\n        BindableProperty.Create(\n            nameof(AccentColor),\n            typeof(Color),\n            typeof(RadioCell),\n            default(Color),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the accent.\n    /// </summary>\n    /// <value>The color of the accent.</value>\n    public Color AccentColor {\n        get { return (Color)GetValue(AccentColorProperty); }\n        set { SetValue(AccentColorProperty, value); }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/SimpleCheckCell.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings;\n\r\npublic class SimpleCheckCell: CellBase\n{\n    public static BindableProperty CheckedProperty = BindableProperty.Create(\n            nameof(Checked),\n            typeof(bool),\n            typeof(SimpleCheckCell),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public bool Checked{\n        get { return (bool)GetValue(CheckedProperty); }\n        set { SetValue(CheckedProperty, value); }\n    }\n\n    /// <summary>\n    /// The value property.\n    /// </summary>\n    public static BindableProperty ValueProperty =\n        BindableProperty.Create(\n            nameof(Value),\n            typeof(object),\n            typeof(SimpleCheckCell),\n            default(object),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the value.\n    /// </summary>\n    /// <value>The value.</value>\n    public object Value\n    {\n        get { return (object)GetValue(ValueProperty); }\n        set { SetValue(ValueProperty, value); }\n    }\n\n    /// <summary>\n    /// The accent color property.\n    /// </summary>\n    public static BindableProperty AccentColorProperty =\n        BindableProperty.Create(\n            nameof(AccentColor),\n            typeof(Color),\n            typeof(SimpleCheckCell),\n            default(Color),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the accent.\n    /// </summary>\n    /// <value>The color of the accent.</value>\n    public Color AccentColor\n    {\n        get { return (Color)GetValue(AccentColorProperty); }\n        set { SetValue(AccentColorProperty, value); }\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Cells/SwitchCell.cs",
    "content": "﻿using System;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Switch cell.\n/// </summary>\npublic class SwitchCell:CellBase\n{\n    /// <summary>\n    /// The on property.\n    /// </summary>\n    public static BindableProperty OnProperty =\n        BindableProperty.Create(\n            nameof(On),\n            typeof(bool),\n            typeof(SwitchCell),\n            default(bool),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.SwitchCell\"/> is on.\n    /// </summary>\n    /// <value><c>true</c> if on; otherwise, <c>false</c>.</value>\n    public bool On {\n        get { return (bool)GetValue(OnProperty); }\n        set { SetValue(OnProperty, value); }\n    }\n\n    /// <summary>\n    /// The accent color property.\n    /// </summary>\n    public static BindableProperty AccentColorProperty =\n        BindableProperty.Create(\n            nameof(AccentColor),\n            typeof(Color),\n            typeof(SwitchCell),\n            default(Color),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the accent.\n    /// </summary>\n    /// <value>The color of the accent.</value>\n    public Color AccentColor {\n        get { return (Color)GetValue(AccentColorProperty); }\n        set { SetValue(AccentColorProperty, value); }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Cells/TextPickerCell.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\nusing System.Collections.Generic;\nusing System.Collections;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Text picker cell.\n/// </summary>\npublic class TextPickerCell:LabelCell\n{\n    /// <summary>\n    /// The items property.\n    /// </summary>\n    public static BindableProperty ItemsProperty =\n        BindableProperty.Create(\n            nameof(Items),\n            typeof(IList),\n            typeof(TextPickerCell),\n            new List<object>(),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the items.\n    /// </summary>\n    /// <value>The items.</value>\n    public IList Items {\n        get { return (IList)GetValue(ItemsProperty); }\n        set { SetValue(ItemsProperty, value); }\n    }\n\n    /// <summary>\n    /// The page title property.\n    /// </summary>\n    public static BindableProperty PageTitleProperty =\n        BindableProperty.Create(\n            nameof(PageTitle),\n            typeof(string),\n            typeof(PickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the page title.\n    /// </summary>\n    /// <value>The page title.</value>\n    public string PageTitle {\n        get { return (string)GetValue(PageTitleProperty); }\n        set { SetValue(PageTitleProperty, value); }\n    }\n\n    /// <summary>\n    /// The accent color property.\n    /// </summary>\n    public static BindableProperty AccentColorProperty =\n        BindableProperty.Create(\n            nameof(AccentColor),\n            typeof(Color),\n            typeof(PickerCell),\n            default(Color),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the accent.\n    /// </summary>\n    /// <value>The color of the accent.</value>\n    public Color AccentColor {\n        get { return (Color)GetValue(AccentColorProperty); }\n        set { SetValue(AccentColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The selected item property.\n    /// </summary>\n    public static BindableProperty SelectedItemProperty =\n        BindableProperty.Create(\n            nameof(SelectedItem),\n            typeof(object),\n            typeof(TextPickerCell),\n            default(object),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets the selected number.\n    /// </summary>\n    /// <value>The text value.</value>\n    public object SelectedItem {\n        get { return (object)GetValue(SelectedItemProperty); }\n        set { SetValue(SelectedItemProperty, value); }\n    }\n\n    /// <summary>\n    /// The picker title property.\n    /// </summary>\n    public static BindableProperty PickerTitleProperty =\n        BindableProperty.Create(\n            nameof(PickerTitle),\n            typeof(string),\n            typeof(TextPickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the picker title.\n    /// </summary>\n    /// <value>The picker title.</value>\n    public string PickerTitle {\n        get { return (string)GetValue(PickerTitleProperty); }\n        set { SetValue(PickerTitleProperty, value); }\n    }\n\n    /// <summary>\n    /// The selected command property.\n    /// </summary>\n    public static BindableProperty SelectedCommandProperty =\n        BindableProperty.Create(\n            nameof(SelectedCommand),\n            typeof(ICommand),\n            typeof(TextPickerCell),\n            default(ICommand),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the selected command.\n    /// </summary>\n    /// <value>The selected command.</value>\n    public ICommand SelectedCommand {\n        get { return (ICommand)GetValue(SelectedCommandProperty); }\n        set { SetValue(SelectedCommandProperty, value); }\n    }\n\n    /// <summary>\n    /// Whether the picker is circular. (only Android)\n    /// </summary>\n    public static BindableProperty IsCircularPickerProperty = BindableProperty.Create(\n        nameof(IsCircularPicker),\n        typeof(bool),\n        typeof(TextPickerCell),\n        true,\n        defaultBindingMode: BindingMode.OneWay\n    );\n    /// <summary>\n    /// Whether the picker is circular. (only Android)\n    /// </summary>\n    public bool IsCircularPicker {\n        get { return (bool)GetValue(IsCircularPickerProperty); }\n        set { SetValue(IsCircularPickerProperty, value); }\n    }\n\n    private new string ValueText { get; set; }\n}\n"
  },
  {
    "path": "SettingsView/Cells/TimePickerCell.cs",
    "content": "﻿using System;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Time picker cell.\n/// </summary>\npublic class TimePickerCell:LabelCell\n{\n    /// <summary>\n    /// The time property.\n    /// </summary>\n    public static BindableProperty TimeProperty =\n        BindableProperty.Create(\n            nameof(Time),\n            typeof(TimeSpan),\n            typeof(TimePickerCell),\n            default(TimeSpan),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets the time.\n    /// </summary>\n    /// <value>The time.</value>\n    public TimeSpan Time {\n        get { return (TimeSpan)GetValue(TimeProperty); }\n        set { SetValue(TimeProperty, value); }\n    }\n\n    /// <summary>\n    /// The format property.\n    /// </summary>\n    public static BindableProperty FormatProperty =\n        BindableProperty.Create(\n            nameof(Format),\n            typeof(string),\n            typeof(TimePickerCell),\n            \"t\",\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the format.\n    /// </summary>\n    /// <value>The format.</value>\n    public string Format {\n        get { return (string)GetValue(FormatProperty); }\n        set { SetValue(FormatProperty, value); }\n    }\n\n    /// <summary>\n    /// The picker title property.\n    /// </summary>\n    public static BindableProperty PickerTitleProperty =\n        BindableProperty.Create(\n            nameof(PickerTitleProperty),\n            typeof(string),\n            typeof(TimePickerCell),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the picker title.\n    /// </summary>\n    /// <value>The picker title.</value>\n    public string PickerTitle {\n        get { return (string)GetValue(PickerTitleProperty); }\n        set { SetValue(PickerTitleProperty, value); }\n    }\n\n    private new string ValueText { get; set; }\n}\n"
  },
  {
    "path": "SettingsView/DropEventArgs.cs",
    "content": "﻿using System;\n\nnamespace AiForms.Settings;\n\r\npublic class DropEventArgs:EventArgs\n{       \n    public Section Section { get; }\n    public CellBase Cell { get; }\n    public object SectionSource { get; }\n    public object CellSource { get; }\n\n    public DropEventArgs(Section section,CellBase cell)\n    {\n        Section = section;\n        Cell = cell;\n        SectionSource = section.BindingContext;\n        CellSource = cell.BindingContext;\n    }\n}\n"
  },
  {
    "path": "SettingsView/Extensions/EnumerableExtension.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Extensions\n{\n    public static class EnumerableExtension\n    {\n        public static int IndexOf<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)\n        {\n            var i = 0;\n            foreach (T element in enumerable)\n            {\n                if (predicate(element))\n                    return i;\n\n                i++;\n            }\n\n            return -1;\n        }\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Extensions/FontExtension.cs",
    "content": "﻿using System;\nusing Microsoft.Maui;\nusing Font = Microsoft.Maui.Font;\n\nnamespace AiForms.Settings.Extensions;\n\r\npublic static class FontExtension\n{\n    public static Font ToFont(this string fontFamily, double fontSize, FontAttributes fontAttributes, double? defaultSize = null)\n    {\n        if (defaultSize.HasValue && (fontSize <= 0 || double.IsNaN(fontSize)))\n        {\n            fontSize = defaultSize.Value;\n        }            \n\n        return Font.OfSize(fontFamily, fontSize, enableScaling: false).WithAttributes(fontAttributes);\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Extensions/HandlerCleanUpHelper.cs",
    "content": "﻿using System;\nusing Microsoft.Maui.Handlers;\n\nnamespace AiForms.Settings.Extensions;\n\npublic static class HandlerCleanUpHelper\n{\n    public static void AddCleanUpEvent(this View view)\n    {\n        if (view is not Element element)\n        {\n            return;\n        }\n\n        Page parentPage;\n\n        void PageUnloaded(object sender, EventArgs e)\n        {\n            view.Handler?.DisconnectHandler();\n            if (parentPage is not null)\n            {\n                parentPage.Unloaded -= PageUnloaded;\n                parentPage = null;\n            }\n        }        \n\n        foreach (var el in element.GetParentsPath())\n        {\n            if (el is Page page)\n            {\n                parentPage = page;\n                page.Unloaded += PageUnloaded;\n            }\n        }        \n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Extensions/ViewExtension.cs",
    "content": "﻿#nullable enable\nusing System;\n\nnamespace AiForms.Settings.Extensions;\n\r\npublic static class ViewExtension\n{\n    public static IMauiContext? FindMauiContext(this Element element, bool fallbackToAppMauiContext = false)\n    {\n        if (element is Microsoft.Maui.IElement fe && fe.Handler?.MauiContext != null)\n            return fe.Handler.MauiContext;\n\n        foreach (var parent in element.GetParentsPath())\n        {\n            if (parent is Microsoft.Maui.IElement parentView && parentView.Handler?.MauiContext != null)\n                return parentView.Handler.MauiContext;\n        }\n\n        return fallbackToAppMauiContext ? Application.Current?.FindMauiContext() : default;\n    }\n\n    public static IEnumerable<Element> GetParentsPath(this Element self)\n    {\n        Element current = self;\n\n        while (!IsApplicationOrNull(current.RealParent))\n        {\n            current = current.RealParent;\n            yield return current;\n        }\n    }\n\n    public static bool IsApplicationOrNull(object? element) =>\n            element == null || element is IApplication;\n\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/ButtonCell/ButtonCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class ButtonCellHandler : CellBaseHandler<ButtonCell, ButtonCellView>\n{\n    public static IPropertyMapper<ButtonCell, ButtonCellHandler> ButtonMapper =\n        new PropertyMapper<ButtonCell, ButtonCellHandler>(BasePropertyMapper)\n        {\n            [nameof(ButtonCell.Command)] = MapCommand,\n            [nameof(ButtonCell.CommandParameter)] = MapCommand,\n            [nameof(ButtonCell.TitleAlignment)] = MapTitleAlignment,\n        };\n\n    private static void MapTitleAlignment(ButtonCellHandler handler, ButtonCell arg2)\n    {\n        handler.PlatformView.UpdateTitleAlignment();\n    }\n\n    private static void MapCommand(ButtonCellHandler handoer, ButtonCell arg2)\n    {\n        handoer.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/ButtonCell/ButtonCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class ButtonCellHandler : CellBaseHandler<ButtonCell, CellBaseView>\n{\n    public static IPropertyMapper<ButtonCell, ButtonCellHandler> ButtonMapper =\n        new PropertyMapper<ButtonCell, ButtonCellHandler>(BasePropertyMapper)\n        {\n        };\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/ButtonCell/ButtonCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class ButtonCellHandler\n{\n    public static CommandMapper<ButtonCell, ButtonCellHandler> ButtonCommandMapper = new(BaseCommandMapper);  \n\n    public ButtonCellHandler() : base(ButtonMapper, ButtonCommandMapper)\n    {\n    }\n\n    public ButtonCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? ButtonMapper, commandMapper ?? ButtonCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/ButtonCell/ButtonCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class ButtonCellHandler : CellBaseHandler<ButtonCell, ButtonCellView>\n{\n    public static IPropertyMapper<ButtonCell, ButtonCellHandler> ButtonMapper =\n        new PropertyMapper<ButtonCell, ButtonCellHandler>(BasePropertyMapper)\n        {\n            [nameof(ButtonCell.Command)] = MapCommand,\n            [nameof(ButtonCell.CommandParameter)] = MapCommand,\n            [nameof(ButtonCell.TitleAlignment)] = MapTitleAlignment,\n        };\n\n    private static void MapTitleAlignment(ButtonCellHandler handler, ButtonCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateTitleAlignment();\n    }\n\n    private static void MapCommand(ButtonCellHandler handler, ButtonCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CellBase/CellBaseHandler.Android.cs",
    "content": "﻿using System;\nusing System.Linq.Expressions;\nusing System.Reflection;\nusing AiForms.Settings.Platforms.Droid;\nusing Android.Content;\nusing Android.Graphics.Drawables;\nusing Android.Views;\nusing Microsoft.Maui.Handlers;\nusing AView = Android.Views.View;\n\nnamespace AiForms.Settings.Handlers\n{\n    public partial class CellBaseHandler<TvirtualCell, TnativeCell> \n    {\n        public static IPropertyMapper<CellBase, CellBaseHandler<TvirtualCell, TnativeCell>> BasePropertyMapper =\n            new PropertyMapper<CellBase, CellBaseHandler<TvirtualCell, TnativeCell>>(ElementMapper)\n            {\n                [nameof(CellBase.Title)] = MapTitleText,\n                [nameof(CellBase.TitleColor)] = MapTitleColor,\n                [nameof(CellBase.TitleFontSize)] = MapTitleFontSize,\n                [nameof(CellBase.TitleFontAttributes)] = MapTitleFont,\n                [nameof(CellBase.TitleFontFamily)] = MapTitleFont,\n                [nameof(CellBase.Description)] = MapDescriptionText,\n                [nameof(CellBase.DescriptionColor)] = MapDescriptionColor,\n                [nameof(CellBase.DescriptionFontSize)] = MapDescriptionFontSize,\n                [nameof(CellBase.DescriptionFontAttributes)] = MapDescriptionFont,\n                [nameof(CellBase.DescriptionFontFamily)] = MapDescriptionFont,\n                [nameof(CellBase.HintText)] = MapHintText,\n                [nameof(CellBase.HintTextColor)] = MapHintTextColor,\n                [nameof(CellBase.HintFontSize)] = MapHintFontSize,\n                [nameof(CellBase.HintFontAttributes)] = MapHintFont,\n                [nameof(CellBase.HintFontFamily)] = MapHintFont,\n                [nameof(CellBase.BackgroundColor)] = MapBackgroundColor,\n                [nameof(CellBase.IconSource)] = MapIconSource,\n                [nameof(CellBase.IconSize)] = MapIconSource,\n                [nameof(CellBase.IconRadius)] = MapIconRadius,\n                [nameof(CellBase.IsEnabled)] = MapIsEnabled,\n            };\n\n        internal static class InstanceCreator<T1, T2, TInstance>\n        {\n            public static Func<T1, T2, TInstance> Create { get; } = CreateInstance();\n\n            private static Func<T1, T2, TInstance> CreateInstance()\n            {\n                var argsTypes = new[] { typeof(T1), typeof(T2) };\n                var constructor = typeof(TInstance).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, Type.DefaultBinder,\n                       argsTypes, null);\n                var args = argsTypes.Select(Expression.Parameter).ToArray();\n                return Expression.Lambda<Func<T1, T2, TInstance>>(Expression.New(constructor, args), args).Compile();\n            }\n        }\n\n        protected override TnativeCell CreatePlatformElement()\n        {\n            var convertView = VirtualView.ConvertView;\n            VirtualView.ConvertView = null;\n\n            return GetCell(VirtualView, convertView, null, MauiContext.Context);\n        }\n\n        public virtual TnativeCell GetCell(CellBase item, AView convertView, ViewGroup parent, Context context)\n        {\n            TnativeCell nativeCell = convertView as TnativeCell;\n            if (nativeCell == null)\n            {\n                nativeCell = InstanceCreator<Context, CellBase, TnativeCell>.Create(context, item);\n            }\n\n            ClearPropertyChanged(nativeCell);\n\n            nativeCell.Cell = item;\n\n            SetUpPropertyChanged(nativeCell);\n\n            nativeCell.UpdateCell(); // Initialization process not handled by Mapper\n\n            return nativeCell;\n        }        \n\n        private static void MapTitleText(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateTitleText();\n        }\n\n        private static void MapTitleColor(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateTitleColor();\n        }\n\n        private static void MapTitleFontSize(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateTitleFontSize();\n        }\n\n        private static void MapTitleFont(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateTitleFont();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapDescriptionText(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateDescriptionText();\n        }\n\n        private static void MapDescriptionColor(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateDescriptionColor();\n        }\n\n        private static void MapDescriptionFontSize(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateDescriptionFontSize();\n        }\n\n        private static void MapDescriptionFont(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateDescriptionFont();\n        }\n\n        private static void MapHintText(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateHintText();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapHintTextColor(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateHintTextColor();\n        }\n\n        private static void MapHintFontSize(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateHintFontSize();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapHintFont(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateHintFont();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapIconSource(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateIcon();\n        }\n\n        private static void MapIconRadius(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateIconRadius();\n            nativeView?.UpdateIcon(true);\n        }\n\n        private static void MapIsEnabled(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateIsEnabled();\n        }\n\n        private static void MapBackgroundColor(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            ((CellBaseView)handler.PlatformView)?.UpdateBackgroundColor();\n        }\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CellBase/CellBaseHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class CellBaseHandler<TvirtualCell, TnativeCell>\n{\n    public static IPropertyMapper<CellBase, CellBaseHandler<TvirtualCell, TnativeCell>> BasePropertyMapper =\n            new PropertyMapper<CellBase, CellBaseHandler<TvirtualCell, TnativeCell>>(ElementMapper);\n\n    protected override TnativeCell CreatePlatformElement()\n    {\n        throw new NotImplementedException();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CellBase/CellBaseHandler.cs",
    "content": "﻿#nullable enable\nusing System;\nusing System.Linq.Expressions;\nusing System.Reflection;\nusing AiForms.Settings;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Maui.Handlers;\nusing Microsoft.Maui.Platform;\n#if IOS || MACCATALYST\nusing CellBaseView = AiForms.Settings.Platforms.iOS.CellBaseView;\n#elif __ANDROID__\nusing CellBaseView = AiForms.Settings.Platforms.Droid.CellBaseView;\n#elif NET6_0_OR_GREATER\nusing CellBaseView = AiForms.Settings.Handlers.CellBaseView;\n#endif\n\n\nnamespace AiForms.Settings.Handlers\n{\n    public partial class CellBaseHandler<TvirtualCell, TnativeCell> : ElementHandler<TvirtualCell, TnativeCell>, IRegisterable\n        where TvirtualCell : CellBase\n        where TnativeCell : CellBaseView\n    {\n        public static CommandMapper<CellBase, CellBaseHandler<TvirtualCell, TnativeCell>> BaseCommandMapper = new CommandMapper<CellBase, CellBaseHandler<TvirtualCell, TnativeCell>>\n        {\n            [nameof(CellBase.SetEnabledAppearance)] = MapSetEnabledAppearance\n        };\n\n        private static void MapSetEnabledAppearance(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase view, object? param)\n        {\n            handler.PlatformView?.SetEnabledAppearance((bool)param!);\n        }\n\n        public CellBaseHandler(): base(BasePropertyMapper, BaseCommandMapper)\n        {\n        }\n\n        public CellBaseHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null): base(mapper ?? BasePropertyMapper, commandMapper ?? BaseCommandMapper)\n        {\n        }\n        \n\n        /// <summary>\n        /// Sets up property changed.\n        /// </summary>\n        /// <param name=\"nativeCell\">Native cell.</param>\n        protected void SetUpPropertyChanged(CellBaseView nativeCell)\n        {\n            var virtualCell = nativeCell.Cell;\n            var parentElement = virtualCell.Parent as SettingsView;\n\n            if (parentElement != null)\n            {\n                parentElement.PropertyChanged += nativeCell.ParentPropertyChanged;\n\n                var section = parentElement.Model.GetSectionFromCell(virtualCell);\n                if (section != null)\n                {\n                    virtualCell.Section = section;\n                    virtualCell.Section.PropertyChanged += nativeCell.SectionPropertyChanged;\n                }\n            }\n        }\n\n        protected void ClearPropertyChanged(CellBaseView nativeCell)\n        {\n            var virtualCell = nativeCell.Cell;\n\n            if (virtualCell is null)\n                return; // for HotReload\n\n            var parentElement = virtualCell.Parent as SettingsView;\n\n            if (parentElement != null)\n            {\n                parentElement.PropertyChanged -= nativeCell.ParentPropertyChanged;\n                if (virtualCell.Section != null)\n                {\n                    virtualCell.Section.PropertyChanged -= nativeCell.SectionPropertyChanged;\n                }\n            }\n        }\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CellBase/CellBaseHandler.iOS.cs",
    "content": "﻿#nullable enable\nusing System;\nusing System.Linq.Expressions;\nusing System.Reflection;\nusing AiForms.Settings.Platforms.iOS;\nusing Microsoft.Maui;\nusing Microsoft.Maui.Handlers;\nusing UIKit;\n\nnamespace AiForms.Settings.Handlers\n{\n    [Foundation.Preserve(AllMembers = true)]\n    public partial class CellBaseHandler<TvirtualCell, TnativeCell> \n    {\n        public static IPropertyMapper<CellBase, CellBaseHandler<TvirtualCell, TnativeCell>> BasePropertyMapper =\n            new PropertyMapper<CellBase, CellBaseHandler<TvirtualCell, TnativeCell>>(ElementMapper)\n            {\n                [nameof(CellBase.Title)] = MapTitleText,\n                [nameof(CellBase.TitleColor)] = MapTitleColor,\n                [nameof(CellBase.TitleFontSize)] = MapTitleFont,\n                [nameof(CellBase.TitleFontAttributes)] = MapTitleFont,\n                [nameof(CellBase.TitleFontFamily)] = MapTitleFont,\n                [nameof(CellBase.Description)] = MapDescriptionText,\n                [nameof(CellBase.DescriptionColor)] = MapDescriptionColor,\n                [nameof(CellBase.DescriptionFontSize)] = MapDescriptionFont,\n                [nameof(CellBase.DescriptionFontAttributes)] = MapDescriptionFont,\n                [nameof(CellBase.DescriptionFontFamily)] = MapDescriptionFont,\n                [nameof(CellBase.HintText)] = MapHintText,\n                [nameof(CellBase.HintTextColor)] = MapHintTextColor,\n                [nameof(CellBase.HintFontSize)] = MapHintFont,\n                [nameof(CellBase.HintFontAttributes)] = MapHintFont,\n                [nameof(CellBase.HintFontFamily)] = MapHintFont,\n                [nameof(CellBase.BackgroundColor)] = MapBackgroundColor,\n                [nameof(CellBase.IconSource)] = MapIconSource,\n                [nameof(CellBase.IconSize)] = MapIconSize,\n                [nameof(CellBase.IconRadius)] = MapIconRadius,\n                [nameof(CellBase.IsVisible)] = MapIsVisible,\n                [nameof(CellBase.IsEnabled)] = MapIsEnabled,\n            };\n\n        /// <summary>\n        /// Refer to \n        /// http://qiita.com/Temarin/items/d6f00428743b0971ec95\n        /// http://neue.cc/2014/09/16_478.html\n        /// </summary>\n        internal static class InstanceCreator<T1, TInstance>\n        {\n            public static Func<T1, TInstance> Create { get; } = CreateInstance();\n\n            private static Func<T1, TInstance> CreateInstance()\n            {\n                var constructor = typeof(TInstance).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, Type.DefaultBinder,\n                    new[] { typeof(T1) }, null);\n                var handler = Expression.Parameter(typeof(T1));\n                return Expression.Lambda<Func<T1, TInstance>>(Expression.New(constructor!, handler), handler).Compile();\n            }\n        }\n\n        protected override TnativeCell CreatePlatformElement()\n        {\n            var reusableCell = VirtualView.ReusableCell;\n            var tv = VirtualView.TableView;\n\n            return GetCell(VirtualView, reusableCell, tv);\n        }\n\n        protected override void DisconnectHandler(TnativeCell platformView)\n        {\n            base.DisconnectHandler(platformView);\n            IsDisconnect = true;\n        }\n\n        protected override void ConnectHandler(TnativeCell platformView)\n        {\n            base.ConnectHandler(platformView);\n            IsDisconnect = false;            \n        }\n\n        public bool IsDisconnect { get; private set; }\n\n        /// <summary>\n        /// Gets the cell.\n        /// </summary>\n        /// <returns>The cell.</returns>\n        /// <param name=\"item\">Item.</param>\n        /// <param name=\"reusableCell\">Reusable cell.</param>\n        /// <param name=\"tv\">Tv.</param>\n        public virtual TnativeCell GetCell(CellBase item, UITableViewCell reusableCell, UITableView tv)\n        {\n            var nativeCell = reusableCell as TnativeCell;\n            if (nativeCell == null)\n            {\n                nativeCell = InstanceCreator<CellBase, TnativeCell>.Create(item);\n            }\n\n            ClearPropertyChanged(nativeCell);\n\n            nativeCell.Cell = item;\n\n            SetUpPropertyChanged(nativeCell);\n\n            nativeCell.UpdateCell(tv); // Initialization process not handled by Mapper\n\n            return nativeCell;\n        }\n\n        private static void MapTitleText(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateTitleText();\n        }\n\n        private static void MapTitleColor(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateTitleColor();\n        }\n\n        private static void MapTitleFont(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateTitleFont();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapDescriptionText(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateDescriptionText();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapDescriptionColor(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateDescriptionColor();\n        }\n\n        private static void MapDescriptionFont(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateDescriptionFont();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapHintText(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeCell = handler.PlatformView as CellBaseView;\n            nativeCell?.UpdateHintText();\n            nativeCell?.UpdateLayout();\n        }\n\n        private static void MapHintTextColor(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateHintTextColor();\n        }\n\n        private static void MapHintFont(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateHintFont();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapIconRadius(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateIconRadius();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapIconSize(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateIconSize();\n            nativeView?.UpdateLayout();\n        }\n\n        private static void MapIconSource(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateIcon();\n        }\n\n        private static void MapIsVisible(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateIsVisible();\n        }\n\n        private static void MapIsEnabled(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateIsEnabled();\n        }\n\n        private static void MapBackgroundColor(CellBaseHandler<TvirtualCell, TnativeCell> handler, CellBase cell)\n        {\n            if (handler.IsDisconnect) return;\n            var nativeView = handler.PlatformView as CellBaseView;\n            nativeView?.UpdateBackgroundColor();\n        }\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CellBase/CellBaseView.Net.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\n\nnamespace AiForms.Settings.Handlers;\n\npublic class CellBaseView\n{\n    public CellBase Cell { get; set; }\n\n    public void SetEnabledAppearance(bool enabled)\n    {\n    }\n\n    public virtual void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n    }\n\n    public virtual void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n    }\n\n    public virtual void SectionPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n    }\n}\n"
  },
  {
    "path": "SettingsView/Handlers/CheckboxCell/CheckboxCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CheckboxCellHandler : CellBaseHandler<CheckboxCell, CheckboxCellView>\n{\n    public static IPropertyMapper<CheckboxCell, CheckboxCellHandler> CheckboxMapper =\n        new PropertyMapper<CheckboxCell, CheckboxCellHandler>(BasePropertyMapper)\n        {\n            [nameof(CheckboxCell.AccentColor)] = MapAccentColor,\n            [nameof(CheckboxCell.Checked)] = MapChecked,\n        };\n\n    private static void MapAccentColor(CheckboxCellHandler handler, CheckboxCell arg2)\n    {\n        handler.PlatformView.UpdateAccentColor();\n    }\n\n    private static void MapChecked(CheckboxCellHandler handler, CheckboxCell arg2)\n    {\n        handler.PlatformView.UpdateChecked();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CheckboxCell/CheckboxCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class CheckboxCellHandler: CellBaseHandler<CheckboxCell, CellBaseView>\n{\n    public static IPropertyMapper<CheckboxCell, CheckboxCellHandler> CheckboxMapper =\n        new PropertyMapper<CheckboxCell, CheckboxCellHandler>(BasePropertyMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CheckboxCell/CheckboxCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CheckboxCellHandler\n{\n    public static CommandMapper<CheckboxCell, CheckboxCellHandler> CheckboxCommandMapper = new(BaseCommandMapper);\n\n    public CheckboxCellHandler() : base(CheckboxMapper, CheckboxCommandMapper)\n    {\n    }\n\n    public CheckboxCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? CheckboxMapper, commandMapper ?? CheckboxCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CheckboxCell/CheckboxCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CheckboxCellHandler : CellBaseHandler<CheckboxCell, CheckboxCellView>\n{\n    public static IPropertyMapper<CheckboxCell, CheckboxCellHandler> CheckboxMapper =\n        new PropertyMapper<CheckboxCell, CheckboxCellHandler>(BasePropertyMapper)\n        {\n            [nameof(CheckboxCell.AccentColor)] = MapAccentColor,\n            [nameof(CheckboxCell.Checked)] = MapChecked,\n        };\n\n    private static void MapAccentColor(CheckboxCellHandler handler, CheckboxCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateAccentColor();\n    }\n\n    private static void MapChecked(CheckboxCellHandler handler, CheckboxCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateChecked();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CommandCell/CommandCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\nusing Android.Bluetooth;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CommandCellHandler : LabelCellBaseHandler<CommandCell, CommandCellView>\n{\n    public static IPropertyMapper<CommandCell, CommandCellHandler> CommandMapper =\n        new PropertyMapper<CommandCell, CommandCellHandler>(LabelMapper)\n        {\n            [nameof(CommandCell.Command)] = MapCommand,\n            [nameof(CommandCell.CommandParameter)] = MapCommand,\n        };\n\n    private static void MapCommand(CommandCellHandler handler, CommandCell cell)\n    {\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CommandCell/CommandCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class CommandCellHandler : LabelCellBaseHandler<CommandCell, CellBaseView>\n{\n    public static IPropertyMapper<CommandCell, CommandCellHandler> CommandMapper =\n        new PropertyMapper<CommandCell, CommandCellHandler>(LabelMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CommandCell/CommandCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CommandCellHandler\n{\n    public static CommandMapper<CommandCell, CommandCellHandler> CommandCommandMapper = new(LabelCommandMapper);\n\n    public CommandCellHandler() : base(CommandMapper, CommandCommandMapper)\n    {\n    }\n\n    public CommandCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? CommandMapper, commandMapper ?? CommandCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CommandCell/CommandCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CommandCellHandler: LabelCellBaseHandler<CommandCell, CommandCellView>\n{\n    public static IPropertyMapper<CommandCell, CommandCellHandler> CommandMapper =\n        new PropertyMapper<CommandCell, CommandCellHandler>(LabelMapper)\n        {\n            [nameof(CommandCell.Command)] = MapCommand,\n            [nameof(CommandCell.CommandParameter)] = MapCommand,\n        };\n\n    private static void MapCommand(CommandCellHandler handler, CommandCell cell)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CustomCell/CustomCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\nusing Android.Bluetooth;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CustomCellHandler : CellBaseHandler<CustomCell, CustomCellView>\n{\n    public static IPropertyMapper<CustomCell, CustomCellHandler> CustomMapper =\n        new PropertyMapper<CustomCell, CustomCellHandler>(BasePropertyMapper)\n        {\n            [nameof(CustomCell.Command)] = MapCommand,\n            [nameof(CustomCell.CommandParameter)] = MapCommand,\n        };\n\n    private static void MapCommand(CustomCellHandler handler, CustomCell arg2)\n    {\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CustomCell/CustomCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class CustomCellHandler : CellBaseHandler<CustomCell, CellBaseView>\n{\n    public static IPropertyMapper<CustomCell, CustomCellHandler> CustomMapper =\n        new PropertyMapper<CustomCell, CustomCellHandler>(BasePropertyMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CustomCell/CustomCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CustomCellHandler\n{\n    public static CommandMapper<CustomCell, CustomCellHandler> CustomCommandMapper = new(BaseCommandMapper);\n\n    public CustomCellHandler() : base(CustomMapper, CustomCommandMapper)\n    {\n    }\n\n    public CustomCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? CustomMapper, commandMapper ?? CustomCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/CustomCell/CustomCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class CustomCellHandler : CellBaseHandler<CustomCell, CustomCellView>\n{\n    public static IPropertyMapper<CustomCell, CustomCellHandler> CustomMapper =\n        new PropertyMapper<CustomCell, CustomCellHandler>(BasePropertyMapper)\n        {\n            [nameof(CustomCell.Command)] = MapCommand,\n            [nameof(CustomCell.CommandParameter)] = MapCommand,\n        };\n\n    private static void MapCommand(CustomCellHandler handler, CustomCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/DatePickerCell/DatePickerCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class DatePickerCellHandler : LabelCellBaseHandler<DatePickerCell, DatePickerCellView>\n{\n    public static IPropertyMapper<DatePickerCell, DatePickerCellHandler> DatePickerMapper =\n        new PropertyMapper<DatePickerCell, DatePickerCellHandler>(LabelMapper)\n        {\n            [nameof(DatePickerCell.Date)] = MapDate,\n            [nameof(DatePickerCell.Format)] = MapDate,\n            [nameof(DatePickerCell.MaximumDate)] = MapMaximumDate,\n            [nameof(DatePickerCell.MinimumDate)] = MapMinimumDate,\n        };\n\n    private static void MapDate(DatePickerCellHandler handler, DatePickerCell arg2)\n    {\n        handler.PlatformView.UpdateDate();\n    }\n\n    private static void MapMaximumDate(DatePickerCellHandler handler, DatePickerCell arg2)\n    {\n        handler.PlatformView.UpdateMaximumDate();\n    }\n\n    private static void MapMinimumDate(DatePickerCellHandler handler, DatePickerCell arg2)\n    {\n        handler.PlatformView.UpdateMinimumDate();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/DatePickerCell/DatePickerCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class DatePickerCellHandler : LabelCellBaseHandler<DatePickerCell, CellBaseView>\n{\n    public static IPropertyMapper<DatePickerCell, DatePickerCellHandler> DatePickerMapper =\n        new PropertyMapper<DatePickerCell, DatePickerCellHandler>(LabelMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/DatePickerCell/DatePickerCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class DatePickerCellHandler\n{\n    public static CommandMapper<CommandCell, CommandCellHandler> DatePickerCommandMapper = new(LabelCommandMapper);\n\n    public DatePickerCellHandler() : base(DatePickerMapper, DatePickerCommandMapper)\n    {\n    }\n\n    public DatePickerCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? DatePickerMapper, commandMapper ?? DatePickerCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/DatePickerCell/DatePickerCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class DatePickerCellHandler : LabelCellBaseHandler<DatePickerCell, DatePickerCellView>\n{\n    public static IPropertyMapper<DatePickerCell, DatePickerCellHandler> DatePickerMapper =\n        new PropertyMapper<DatePickerCell, DatePickerCellHandler>(LabelMapper)\n        {\n            [nameof(DatePickerCell.Date)] = MapDate,\n            [nameof(DatePickerCell.Format)] = MapDate,\n            [nameof(DatePickerCell.MaximumDate)] = MapMaximumDate,\n            [nameof(DatePickerCell.MinimumDate)] = MapMinimumDate,\n            [nameof(DatePickerCell.TodayText)] = MapTodayText,\n        };\n\n    private static void MapDate(DatePickerCellHandler handler, DatePickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateDate();\n    }\n\n    private static void MapMaximumDate(DatePickerCellHandler handler, DatePickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateMaximumDate();\n    }\n\n    private static void MapMinimumDate(DatePickerCellHandler handler, DatePickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateMinimumDate();\n    }\n\n    private static void MapTodayText(DatePickerCellHandler handler, DatePickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateTodayText();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/EntryCell/EntryCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class EntryCellHandler : EntryCellBaseHandler<EntryCell, EntryCellView>\n{\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/EntryCell/EntryCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class EntryCellHandler : EntryCellBaseHandler<EntryCell, CellBaseView>\n{\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/EntryCell/EntryCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class EntryCellHandler\n{   \n\n    public EntryCellHandler() : base(EntryMapper, EntryCommandMapper)\n    {\n    }\n\n    public EntryCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? EntryMapper, commandMapper ?? EntryCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/EntryCell/EntryCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class EntryCellHandler : EntryCellBaseHandler<EntryCell, EntryCellView>\n{    \n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/EntryCellBase/EntryCellBaseHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class EntryCellBaseHandler<TvirtualCell, TnativeCell>\n{\n    public static IPropertyMapper<EntryCell, EntryCellBaseHandler<TvirtualCell, TnativeCell>> EntryMapper =\n        new PropertyMapper<EntryCell, EntryCellBaseHandler<TvirtualCell, TnativeCell>>(BasePropertyMapper)\n        {\n            [nameof(EntryCell.ValueText)] = MapValueText,\n            [nameof(EntryCell.ValueTextFontSize)] = MapValueTextFontSize,\n            [nameof(EntryCell.ValueTextFontFamily)] = MapValueTextFont,\n            [nameof(EntryCell.ValueTextFontAttributes)] = MapValueTextFont,\n            [nameof(EntryCell.ValueTextColor)] = MapValueTextColor,\n            [nameof(EntryCell.Keyboard)] = MapKeyboard,\n            [nameof(EntryCell.Placeholder)] = MapPlaceholder,\n            [nameof(EntryCell.PlaceholderColor)] = MapPlaceholder,\n            [nameof(EntryCell.AccentColor)] = MapAccentColor,\n            [nameof(EntryCell.TextAlignment)] = MapTextAlignment,\n            [nameof(EntryCell.IsPassword)] = MapIsPassword,\n        };\n\n    private static void MapValueText(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdateValueText();\n    }\n\n    private static void MapValueTextFontSize(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdateValueTextFontSize();\n        handler.PlatformView.UpdateLayout();\n    }\n\n    private static void MapValueTextFont(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdateValueTextFont();\n        handler.PlatformView.UpdateLayout();\n    }\n\n    private static void MapValueTextColor(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdateValueTextColor();\n        handler.PlatformView.UpdateLayout();\n    }\n\n    private static void MapKeyboard(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdateKeyboard();\n    }\n\n    private static void MapPlaceholder(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdatePlaceholder();\n    }\n\n    private static void MapAccentColor(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdateAccentColor();\n    }\n\n    private static void MapTextAlignment(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdateTextAlignment();\n    }\n\n    private static void MapIsPassword(EntryCellBaseHandler<TvirtualCell,TnativeCell> handler, EntryCell arg2)\n    {\n        handler.PlatformView.UpdateIsPassword();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/EntryCellBase/EntryCellBaseHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class EntryCellBaseHandler<TvirtualCell, TnativeCell>\n{\n    public static IPropertyMapper<EntryCell, EntryCellBaseHandler<TvirtualCell,TnativeCell>> EntryMapper =\n        new PropertyMapper<EntryCell, EntryCellBaseHandler<TvirtualCell, TnativeCell>>(BasePropertyMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/EntryCellBase/EntryCellBaseHandler.cs",
    "content": "﻿using System;\n#if IOS || MACCATALYST\nusing EntryCellView = AiForms.Settings.Platforms.iOS.EntryCellView;\n#elif __ANDROID__\nusing EntryCellView = AiForms.Settings.Platforms.Droid.EntryCellView;\n#elif NET6_0_OR_GREATER\nusing EntryCellView = AiForms.Settings.Handlers.CellBaseView;\n#endif\n\r\nnamespace AiForms.Settings.Handlers;\r\n\r\npublic partial class EntryCellBaseHandler<TvirtualCell, TnativeCell>: CellBaseHandler<TvirtualCell, TnativeCell>\n    where TvirtualCell: EntryCell\n    where TnativeCell: EntryCellView\n{\n    public static CommandMapper<EntryCell, EntryCellBaseHandler<TvirtualCell, TnativeCell>> EntryCommandMapper = new(BaseCommandMapper);\n\n    public EntryCellBaseHandler() : base(EntryMapper, EntryCommandMapper)\n    {\n    }\n\n    public EntryCellBaseHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? EntryMapper, commandMapper ?? EntryCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/EntryCellBase/EntryCellBaseHandler.iOS.cs",
    "content": "﻿using System;\nusing System.Drawing;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class EntryCellBaseHandler<TvirtualCell, TnativeCell>\n{\n    public static IPropertyMapper<EntryCell, EntryCellBaseHandler<TvirtualCell, TnativeCell>> EntryMapper =\n        new PropertyMapper<EntryCell, EntryCellBaseHandler<TvirtualCell, TnativeCell>>(BasePropertyMapper)\n        {\n            [nameof(EntryCell.ValueText)] = MapValueText,\n            [nameof(EntryCell.ValueTextFontFamily)] = MapValueTextFont,\n            [nameof(EntryCell.ValueTextFontSize)] = MapValueTextFont,\n            [nameof(EntryCell.ValueTextFontAttributes)] = MapValueTextFont,\n            [nameof(EntryCell.ValueTextColor)] = MapValueTextColor,\n            [nameof(EntryCell.Keyboard)] = MapKeyboard,\n            [nameof(EntryCell.Placeholder)] = MapPlaceholder,\n            [nameof(EntryCell.PlaceholderColor)] = MapPlaceholder,\n            [nameof(EntryCell.TextAlignment)] = MapTextAlignment,\n            [nameof(EntryCell.IsPassword)] = MapIsPassword,\n            [nameof(EntryCell.ShowDoneButtonOnIOSProperty)] = MapShowDoneButtonOnIOS,\n        };\n\n    private static void MapShowDoneButtonOnIOS(EntryCellBaseHandler<TvirtualCell, TnativeCell> handler, EntryCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateShowDoneButton();\n    }\n\n    private static void MapValueText(EntryCellBaseHandler<TvirtualCell, TnativeCell> handler, EntryCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateValueText();\n    }    \n\n    private static void MapValueTextFont(EntryCellBaseHandler<TvirtualCell, TnativeCell> handler, EntryCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateValueTextFont();\n        handler.PlatformView.UpdateLayout();\n    }\n\n    private static void MapValueTextColor(EntryCellBaseHandler<TvirtualCell, TnativeCell> handler, EntryCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateValueTextColor();\n    }\n\n    private static void MapKeyboard(EntryCellBaseHandler<TvirtualCell, TnativeCell> handler, EntryCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateKeyboard();\n    }\n\n    private static void MapPlaceholder(EntryCellBaseHandler<TvirtualCell, TnativeCell> handler, EntryCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdatePlaceholder();\n    }    \n\n    private static void MapTextAlignment(EntryCellBaseHandler<TvirtualCell, TnativeCell> handler, EntryCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateTextAlignment();\n    }\n\n    private static void MapIsPassword(EntryCellBaseHandler<TvirtualCell, TnativeCell> handler, EntryCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateIsPassword();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/LabelCell/LabelCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class LabelCellHandler: LabelCellBaseHandler<LabelCell, LabelCellView>\n{\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/LabelCell/LabelCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class LabelCellHandler : LabelCellBaseHandler<LabelCell, CellBaseView>\n{    \n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/LabelCell/LabelCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class LabelCellHandler\n{\n    public LabelCellHandler() : base(LabelMapper, LabelCommandMapper)\n    {\n    }\n\n    public LabelCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? LabelMapper, commandMapper ?? LabelCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/LabelCell/LabelCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class LabelCellHandler: LabelCellBaseHandler<LabelCell, LabelCellView>\n{\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/LabelCellBase/LabelCellBaseHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers\n{\n    public partial class LabelCellBaseHandler<TvirtualCell, TnativeCell>\n    {\n        public static IPropertyMapper<LabelCell, LabelCellBaseHandler<TvirtualCell, TnativeCell>> LabelMapper =\n        new PropertyMapper<LabelCell, LabelCellBaseHandler<TvirtualCell, TnativeCell>>(BasePropertyMapper)\n        {\n            [nameof(LabelCell.ValueText)] = MapValueText,\n            [nameof(LabelCell.ValueTextColor)] = MapValueTextColor,\n            [nameof(LabelCell.ValueTextFontSize)] = MapValueTextFontSize,\n            [nameof(LabelCell.ValueTextFontAttributes)] = MapValueTextFont,\n            [nameof(LabelCell.ValueTextFontFamily)] = MapValueTextFont,\n            [nameof(LabelCell.IgnoreUseDescriptionAsValue)] = MapUseDescriptionAsValue,\n        };\n\n        private static void MapValueText(LabelCellBaseHandler<TvirtualCell, TnativeCell> handler, LabelCell cell)\n        {\n            switch (cell)\n            {\n                // disabled ValueTextMapper if cell is PickerCell.\n                case NumberPickerCell:\n                case TimePickerCell:\n                case DatePickerCell:\n                case TextPickerCell:\n                    return;\n            }\n\n            handler.PlatformView.UpdateValueText();\n        }\n\n        private static void MapValueTextColor(LabelCellBaseHandler<TvirtualCell, TnativeCell> handler, LabelCell cell)\n        {\n            handler.PlatformView.UpdateValueTextColor();\n        }\n\n        private static void MapValueTextFontSize(LabelCellBaseHandler<TvirtualCell, TnativeCell> handler, LabelCell cell)\n        {\n            handler.PlatformView.UpdateValueTextFontSize();\n        }\n\n        private static void MapValueTextFont(LabelCellBaseHandler<TvirtualCell, TnativeCell> handler, LabelCell cell)\n        {\n            handler.PlatformView.UpdateValueTextFont();\n        }\n\n        private static void MapUseDescriptionAsValue(LabelCellBaseHandler<TvirtualCell, TnativeCell> handler, LabelCell cell)\n        {\n            handler.PlatformView.UpdateUseDescriptionAsValue();\n        }\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/LabelCellBase/LabelCellBaseHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class LabelCellBaseHandler<TvirtualCell, TnativeCell>\n{\n    public static IPropertyMapper<LabelCell, LabelCellBaseHandler<TvirtualCell, TnativeCell>> LabelMapper =\n    new PropertyMapper<LabelCell, LabelCellBaseHandler<TvirtualCell, TnativeCell>>(BasePropertyMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/LabelCellBase/LabelCellBaseHandler.cs",
    "content": "﻿using System;\n#if IOS || MACCATALYST\nusing LabelCellView = AiForms.Settings.Platforms.iOS.LabelCellView;\n#elif __ANDROID__\nusing LabelCellView = AiForms.Settings.Platforms.Droid.LabelCellView;\n#elif NET6_0_OR_GREATER\nusing LabelCellView = AiForms.Settings.Handlers.CellBaseView;\n#endif\n\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class LabelCellBaseHandler<TvirtualCell, TnativeCell> : CellBaseHandler<TvirtualCell, TnativeCell>\n        where TvirtualCell : LabelCell\n        where TnativeCell : LabelCellView\n{\n    public static CommandMapper<LabelCell, LabelCellBaseHandler<TvirtualCell, TnativeCell>> LabelCommandMapper = new(BaseCommandMapper);\n\n    public LabelCellBaseHandler(): base(LabelMapper, LabelCommandMapper)\n    {\n    }\n\n    public LabelCellBaseHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base (mapper ?? LabelMapper, commandMapper ?? LabelCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/LabelCellBase/LabelCellBaseHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class LabelCellBaseHandler<TvirtualCell, TnativeCell>\n{\n    public static IPropertyMapper<LabelCell, LabelCellBaseHandler<TvirtualCell, TnativeCell>> LabelMapper =\n    new PropertyMapper<LabelCell, LabelCellBaseHandler<TvirtualCell, TnativeCell>>(BasePropertyMapper)\n    {\n        [nameof(LabelCell.ValueText)] = MapValueText,\n        [nameof(LabelCell.ValueTextColor)] = MapValueTextColor,\n        [nameof(LabelCell.ValueTextFontSize)] = MapValueTextFont,\n        [nameof(LabelCell.ValueTextFontAttributes)] = MapValueTextFont,\n        [nameof(LabelCell.ValueTextFontFamily)] = MapValueTextFont,\n    };\n\n\n    private static void MapValueTextColor(LabelCellBaseHandler<TvirtualCell, TnativeCell> handler, LabelCell cell)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateValueTextColor();\n    }\n\n    private static void MapValueText(LabelCellBaseHandler<TvirtualCell, TnativeCell> handler, LabelCell cell)\n    {\n        if (handler.IsDisconnect) return;\n        switch (cell)\n        {\n            // disabled ValueTextMapper if cell is PickerCell.\n            case NumberPickerCell:\n            case TimePickerCell:\n            case DatePickerCell:\n            case TextPickerCell:\n                return;               \n        }\n\n        handler.PlatformView.UpdateValueText();\n    }\n\n    private static void MapValueTextFont(LabelCellBaseHandler<TvirtualCell, TnativeCell> handler, LabelCell cell)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateValueTextFont();\n        handler.PlatformView.UpdateLayout();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/NumberPickerCell/NumberPickerCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class NumberPickerCellHandler : LabelCellBaseHandler<NumberPickerCell, NumberPickerCellView>\n{\n    public static IPropertyMapper<NumberPickerCell, NumberPickerCellHandler> NumberPickerMapper =\n        new PropertyMapper<NumberPickerCell, NumberPickerCellHandler>(LabelMapper)\n        {\n            [nameof(NumberPickerCell.Min)] = MapMin,\n            [nameof(NumberPickerCell.Max)] = MapMax,\n            [nameof(NumberPickerCell.Number)] = MapNumber,\n            [nameof(NumberPickerCell.PickerTitle)] = MapPickerTitle,\n            [nameof(NumberPickerCell.SelectedCommand)] = MapSelectedCommand,\n        };\n\n    private static void MapMin(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        handler.PlatformView.UpdateMin();\n    }\n\n    private static void MapMax(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        handler.PlatformView.UpdateMax();\n    }\n\n    private static void MapNumber(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        handler.PlatformView.UpdateNumber();\n    }\n\n    private static void MapPickerTitle(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        handler.PlatformView.UpdatePickerTitle();\n    }\n\n    private static void MapSelectedCommand(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/NumberPickerCell/NumberPickerCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class NumberPickerCellHandler : LabelCellBaseHandler<NumberPickerCell, CellBaseView>\n{\n    public static IPropertyMapper<NumberPickerCell, NumberPickerCellHandler> NumberPickerMapper =\n        new PropertyMapper<NumberPickerCell, NumberPickerCellHandler>(LabelMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/NumberPickerCell/NumberPickerCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class NumberPickerCellHandler\n{\n    public static CommandMapper<NumberPickerCell, NumberPickerCellHandler> NumberPickerCommandMapper = new(LabelCommandMapper);\n\n    public NumberPickerCellHandler() : base(NumberPickerMapper, NumberPickerCommandMapper)\n    {\n    }\n\n    public NumberPickerCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? NumberPickerMapper, commandMapper ?? NumberPickerCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/NumberPickerCell/NumberPickerCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class NumberPickerCellHandler : LabelCellBaseHandler<NumberPickerCell, NumberPickerCellView>\n{\n    public static IPropertyMapper<NumberPickerCell, NumberPickerCellHandler> NumberPickerMapper =\n        new PropertyMapper<NumberPickerCell, NumberPickerCellHandler>(LabelMapper)\n        {\n            [nameof(NumberPickerCell.Min)] = MapNumberList,\n            [nameof(NumberPickerCell.Max)] = MapNumberList,\n            [nameof(NumberPickerCell.Number)] = MapNumber,\n            [nameof(NumberPickerCell.PickerTitle)] = MapPickerTitle,\n            [nameof(NumberPickerCell.SelectedCommand)] = MapSelectedCommand,\n        };\n\n    private static void MapNumberList(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateNumberList();\n    }\n\n    private static void MapNumber(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateNumber();\n    }\n\n    private static void MapPickerTitle(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateTitle();\n    }\n\n    private static void MapSelectedCommand(NumberPickerCellHandler handler, NumberPickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/RadioCell/RadioCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class RadioCellHandler : CellBaseHandler<RadioCell, RadioCellView>\n{\n    public static IPropertyMapper<RadioCell, RadioCellHandler> RadioMapper =\n        new PropertyMapper<RadioCell, RadioCellHandler>(BasePropertyMapper)\n        {\n            [nameof(RadioCell.AccentColor)] = MapAccentColor,\n        };\n\n    private static void MapAccentColor(RadioCellHandler handler, RadioCell arg2)\n    {\n        handler.PlatformView.UpdateAccentColor();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/RadioCell/RadioCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class RadioCellHandler : CellBaseHandler<RadioCell, CellBaseView>\n{\n    public static IPropertyMapper<RadioCell, RadioCellHandler> RadioMapper =\n        new PropertyMapper<RadioCell, RadioCellHandler>(BasePropertyMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/RadioCell/RadioCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class RadioCellHandler\n{\n    public static CommandMapper<RadioCell, RadioCellHandler> RadioCommandMapper = new(BaseCommandMapper);\n\n    public RadioCellHandler() : base(RadioMapper, RadioCommandMapper)\n    {\n    }\n\n    public RadioCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? RadioMapper, commandMapper ?? RadioCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/RadioCell/RadioCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class RadioCellHandler : CellBaseHandler<RadioCell, RadioCellView>\n{\n    public static IPropertyMapper<RadioCell, RadioCellHandler> RadioMapper =\n        new PropertyMapper<RadioCell, RadioCellHandler>(BasePropertyMapper)\n        {\n            [nameof(RadioCell.AccentColor)] = MapAccentColor,\n        };\n\n    private static void MapAccentColor(RadioCellHandler handler, RadioCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateAccentColor();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SettingsViewHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Extensions;\nusing AiForms.Settings.Platforms.Droid;\nusing Android.Views;\nusing AndroidX.RecyclerView.Widget;\nusing Microsoft.Maui.Handlers;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Handlers;\n\n[Android.Runtime.Preserve(AllMembers = true)]\npublic partial class SettingsViewHandler : ViewHandler<SettingsView, AiRecyclerView>\n{\n    public static IPropertyMapper<SettingsView, SettingsViewHandler> Mapper =\n    new PropertyMapper<SettingsView, SettingsViewHandler>(ViewMapper)\n    {\n        [nameof(SettingsView.SeparatorColor)] = MapSeparatorColor,\n        [nameof(SettingsView.BackgroundColor)] = MapBackgroundColor,\n        [nameof(SettingsView.RowHeight)] = MapRowHeight,\n        [nameof(SettingsView.ScrollToTop)] = MapScrollToTop,\n        [nameof(SettingsView.ScrollToBottom)] = MapScrollToBottom,\n        [nameof(SettingsView.UseDescriptionAsValue)] = MapDataSetChanged,\n        [nameof(SettingsView.HasUnevenRows)] = MapDataSetChanged,\n        [nameof(SettingsView.ShowSectionTopBottomBorder)] = MapInvalidateItemDecorations,\n    };\n\n    protected override AiRecyclerView CreatePlatformView()\n    {        \n        return new AiRecyclerView(Context, VirtualView);\n    }\n\n    protected override void ConnectHandler(AiRecyclerView platformView)\n    {\n        base.ConnectHandler(platformView);\n\n        if (SettingsViewConfiguration.ShouldAutoDisconnect)\n        {\n            VirtualView.AddCleanUpEvent();\n        }\n    }\n\n    protected override void DisconnectHandler(AiRecyclerView platformView)\n    {\n        base.DisconnectHandler(platformView);\n\n        platformView.Dispose();\n    }\n\n    private static void MapSeparatorColor(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView?.UpdateSeparatorColor();\n    }\n\n    private static void MapBackgroundColor(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView?.UpdateBackgroundColor();\n    }\n\n    private static void MapRowHeight(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView?.UpdateRowHeight();\n    }\n\n    private static void MapScrollToTop(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView?.UpdateScrollToTop();\n    }\n\n    private static void MapScrollToBottom(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView?.UpdateScrollToBottom();\n    }\n\n    private static void MapDataSetChanged(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView?.GetAdapter()?.NotifyDataSetChanged();\n    }\n\n    private static void MapInvalidateItemDecorations(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView?.InvalidateItemDecorations();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SettingsViewHandler.Net.cs",
    "content": "﻿using System;\nusing Microsoft.Maui.ApplicationModel.Communication;\nusing Microsoft.Maui.Handlers;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SettingsViewHandler : ViewHandler<SettingsView, View>\n{\n    public static IPropertyMapper<SettingsView, SettingsViewHandler> Mapper =\n    new PropertyMapper<SettingsView, SettingsViewHandler>(ViewMapper);\n\n    protected override View CreatePlatformView()\n    {\n        throw new NotImplementedException();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SettingsViewHandler.cs",
    "content": "﻿using System;\nusing Microsoft.Maui;\n\nnamespace AiForms.Settings.Handlers;\n\r\npublic partial class SettingsViewHandler\n{   \n    public SettingsViewHandler(): base(Mapper)\n    {\n    }\n\n    public SettingsViewHandler(IPropertyMapper mapper = null) : base(mapper ?? Mapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SettingsViewHandler.iOS.cs",
    "content": "﻿using System;\nusing System.Collections.Specialized;\nusing AiForms.Settings.Platforms.iOS;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Handlers;\nusing ObjCRuntime;\nusing UIKit;\nusing Microsoft.Maui.Controls.Compatibility.Platform.iOS;\nusing Microsoft.Maui.Platform;\nusing MobileCoreServices;\nusing AiForms.Settings.Extensions;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SettingsViewHandler: ViewHandler<SettingsView, AiTableView>\n{\n    public static IPropertyMapper<SettingsView, SettingsViewHandler> Mapper =\n    new PropertyMapper<SettingsView, SettingsViewHandler>(ViewMapper)\n    {\n        [nameof(SettingsView.SeparatorColor)] = MapSeparatorColor,\n        [nameof(SettingsView.BackgroundColor)] = MapBackgroundColor,\n        [nameof(SettingsView.RowHeight)] = MapRowHeight,\n        [nameof(SettingsView.ScrollToTop)] = MapScrollToTop,\n        [nameof(SettingsView.ScrollToBottom)] = MapScrollToBottom,\n    };\n\n    internal static readonly string TextHeaderId = \"textHeaderView\";\n    internal static readonly string TextFooterId = \"textFooterView\";\n    internal static readonly string CustomHeaderId = \"customHeaderView\";\n    internal static readonly string CustomFooterId = \"customFooterView\";\n    Page _parentPage;\n    KeyboardInsetTracker _insetTracker;\n    internal static float MinRowHeight = 48;\n    AiTableView _tableview;\n    IDisposable _contentSizeObserver;\n\n    protected override AiTableView CreatePlatformView()\n    {\n        _tableview = new AiTableView(VirtualView);\n\n        VirtualView.CollectionChanged += OnCollectionChanged;\n        VirtualView.SectionCollectionChanged += OnSectionCollectionChanged;\n        VirtualView.SectionPropertyChanged += OnSectionPropertyChanged;\n        VirtualView.CellPropertyChanged += OnCellPropertyChanged;\n\n        _insetTracker = new KeyboardInsetTracker(_tableview, () => PlatformView.Window, insets => PlatformView.ContentInset = PlatformView.ScrollIndicatorInsets = insets, point =>\n        {\n            var offset = PlatformView.ContentOffset;\n            offset.Y += point.Y;\n            PlatformView.SetContentOffset(offset, true);\n        }, this);\n\n        _contentSizeObserver = _tableview.AddObserver(\"contentSize\", NSKeyValueObservingOptions.New, OnContentSizeChanged);\n\n        return _tableview;\n    }   \n\n    protected override void ConnectHandler(AiTableView platformView)\n    {\n        base.ConnectHandler(platformView);\n\n        foreach (var el in VirtualView.GetParentsPath())\n        {\n            if (el is Page page)\n            {\n                _parentPage = page;\n                _parentPage.Appearing += ParentPageAppearing;\n            }\n        }\n\n        if (SettingsViewConfiguration.ShouldAutoDisconnect)\n        {\n            VirtualView.AddCleanUpEvent();\n        }\n    }\n\n    protected override void DisconnectHandler(AiTableView platformView)\n    {\n        if (_parentPage is not null)\n        {\n            _parentPage.Appearing -= ParentPageAppearing;\n            _parentPage = null;\n        }\n\n        _contentSizeObserver?.Dispose();\n        _contentSizeObserver = null;\n\n        VirtualView.CollectionChanged -= OnCollectionChanged;\n        VirtualView.SectionCollectionChanged -= OnSectionCollectionChanged;\n        VirtualView.SectionPropertyChanged -= OnSectionPropertyChanged;\n        VirtualView.CellPropertyChanged -= OnCellPropertyChanged;\n\n        _insetTracker?.Dispose();\n        _insetTracker = null;\n\n        _tableview?.Dispose();\n        _tableview = null;\n\n        base.DisconnectHandler(platformView);\n    }\n\n    void OnContentSizeChanged(NSObservedChange change)\n    {\n        VirtualView.VisibleContentHeight = PlatformView.ContentSize.Height;\n    }\n\n    void ParentPageAppearing(object sender, EventArgs e)\n    {\n        if(_tableview is null)\n        {\n            return;\n        }\n\n        if(_tableview.IndexPathForSelectedRow != null)\n        {\n            _tableview.DeselectRow(_tableview.IndexPathForSelectedRow, true);\n        }        \n    }\n\n    void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        PlatformView.UpdateSections(e);\n    }\n\n    void OnSectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        var sectionIdx = VirtualView.Model.GetSectionIndex((Section)sender);\n        PlatformView.UpdateItems(e, sectionIdx, false);\n    }\n\n    void OnSectionPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        if (e.PropertyName == Section.IsVisibleProperty.PropertyName)\n        {\n            PlatformView.UpdateSectionVisible((Section)sender);\n        }\n        else if (e.PropertyName == TableSectionBase.TitleProperty.PropertyName ||\n                e.PropertyName == Section.HeaderViewProperty.PropertyName ||\n                e.PropertyName == Section.HeaderHeightProperty.PropertyName ||\n                e.PropertyName == Section.FooterTextProperty.PropertyName ||\n                e.PropertyName == Section.FooterViewProperty.PropertyName)\n        {\n            PlatformView.UpdateSectionNoAnimation((Section)sender);\n        }\n        else if (e.PropertyName == Section.FooterVisibleProperty.PropertyName)\n        {\n            PlatformView.UpdateSectionFade((Section)sender);\n        }\n    }\n\n    void OnCellPropertyChanged(object sender, CellPropertyChangedEventArgs e)\n    {\n        if (e.PropertyName == CellBase.IsVisibleProperty.PropertyName)\n        {\n            PlatformView.UpdateCellVisible(e.Section, (CellBase)sender);\n        }\n    }\n\n    private static void MapScrollToBottom(SettingsViewHandler handler, SettingsView sv)\n    {\n        if (sv.ScrollToBottom)\n        {\n            var tv = handler.PlatformView;\n            var sectionIdx = tv.NumberOfSections() - 1;\n            if (sectionIdx < 0)\n            {\n                sv.ScrollToBottom = false;\n                return;\n            }\n\n            var rowIdx = tv.NumberOfRowsInSection(sectionIdx) - 1;\n\n            if (sectionIdx >= 0 && rowIdx >= 0)\n            {\n                tv.ScrollToRow(NSIndexPath.Create(sectionIdx, rowIdx), UITableViewScrollPosition.Top, false);\n            }\n\n            sv.ScrollToBottom = false;\n        }\n    }\n\n    private static void MapScrollToTop(SettingsViewHandler handler, SettingsView sv)\n    {\n        if (sv.ScrollToTop)\n        {\n            var tv = handler.PlatformView;\n            if (tv.NumberOfSections() == 0)\n            {\n                sv.ScrollToTop = false;\n                return;\n            }\n            var sectionIdx = 0;\n            var rows = tv.NumberOfRowsInSection(sectionIdx);\n            if (rows > 0)\n            {\n                tv.SetContentOffset(new CGPoint(0, 0), false);\n            }\n\n            sv.ScrollToTop = false;\n        }\n    }\n\n    private static void MapRowHeight(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView.EstimatedRowHeight = Math.Max((float)sv.RowHeight, MinRowHeight);\n        handler.PlatformView.ReloadData();\n    }\n\n    private static void MapBackgroundColor(SettingsViewHandler handler, SettingsView sv)\n    {\n        if (!sv.BackgroundColor.IsDefault())\n        {\n            handler.PlatformView.BackgroundColor = sv.BackgroundColor.ToPlatform();\n        }\n    }\n\n    private static void MapSeparatorColor(SettingsViewHandler handler, SettingsView sv)\n    {\n        handler.PlatformView.SeparatorColor = sv.SeparatorColor.ToPlatform();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SimpleCheckCell/SimpleCheckCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SimpleCheckCellHandler : CellBaseHandler<SimpleCheckCell, SimpleCheckCellView>\n{\n    private static void MapAccentColor(SimpleCheckCellHandler handler, SimpleCheckCell arg2)\n    {\n        handler.PlatformView.UpdateAccentColor();\n    }\n\n    private static void MapChecked(SimpleCheckCellHandler handler, SimpleCheckCell arg2)\n    {\n        handler.PlatformView.UpdateChecked();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SimpleCheckCell/SimpleCheckCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SimpleCheckCellHandler : CellBaseHandler<SimpleCheckCell, CellBaseView>\n{\n    private static void MapAccentColor(SimpleCheckCellHandler handler, SimpleCheckCell arg2)\n    {\n    }\n\n    private static void MapChecked(SimpleCheckCellHandler handler, SimpleCheckCell arg2)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SimpleCheckCell/SimpleCheckCellHandler.cs",
    "content": "﻿using System;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SimpleCheckCellHandler\n{\n    public static IPropertyMapper<SimpleCheckCell, SimpleCheckCellHandler> SimpleCheckMapper =\n        new PropertyMapper<SimpleCheckCell, SimpleCheckCellHandler>(BasePropertyMapper)\n        {\n            [nameof(SimpleCheckCell.AccentColor)] = MapAccentColor,\n            [nameof(SimpleCheckCell.Checked)] = MapChecked,\n        };\n\n    public static CommandMapper<SimpleCheckCell, SimpleCheckCellHandler> SimpleCheckCommandMapper = new(BaseCommandMapper);\n\n    public SimpleCheckCellHandler() : base(SimpleCheckMapper, SimpleCheckCommandMapper)\n    {\n    }\n\n    public SimpleCheckCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? SimpleCheckMapper, commandMapper ?? SimpleCheckCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SimpleCheckCell/SimpleCheckCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SimpleCheckCellHandler : CellBaseHandler<SimpleCheckCell, SimpleCheckCellView>\n{\n    private static void MapAccentColor(SimpleCheckCellHandler handler, SimpleCheckCell arg2)\n    {\n        handler.PlatformView.UpdateAccentColor();\n    }\n\n    private static void MapChecked(SimpleCheckCellHandler handler, SimpleCheckCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateChecked();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SwitchCell/SwitchCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SwitchCellHandler : CellBaseHandler<SwitchCell, SwitchCellView>\n{\n    public static IPropertyMapper<SwitchCell, SwitchCellHandler> SwitchMapper =\n        new PropertyMapper<SwitchCell, SwitchCellHandler>(BasePropertyMapper)\n        {\n            [nameof(SwitchCell.AccentColor)] = MapAccentColor,\n            [nameof(SwitchCell.On)] = MapOn\n        };\n\n    private static void MapAccentColor(SwitchCellHandler handler, SwitchCell arg2)\n    {\n        handler.PlatformView.UpdateAccentColor();\n    }\n\n    private static void MapOn(SwitchCellHandler handler, SwitchCell arg2)\n    {\n        handler.PlatformView.UpdateOn();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SwitchCell/SwitchCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SwitchCellHandler : CellBaseHandler<SwitchCell, CellBaseView>\n{\n    public static IPropertyMapper<SwitchCell, SwitchCellHandler> SwitchMapper =\n        new PropertyMapper<SwitchCell, SwitchCellHandler>(BasePropertyMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SwitchCell/SwitchCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SwitchCellHandler\n{\n    public static CommandMapper<SwitchCell, SwitchCellHandler> SwitchCommandMapper = new(BaseCommandMapper);\n\n    public SwitchCellHandler() : base(SwitchMapper,SwitchCommandMapper)\n    {\n    }\n\n    public SwitchCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? SwitchMapper, commandMapper ?? SwitchCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/SwitchCell/SwitchCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class SwitchCellHandler : CellBaseHandler<SwitchCell, SwitchCellView>\n{\n    public static IPropertyMapper<SwitchCell, SwitchCellHandler> SwitchMapper =\n        new PropertyMapper<SwitchCell, SwitchCellHandler>(BasePropertyMapper)\n        {\n            [nameof(SwitchCell.AccentColor)] = MapAccentColor,\n            [nameof(SwitchCell.On)] = MapOn\n        };\n\n    private static void MapAccentColor(SwitchCellHandler handler, SwitchCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateAccentColor();\n    }\n\n    private static void MapOn(SwitchCellHandler handler, SwitchCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateOn();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/Template/CellHandler.Android.cs",
    "content": "﻿//using System;\n//using AiForms.Settings.Platforms.Droid;\n\n//namespace AiForms.Settings.Handlers;\n\r\n//public partial class FooCellHandler : CellBaseHandler<FooCell, FooCellView>\n//{\n//    public static IPropertyMapper<FooCell, CellBaseHandler<FooCell, FooCellView>> FooMapper =\n//        new PropertyMapper<FooCell, CellBaseHandler<FooCell, FooCellView>>(BasePropertyMapper)\n//        {\n//        };        \n//}\n\n"
  },
  {
    "path": "SettingsView/Handlers/Template/CellHandler.cs",
    "content": "﻿//using System;\n//namespace AiForms.Settings.Handlers;\n\r\n//public partial class FooCellHandler\n//{\n//    public FooCellHandler() : base(FooMapper)\n//    {\n//    }\n\n//    public FooCellHandler(IPropertyMapper mapper = null) : base(mapper ?? FooMapper)\n//    {\n//    }\n//}\n\n"
  },
  {
    "path": "SettingsView/Handlers/Template/CellHandler.iOS.cs",
    "content": "﻿//using System;\n//using AiForms.Settings.Platforms.iOS;\n\n//namespace AiForms.Settings.Handlers;\n\r\n//public partial class FooCellHandler: CellBaseHandler<FooCell, FooCellView>\n//{\n//    public static IPropertyMapper<FooCell, CellBaseHandler<FooCell, FooCellView>> FooMapper =\n//        new PropertyMapper<FooCell, CellBaseHandler<FooCell, FooCellView>>(BasePropertyMapper)\n//        {\n//        };\n//}\n\n"
  },
  {
    "path": "SettingsView/Handlers/TextPickerCell/TextPickerCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class TextPickerCellHandler : LabelCellBaseHandler<TextPickerCell, TextPickerCellView>\n{\n    public static IPropertyMapper<TextPickerCell, TextPickerCellHandler> TextPickerMapper =\n        new PropertyMapper<TextPickerCell, TextPickerCellHandler>(LabelMapper)\n        {\n            [nameof(TextPickerCell.SelectedItem)] = MapSelectedItem,\n            [nameof(TextPickerCell.PickerTitle)] = MapPickerTitle,\n            [nameof(TextPickerCell.SelectedCommand)] = MapSelectedCommand,\n        };\n\n    private static void MapSelectedItem(TextPickerCellHandler handler, TextPickerCell arg2)\n    {\n        handler.PlatformView.UpdateSelectedItem();\n    }\n\n    private static void MapPickerTitle(TextPickerCellHandler handler, TextPickerCell arg2)\n    {\n        handler.PlatformView.UpdatePickerTitle();\n    }\n\n    private static void MapSelectedCommand(TextPickerCellHandler handler, TextPickerCell arg2)\n    {\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/TextPickerCell/TextPickerCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class TextPickerCellHandler : LabelCellBaseHandler<TextPickerCell, CellBaseView>\n{\n    public static IPropertyMapper<TextPickerCell, TextPickerCellHandler> TextPickerMapper =\n        new PropertyMapper<TextPickerCell, TextPickerCellHandler>(LabelMapper);\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/TextPickerCell/TextPickerCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class TextPickerCellHandler\n{\n    public static CommandMapper<TextPickerCell, TextPickerCellHandler> TextPickerCommandMapper = new(LabelCommandMapper);\n\n    public TextPickerCellHandler() : base(TextPickerMapper, TextPickerCommandMapper)\n    {\n    }\n\n    public TextPickerCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? TextPickerMapper, commandMapper ?? TextPickerCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/TextPickerCell/TextPickerCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class TextPickerCellHandler : LabelCellBaseHandler<TextPickerCell, TextPickerCellView>\n{\n    public static IPropertyMapper<TextPickerCell, TextPickerCellHandler> TextPickerMapper =\n        new PropertyMapper<TextPickerCell, TextPickerCellHandler>(LabelMapper)\n        {\n            [nameof(TextPickerCell.Items)] = MapItems,\n            [nameof(TextPickerCell.SelectedItem)] = MapSelectedItem,\n            [nameof(TextPickerCell.PickerTitle)] = MapPickerTitle,\n            [nameof(TextPickerCell.SelectedCommand)] = MapSelectedCommand,            \n        };\n\n    private static void MapItems(TextPickerCellHandler handler, TextPickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateItems();\n    }\n\n    private static void MapSelectedItem(TextPickerCellHandler handler, TextPickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateSelectedItem();\n    }\n\n    private static void MapPickerTitle(TextPickerCellHandler handler, TextPickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateTitle();\n    }\n\n    private static void MapSelectedCommand(TextPickerCellHandler handler, TextPickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateCommand();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/TimePickerCell/TimePickerCellHandler.Android.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class TimePickerCellHandler : LabelCellBaseHandler<TimePickerCell, TimePickerCellView>\n{\n    public static IPropertyMapper<TimePickerCell, TimePickerCellHandler> TimePickerMapper =\n        new PropertyMapper<TimePickerCell, TimePickerCellHandler>(LabelMapper)\n        {\n            [nameof(TimePickerCell.Time)] = MapTime,\n            [nameof(TimePickerCell.Format)] = MapTime,\n            [nameof(TimePickerCell.PickerTitle)] = MapPickerTitle,\n        };\n\n    private static void MapTime(TimePickerCellHandler handler, TimePickerCell arg2)\n    {\n        handler.PlatformView.UpdateTime();\n    }\n\n    private static void MapPickerTitle(TimePickerCellHandler handler, TimePickerCell arg2)\n    {\n        handler.PlatformView.UpdatePickerTitle();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/TimePickerCell/TimePickerCellHandler.Net.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class TimePickerCellHandler : LabelCellBaseHandler<TimePickerCell, CellBaseView>\n{\n    public static IPropertyMapper<TimePickerCell, TimePickerCellHandler> TimePickerMapper =\n        new PropertyMapper<TimePickerCell, TimePickerCellHandler>(LabelMapper);\n}"
  },
  {
    "path": "SettingsView/Handlers/TimePickerCell/TimePickerCellHandler.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings.Handlers;\n\npublic partial class TimePickerCellHandler\n{\n    public static CommandMapper<TimePickerCell, TimePickerCellHandler> TimePickerCommandMapper = new(LabelCommandMapper);\n\n    public TimePickerCellHandler() : base(TimePickerMapper, TimePickerCommandMapper)\n    {\n    }\n\n    public TimePickerCellHandler(IPropertyMapper mapper = null, CommandMapper commandMapper = null) : base(mapper ?? TimePickerMapper, commandMapper ?? TimePickerCommandMapper)\n    {\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Handlers/TimePickerCell/TimePickerCellHandler.iOS.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.iOS;\n\nnamespace AiForms.Settings.Handlers;\n\npublic partial class TimePickerCellHandler : LabelCellBaseHandler<TimePickerCell, TimePickerCellView>\n{\n    public static IPropertyMapper<TimePickerCell, TimePickerCellHandler> TimePickerMapper =\n        new PropertyMapper<TimePickerCell, TimePickerCellHandler>(LabelMapper)\n        {\n            [nameof(TimePickerCell.Time)] = MapTime,\n            [nameof(TimePickerCell.Format)] = MapTime,\n            [nameof(TimePickerCell.PickerTitle)] = MapPickerTitle,\n        };\n\n    private static void MapTime(TimePickerCellHandler handler, TimePickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdateTime();\n    }\n\n    private static void MapPickerTitle(TimePickerCellHandler handler, TimePickerCell arg2)\n    {\n        if (handler.IsDisconnect) return;\n        handler.PlatformView.UpdatePickerTitle();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/MauiAppBuilderExtension.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings;\n\npublic static class MauiAppBuilderExtension\n{\n    public static MauiAppBuilder UseSettingsView(this MauiAppBuilder builder, bool shouldCallDisconnectHandlerWhenPageUnloaded = false)\n    {\n        builder.ConfigureMauiHandlers(handler =>\n        {\n            handler.AddSettingsViewHandler();\n        });\n\n        SettingsViewConfiguration.ShouldAutoDisconnect = shouldCallDisconnectHandlerWhenPageUnloaded;\n\n        return builder;\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/MauiHandlerExtension.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Handlers;\n\nnamespace AiForms.Settings\n{\n    public static class MauiHandlerExtension\n    {\n        public static void AddSettingsViewHandler(this IMauiHandlersCollection handlers)\n        {\n            handlers.AddHandler(typeof(SettingsView), typeof(SettingsViewHandler));\n            handlers.AddHandler(typeof(LabelCell), typeof(LabelCellHandler));\n            handlers.AddHandler(typeof(ButtonCell), typeof(ButtonCellHandler));\n            handlers.AddHandler(typeof(CheckboxCell), typeof(CheckboxCellHandler));\n            handlers.AddHandler(typeof(CommandCell), typeof(CommandCellHandler));\n            handlers.AddHandler(typeof(DatePickerCell), typeof(DatePickerCellHandler));\n            handlers.AddHandler(typeof(EntryCell), typeof(EntryCellHandler));\n            handlers.AddHandler(typeof(NumberPickerCell), typeof(NumberPickerCellHandler));\n            handlers.AddHandler(typeof(RadioCell), typeof(RadioCellHandler));\n            handlers.AddHandler(typeof(SwitchCell), typeof(SwitchCellHandler));\n            handlers.AddHandler(typeof(TextPickerCell), typeof(TextPickerCellHandler));\n            handlers.AddHandler(typeof(TimePickerCell), typeof(TimePickerCellHandler));\n            handlers.AddHandler(typeof(CustomCell), typeof(CustomCellHandler));\n            handlers.AddHandler(typeof(SimpleCheckCell), typeof(SimpleCheckCellHandler));\n        }\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/AiRecyclerView.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Platforms.Droid;\nusing Android.Content;\nusing Android.Graphics.Drawables;\nusing Android.Runtime;\nusing Android.Util;\nusing Android.Views;\nusing AndroidX.RecyclerView.Widget;\nusing Microsoft.Maui.Controls.Compatibility.Platform.Android;\nusing Microsoft.Maui.Platform;\nusing View = Microsoft.Maui.Controls.View;\nusing AView = Android.Views.View;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class AiRecyclerView : RecyclerView\n{\n    SettingsViewRecyclerAdapter _adapter;\n    SettingsViewLayoutManager _layoutManager;\n    ItemTouchHelper _itemTouchhelper;\n    SettingsViewSimpleCallback _simpleCallback;\n    SVItemdecoration _itemDecoration;\n    Drawable _divider;\n    Page _parentPage;\n    SettingsView _settingsView;\n\n    List<IPlatformViewHandler> _shouldDisposeHandlers = new List<IPlatformViewHandler>();\n    bool _disposed;\n\n    // Fix scrollbar visibility and flash. https://github.com/xamarin/Xamarin.Forms/pull/10893\n    public AiRecyclerView(Context context, SettingsView settingsView) : base(new ContextThemeWrapper(context, Resource.Style.settingsViewTheme),null, Resource.Attribute.settingsViewStyle)\n    {\n        _settingsView = settingsView;\n        NestedScrollingEnabled = false;\n\n        _layoutManager = new SettingsViewLayoutManager(Context, settingsView);\n        SetLayoutManager(_layoutManager);\n\n        _divider = Context.GetDrawable(Resource.Drawable.divider);\n        _itemDecoration = new SVItemdecoration(_divider, settingsView);\n        AddItemDecoration(_itemDecoration);\n\n        Focusable = false;\n        DescendantFocusability = Android.Views.DescendantFocusability.AfterDescendants;\n\n        _adapter = new SettingsViewRecyclerAdapter(Context, settingsView, this);\n        SetAdapter(_adapter);\n\n        _simpleCallback = new SettingsViewSimpleCallback(settingsView, ItemTouchHelper.Up | ItemTouchHelper.Down, 0);\n        _itemTouchhelper = new ItemTouchHelper(_simpleCallback);\n        _itemTouchhelper.AttachToRecyclerView(this);\n\n        settingsView.Root.CollectionChanged += RootCollectionChanged;\n\n        Element elm = settingsView;\n        while (elm != null)\n        {\n            elm = elm.Parent;\n            if (elm is Page)\n            {\n                break;\n            }\n        }\n\n        _parentPage = elm as Page;\n        if (_parentPage != null)\n        {\n            _parentPage.Appearing += ParentPageAppearing;\n        }\n    }\n\n    public AiRecyclerView(Context context, IAttributeSet attrs) : base(context, attrs)\n    {\n    }\n\n    public AiRecyclerView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)\n    {\n    }\n\n    protected AiRecyclerView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)\n    {\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (_disposed) return;\n        _disposed = true;\n\n        if (disposing)\n        {\n            // ステップ1: RecyclerViewからコンポーネントを切り離す\n            // これにより以降のDispose中にRecyclerView経由のコールバックを防止する\n            try { SetAdapter(null); }\n            catch (Exception) { }\n\n            try { SetLayoutManager(null); }\n            catch (Exception) { }\n\n            if (_itemDecoration != null)\n            {\n                try { RemoveItemDecoration(_itemDecoration); }\n                catch (Exception) { }\n            }\n\n            try { _itemTouchhelper?.AttachToRecyclerView(null); }\n            catch (Exception) { }\n\n            // ステップ2: HeaderView/FooterViewをクリーンアップ\n            if (_settingsView?.Root != null)\n            {\n                foreach (var section in _settingsView.Root)\n                {\n                    if (section.HeaderView != null)\n                    {\n                        DisposeChildView(section.HeaderView);\n                    }\n                    if (section.FooterView != null)\n                    {\n                        DisposeChildView(section.FooterView);\n                    }\n                }\n            }\n\n            // ステップ3: 保留中のhandlerを破棄\n            if (_shouldDisposeHandlers != null)\n            {\n                foreach (var handler in _shouldDisposeHandlers)\n                {\n                    // DisconnectHandler()後にPlatformViewがnullになるため、先に参照を保持する\n                    var pv = handler.PlatformView;\n                    handler.DisconnectHandler();\n                    if (pv != null && pv.Handle != IntPtr.Zero)\n                    {\n                        pv.RemoveFromParent();\n                        pv.Dispose();\n                    }\n                }\n            }\n            _shouldDisposeHandlers = null;\n\n            // ステップ4: イベント購読を解除\n            if (_parentPage != null)\n            {\n                _parentPage.Appearing -= ParentPageAppearing;\n                _parentPage = null;\n            }\n\n            if (_settingsView?.Root != null)\n            {\n                _settingsView.Root.CollectionChanged -= RootCollectionChanged;\n            }\n            _settingsView = null;\n\n            // ステップ5: 切り離し済みのコンポーネントをDispose\n            _adapter?.Dispose();\n            _adapter = null;\n            _layoutManager?.Dispose();\n            _layoutManager = null;\n            _simpleCallback?.Dispose();\n            _simpleCallback = null;\n            _itemTouchhelper?.Dispose();\n            _itemTouchhelper = null;\n\n            _itemDecoration?.Dispose();\n            _itemDecoration = null;\n            _divider?.Dispose();\n            _divider = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    void DisposeChildView(View view)\n    {\n        // DisconnectHandler()後にview.Handlerがnullになるため、先に参照を保持する\n        var handler = view.Handler as IPlatformViewHandler;\n        var pv = handler?.PlatformView as AView;\n        handler?.DisconnectHandler();\n        if (pv != null && pv.Handle != IntPtr.Zero)\n        {\n            pv.RemoveFromParent();\n            pv.Dispose();\n        }\n    }\n\n    void ParentPageAppearing(object sender, EventArgs e)\n    {\n        MainThread.BeginInvokeOnMainThread(() => _adapter?.DeselectRow());\n    }\n\n    void RootCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)\n    {\n        if (_disposed) return;\n\n        if (e.OldItems == null)\n        {\n            return;\n        }\n\n        foreach (Section section in e.OldItems)\n        {\n            if (section.HeaderView != null)\n            {\n                var header = (IPlatformViewHandler)section.HeaderView.Handler;\n                if (header != null)\n                {\n                    _shouldDisposeHandlers.Add(header);\n                }\n            }\n            if (section.FooterView != null)\n            {\n                var footer = (IPlatformViewHandler)section.FooterView.Handler;\n                if (footer != null)\n                {\n                    _shouldDisposeHandlers.Add(footer);\n                }\n            }\n        }\n    }\n\n    internal void UpdateSeparatorColor()\n    {\n        if (_disposed || _settingsView == null || _divider == null) return;\n        _divider.SetTint(_settingsView.SeparatorColor.ToPlatform());\n        InvalidateItemDecorations();\n    }\n\n    internal void UpdateRowHeight()\n    {\n        if (_disposed || _settingsView == null) return;\n        if (_settingsView.RowHeight == -1)\n        {\n            _settingsView.RowHeight = 60;\n        }\n        else\n        {\n            _adapter?.NotifyDataSetChanged();\n        }\n    }\n\n    internal void UpdateScrollToTop()\n    {\n        if (_disposed || _settingsView == null || _layoutManager == null) return;\n        if (_settingsView.ScrollToTop)\n        {\n            _layoutManager.ScrollToPosition(0);\n            _settingsView.ScrollToTop = false;\n        }\n    }\n\n    internal void UpdateScrollToBottom()\n    {\n        if (_disposed || _settingsView == null || _layoutManager == null) return;\n        if (_settingsView.ScrollToBottom)\n        {\n            if (_adapter != null)\n            {\n                _layoutManager.ScrollToPosition(_adapter.ItemCount - 1);\n            }\n            _settingsView.ScrollToBottom = false;\n        }\n    }\n\n    internal void UpdateBackgroundColor()\n    {\n        if (_disposed || _settingsView == null) return;\n        if (_settingsView.BackgroundColor.IsNotDefault())\n        {\n            SetBackgroundColor(_settingsView.BackgroundColor.ToPlatform());\n        }\n    }\n}\n\nclass SettingsViewSimpleCallback : ItemTouchHelper.SimpleCallback\n{\n    SettingsView _settingsView;\n    RowInfo _fromInfo;\n    Queue<(RowInfo from, RowInfo to)> _moveHistory = new Queue<(RowInfo from, RowInfo to)>();\n\n    public SettingsViewSimpleCallback(SettingsView settingsView, int dragDirs, int swipeDirs) : base(dragDirs, swipeDirs)\n    {\n        _settingsView = settingsView;\n    }\n\n    public override bool OnMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)\n    {\n        System.Diagnostics.Debug.WriteLine(\"OnMove\");\n        if (!(viewHolder is ContentBodyViewHolder fromContentHolder))\n        {\n            System.Diagnostics.Debug.WriteLine(\"Cannot move no ContentHolder\");\n            return false;\n        }\n\n        var fromPos = viewHolder.AbsoluteAdapterPosition;\n        var toPos = target.AbsoluteAdapterPosition;\n\n        if (fromPos < toPos)\n        {\n            // disallow a Footer when drag is from up to down.\n            if (target is IFooterViewHolder)\n            {\n                System.Diagnostics.Debug.WriteLine(\"Up To Down disallow Footer\");\n                return false;\n            }\n        }\n        else\n        {\n            // disallow a Header when drag is from down to up.\n            if (target is IHeaderViewHolder)\n            {\n                System.Diagnostics.Debug.WriteLine(\"Down To Up disallow Header\");\n                return false;\n            }\n        }\n\n        var toContentHolder = target as ViewHolder;\n\n        var section = fromContentHolder.RowInfo.Section;\n        if (section == null || !section.UseDragSort)\n        {\n            System.Diagnostics.Debug.WriteLine(\"From Section Not UseDragSort\");\n            return false;\n        }\n\n        var toSection = toContentHolder.RowInfo.Section;\n        if (toSection == null || !toSection.UseDragSort)\n        {\n            System.Diagnostics.Debug.WriteLine(\"To Section Not UseDragSort\");\n            return false;\n        }\n\n        var toInfo = toContentHolder.RowInfo;\n        System.Diagnostics.Debug.WriteLine($\"Set ToInfo Section:{_settingsView.Root.IndexOf(toInfo.Section)} Cell:{toInfo.Section.IndexOf(toInfo.Cell)}\");\n\n        var settingsAdapter = recyclerView.GetAdapter() as SettingsViewRecyclerAdapter;\n\n        settingsAdapter.CellMoved(fromPos, toPos); //caches update\n        settingsAdapter.NotifyItemMoved(fromPos, toPos); //rows update\n\n        // save moved changes \n        _moveHistory.Enqueue((_fromInfo, toInfo));\n\n        System.Diagnostics.Debug.WriteLine($\"Move Completed from:{fromPos} to:{toPos}\");\n\n        return true;\n    }\n\n    void DataSourceMoved()\n    {\n        if (!_moveHistory.Any())\n        {\n            return;\n        }\n\n        var cell = _moveHistory.Peek().from.Cell;\n        var section = _moveHistory.Last().to.Section;\n        while (_moveHistory.Any())\n        {\n            var pos = _moveHistory.Dequeue();\n            DataSourceMoved(pos.from, pos.to);\n        }\n\n        _settingsView.SendItemDropped(section, cell);\n    }\n\n    void DataSourceMoved(RowInfo from, RowInfo to)\n    {\n        var fromPos = from.Section.IndexOf(from.Cell);\n        var toPos = to.Section.IndexOf(to.Cell);\n        if (toPos < 0)\n        {\n            // if Header, insert the first.s\n            toPos = 0;\n        }\n\n        if (from.Section.ItemsSource == null)\n        {\n            System.Diagnostics.Debug.WriteLine($\"Update Sections from:{fromPos} to:{toPos}\");\n            var cell = from.Section.DeleteCellWithoutNotify(fromPos);\n            to.Section.InsertCellWithoutNotify(cell, toPos);\n        }\n        else\n        {\n            System.Diagnostics.Debug.WriteLine($\"UpdateSource from:{fromPos} to:{toPos}\");\n            var deletedSet = from.Section.DeleteSourceItemWithoutNotify(fromPos);\n            to.Section.InsertSourceItemWithoutNotify(deletedSet.Cell, deletedSet.Item, toPos);\n        }\n\n        from.Section = to.Section;\n    }\n\n    public override void ClearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)\n    {\n        System.Diagnostics.Debug.WriteLine(\"On ClearView\");\n        base.ClearView(recyclerView, viewHolder);\n\n        viewHolder.ItemView.Alpha = 1.0f;\n        viewHolder.ItemView.ScaleX = 1.0f;\n        viewHolder.ItemView.ScaleY = 1.0f;\n\n        // DataSource Update\n        DataSourceMoved();\n\n        _moveHistory.Clear();\n        _fromInfo = null;\n    }\n\n    public override int GetDragDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)\n    {\n        var contentHolder = viewHolder as ContentBodyViewHolder;\n        if (contentHolder == null)\n        {\n            return 0;\n        }\n\n        var section = contentHolder.RowInfo.Section;\n        if (section == null || !section.UseDragSort)\n        {\n            return 0;\n        }\n\n        if (!contentHolder.RowInfo.Cell.IsEnabled)\n        {\n            return 0;\n        }\n\n        // save start info.\n        _fromInfo = contentHolder.RowInfo;\n        System.Diagnostics.Debug.WriteLine($\"DragDirs Section:{_settingsView.Root.IndexOf(_fromInfo.Section)} Cell:{_fromInfo.Section.IndexOf(_fromInfo.Cell)}\");\n        return base.GetDragDirs(recyclerView, viewHolder);\n    }\n\n    public override void OnSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState)\n    {\n        base.OnSelectedChanged(viewHolder, actionState);\n        if (viewHolder == null)\n        {\n            return;\n        }\n\n        if (actionState == ItemTouchHelper.ActionStateDrag)\n        {\n            viewHolder.ItemView.Alpha = 0.9f;\n            viewHolder.ItemView.ScaleX = 1.04f;\n            viewHolder.ItemView.ScaleY = 1.04f;\n        }\n    }\n\n\n    public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction)\n    {\n        throw new NotImplementedException();\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _settingsView = null;\n            _moveHistory.Clear();\n            _moveHistory = null;\n        }\n        base.Dispose(disposing);\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/ButtonCellView.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\nusing Android.Content;\nusing Android.Runtime;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Button cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class ButtonCellView : CellBaseView\n{\n    internal Action Execute { get; set; }\n    ButtonCell _ButtonCell => Cell as ButtonCell;\n    ICommand _command;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.ButtonCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public ButtonCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        DescriptionLabel.Visibility = Android.Views.ViewStates.Gone;\n    }\n\n    public ButtonCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);        \n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"adapter\">Adapter.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        Execute?.Invoke();\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        base.UpdateCell();\n        //UpdateCommand();\n        //UpdateTitleAlignment();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_command != null)\n            {\n                _command.CanExecuteChanged -= Command_CanExecuteChanged;\n            }\n            Execute = null;\n            _command = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    internal void UpdateTitleAlignment()\n    {\n        TitleLabel.Gravity = _ButtonCell.TitleAlignment.ToGravityFlags();\n    }\n\n    internal void UpdateCommand()\n    {\n        if (_command != null)\n        {\n            _command.CanExecuteChanged -= Command_CanExecuteChanged;\n        }\n\n        _command = _ButtonCell.Command;\n\n        if (_command != null)\n        {\n            _command.CanExecuteChanged += Command_CanExecuteChanged;\n            Command_CanExecuteChanged(_command, System.EventArgs.Empty);\n        }\n\n        Execute = () =>\n        {\n            if (_command == null)\n            {\n                return;\n            }\n            if (_command.CanExecute(_ButtonCell.CommandParameter))\n            {\n                _command.Execute(_ButtonCell.CommandParameter);\n            }\n        };\n\n\n    }\n\n    /// <summary>\n    /// Updates the is enabled.\n    /// </summary>\n    internal override void UpdateIsEnabled()\n    {\n        if (_command != null && !_command.CanExecute(_ButtonCell.CommandParameter))\n        {\n            return;\n        }\n        base.UpdateIsEnabled();\n    }\n\n    void Command_CanExecuteChanged(object sender, EventArgs e)\n    {\n        if (!Cell.IsEnabled)\n        {\n            return;\n        }\n\n        SetEnabledAppearance(_command.CanExecute(_ButtonCell.CommandParameter));\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/CellBaseView.cs",
    "content": "﻿using System;\r\nusing System.ComponentModel;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\nusing Android.Content;\r\nusing Android.Graphics;\r\nusing Android.Graphics.Drawables;\r\nusing Android.Runtime;\r\nusing Android.Util;\r\nusing Android.Views;\r\nusing Android.Widget;\r\nusing Microsoft.Maui.Controls.Platform;\nusing Microsoft.Maui.Platform;\nusing ARelativeLayout = Android.Widget.RelativeLayout;\r\nusing Resource = global::AiForms.Settings.Resource;\r\nusing AiForms.Settings.Extensions;\r\n\r\nnamespace AiForms.Settings.Platforms.Droid;\r\n\r\n/// <summary>\r\n/// Cell base view.\r\n/// </summary>\r\n[Android.Runtime.Preserve(AllMembers = true)]\r\npublic class CellBaseView : ARelativeLayout, IImageSourcePartSetter\r\n{\r\n    CellBase _cell;\r\n    public CellBase Cell\r\n    {\r\n        get { return _cell; }\r\n        set\r\n        {\r\n            if (_cell == value)\r\n                return;\r\n\r\n            if (_cell != null)\r\n            {\r\n                _cell.PropertyChanged -= CellPropertyChanged;\r\n                _imageLoader?.Reset();\n                _imageLoader = null;\r\n            }\r\n            _cell = value;\r\n\r\n            if (_cell != null)\r\n            {\r\n                _cell.PropertyChanged += CellPropertyChanged;\r\n            }\r\n        }\r\n    }\r\n    /// <summary>\r\n    /// Gets the cell parent.\r\n    /// </summary>\r\n    /// <value>The cell parent.</value>\r\n    public SettingsView CellParent => Cell.Parent as SettingsView;\r\n\r\n    /// <summary>\r\n    /// Gets or sets the title label.\r\n    /// </summary>\r\n    /// <value>The title label.</value>\r\n    public TextView TitleLabel { get; set; }\r\n    /// <summary>\r\n    /// Gets or sets the description label.\r\n    /// </summary>\r\n    /// <value>The description label.</value>\r\n    public TextView DescriptionLabel { get; set; }\r\n    /// <summary>\r\n    /// Gets or sets the icon view.\r\n    /// </summary>\r\n    /// <value>The icon view.</value>\r\n    public ImageView IconView { get; set; }\r\n    /// <summary>\r\n    /// Gets or sets the content stack.\r\n    /// </summary>\r\n    /// <value>The content stack.</value>\r\n    public LinearLayout ContentStack { get; set; }\r\n    /// <summary>\r\n    /// Gets or sets the accessory stack.\r\n    /// </summary>\r\n    /// <value>The accessory stack.</value>\r\n    public LinearLayout AccessoryStack { get; set; }\r\n    /// <summary>\r\n    /// Gets the hint label.\r\n    /// </summary>\r\n    /// <value>The hint label.</value>\r\n    public TextView HintLabel { get; private set; }\n\n    IElementHandler IImageSourcePartSetter.Handler => Cell.Handler;\n\n    IImageSourcePart IImageSourcePartSetter.ImageSourcePart => Cell;\n\n    protected Lazy<IFontManager> _fontManager;\r\n    ImageSourcePartLoader _imageLoader;\r\n    /// <summary>\r\n    /// The context.\r\n    /// </summary>\r\n    protected Context _Context;\r\n    CancellationTokenSource _iconTokenSource;\r\n    Android.Graphics.Color _defaultTextColor;\r\n    ColorDrawable _backgroundColor;\r\n    ColorDrawable _selectedColor;\r\n    RippleDrawable _ripple;\r\n    float _defaultFontSize;\r\n    float _iconRadius;\r\n\r\n    /// <summary>\r\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.CellBaseView\"/> class.\r\n    /// </summary>\r\n    /// <param name=\"context\">Context.</param>\r\n    /// <param name=\"cell\">Cell.</param>\r\n    public CellBaseView(Context context, CellBase cell) : base(context)\r\n    {\r\n        _Context = context;\r\n        Cell = cell;\r\n\r\n        CreateContentView();\r\n\r\n        _fontManager = new Lazy<IFontManager>(() =>\n        {\n            return cell.FindMauiContext().Services.GetService<IFontManager>();\n        });\r\n    }\r\n\r\n    public CellBaseView(IntPtr javaReference,JniHandleOwnership transfer) : base(javaReference, transfer) { }\r\n\r\n    protected virtual void CreateContentView()\r\n    {\r\n        var layoutInflater = (LayoutInflater)_Context.GetSystemService(Context.LayoutInflaterService);\r\n        var contentView = layoutInflater.Inflate(Resource.Layout.cellbaseview, this, true);\r\n\r\n        contentView.LayoutParameters = new ViewGroup.LayoutParams(-1, -1);\r\n\r\n        IconView = contentView.FindViewById<ImageView>(Resource.Id.CellIcon);\r\n        TitleLabel = contentView.FindViewById<TextView>(Resource.Id.CellTitle);\r\n        DescriptionLabel = contentView.FindViewById<TextView>(Resource.Id.CellDescription);\r\n        ContentStack = contentView.FindViewById<LinearLayout>(Resource.Id.CellContentStack);\r\n        AccessoryStack = contentView.FindViewById<LinearLayout>(Resource.Id.CellAccessoryView);\r\n        HintLabel = contentView.FindViewById<TextView>(Resource.Id.CellHintText);\r\n\r\n        _backgroundColor = new ColorDrawable();\r\n        _selectedColor = new ColorDrawable(Android.Graphics.Color.Argb(125, 180, 180, 180));\r\n\r\n        var sel = new StateListDrawable();\r\n\r\n        sel.AddState(new int[] { global::Android.Resource.Attribute.StateSelected }, _selectedColor);\r\n        sel.AddState(new int[] { -global::Android.Resource.Attribute.StateSelected }, _backgroundColor);\r\n        sel.SetExitFadeDuration(250);\r\n        sel.SetEnterFadeDuration(250);\r\n\r\n        var rippleColor = Android.Graphics.Color.Rgb(180, 180, 180);\r\n        if (CellParent.SelectedColor.IsNotDefault())\r\n        {\r\n            rippleColor = CellParent.SelectedColor.ToPlatform();\r\n        }\r\n\r\n        _ripple = DrawableUtility.CreateRipple(rippleColor,sel);\r\n\r\n        Background = _ripple;\r\n\r\n        _defaultTextColor = new Android.Graphics.Color(TitleLabel.CurrentTextColor);\r\n        _defaultFontSize = TitleLabel.TextSize;\r\n        \r\n        if (!String.IsNullOrEmpty(Cell.AutomationId)) \r\n        {\r\n            contentView.ContentDescription = Cell.AutomationId;\r\n        }\r\n\r\n    }\r\n\r\n    /// <summary>\r\n    /// Cells the property changed.\r\n    /// </summary>\r\n    /// <param name=\"sender\">Sender.</param>\r\n    /// <param name=\"e\">E.</param>\r\n    public virtual void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\r\n    {        \r\n    }\r\n\r\n    /// <summary>\r\n    /// Parents the property changed.\r\n    /// </summary>\r\n    /// <param name=\"sender\">Sender.</param>\r\n    /// <param name=\"e\">E.</param>\r\n    public virtual void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\r\n    {\r\n        // avoid running the vain process when popping a page.\r\n        if((sender as BindableObject)?.BindingContext == null){\r\n            return;\r\n        }\r\n\r\n        if (e.PropertyName == SettingsView.CellTitleColorProperty.PropertyName)\r\n        {\r\n            UpdateTitleColor();\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellTitleFontSizeProperty.PropertyName)\r\n        {\r\n            UpdateWithForceLayout(UpdateTitleFontSize);\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellTitleFontFamilyProperty.PropertyName ||\r\n                 e.PropertyName == SettingsView.CellTitleFontAttributesProperty.PropertyName)\r\n        {\r\n            UpdateWithForceLayout(UpdateTitleFont);\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellDescriptionColorProperty.PropertyName)\r\n        {\r\n            UpdateDescriptionColor();\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellDescriptionFontSizeProperty.PropertyName)\r\n        {\r\n            UpdateWithForceLayout(UpdateDescriptionFontSize);\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellDescriptionFontFamilyProperty.PropertyName ||\r\n                 e.PropertyName == SettingsView.CellDescriptionFontAttributesProperty.PropertyName)\r\n        {\r\n            UpdateWithForceLayout(UpdateDescriptionFont);\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellBackgroundColorProperty.PropertyName)\r\n        {\r\n            UpdateBackgroundColor();\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellHintTextColorProperty.PropertyName)\r\n        {\r\n            UpdateHintTextColor();\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellHintFontSizeProperty.PropertyName)\r\n        {\r\n            UpdateWithForceLayout(UpdateHintFontSize);\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellHintFontFamilyProperty.PropertyName ||\r\n                 e.PropertyName == SettingsView.CellHintFontAttributesProperty.PropertyName)\r\n        {\r\n            UpdateWithForceLayout(UpdateHintFont);\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellIconSizeProperty.PropertyName)\r\n        {\r\n            UpdateIcon();\r\n        }\r\n        else if (e.PropertyName == SettingsView.CellIconRadiusProperty.PropertyName)\r\n        {\r\n            UpdateIconRadius();\r\n            UpdateIcon(true);\r\n        }\r\n        else if (e.PropertyName == SettingsView.SelectedColorProperty.PropertyName)\r\n        {\r\n            UpdateWithForceLayout(UpdateSelectedColor);\r\n        }\r\n\r\n    }\r\n\r\n    /// <summary>\r\n    /// Sections the property changed.\r\n    /// </summary>\r\n    /// <param name=\"sender\">Sender.</param>\r\n    /// <param name=\"e\">E.</param>\r\n    public virtual void SectionPropertyChanged(object sender, PropertyChangedEventArgs e)\r\n    {\r\n    }\r\n\r\n    /// <summary>\r\n    /// Rows the selected.\r\n    /// </summary>\r\n    /// <param name=\"adapter\">Adapter.</param>\r\n    /// <param name=\"position\">Position.</param>\r\n    public virtual void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\r\n    {\r\n    }\r\n\r\n    /// <summary>\r\n    /// Rows the long pressed.\r\n    /// </summary>\r\n    /// <returns><c>true</c>, if long pressed was rowed, <c>false</c> otherwise.</returns>\r\n    /// <param name=\"adapter\">Adapter.</param>\r\n    /// <param name=\"position\">Position.</param>\r\n    public virtual bool RowLongPressed(SettingsViewRecyclerAdapter adapter, int position)\r\n    {\r\n        return false;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Updates the with force layout.\r\n    /// </summary>\r\n    /// <param name=\"updateAction\">Update action.</param>\r\n    internal void UpdateWithForceLayout(System.Action updateAction)\r\n    {\r\n        updateAction();\r\n        Invalidate();\r\n    }\r\n\r\n    internal void UpdateLayout()\n    {\n        Invalidate();\n    }\r\n\r\n    /// <summary>\r\n    /// Updates the cell.\r\n    /// </summary>\r\n    public virtual void UpdateCell()\r\n    {\r\n        UpdateBackgroundColor();\r\n        UpdateSelectedColor();\r\n        UpdateTitleText();\r\n        UpdateTitleColor();\r\n        UpdateTitleFontSize();\r\n        UpdateTitleFont();\r\n        UpdateDescriptionText();\r\n        UpdateDescriptionColor();\r\n        UpdateDescriptionFontSize();\r\n        UpdateDescriptionFont();\r\n        UpdateHintText();\r\n        UpdateHintTextColor();\r\n        UpdateHintFontSize();\r\n        UpdateHintFont();\r\n\r\n        UpdateIcon();\r\n        UpdateIconRadius();\r\n\r\n        UpdateIsEnabled();\r\n\r\n        Invalidate();\r\n    }\r\n\r\n    internal void UpdateBackgroundColor()\r\n    {\r\n        Selected = false;\r\n\r\n        if (Cell.BackgroundColor.IsNotDefault()) {\r\n            _backgroundColor.Color = Cell.BackgroundColor.ToPlatform();\r\n        }\r\n        else if (CellParent != null && CellParent.CellBackgroundColor.IsNotDefault()) {\r\n            _backgroundColor.Color = CellParent.CellBackgroundColor.ToPlatform();\r\n        }\r\n        else {\r\n            _backgroundColor.Color = Android.Graphics.Color.Transparent;\r\n        }\r\n    }\r\n\r\n    internal void UpdateSelectedColor()\r\n    {\r\n        if (CellParent != null && CellParent.SelectedColor.IsNotDefault()) {\r\n            _selectedColor.Color = CellParent.SelectedColor.MultiplyAlpha(0.5f).ToPlatform();\r\n            _ripple.SetColor(DrawableUtility.GetPressedColorSelector(CellParent.SelectedColor.ToPlatform()));\r\n        }\r\n        else {\r\n            _selectedColor.Color = Android.Graphics.Color.Argb(125, 180, 180, 180);\r\n            _ripple.SetColor(DrawableUtility.GetPressedColorSelector(Android.Graphics.Color.Rgb(180, 180, 180)));\r\n        }\r\n    }\r\n\r\n    internal void UpdateTitleText()\r\n    {\r\n        TitleLabel.Text = Cell.Title;\r\n        //hide TextView right padding when TextView.Text empty.\r\n        TitleLabel.Visibility = string.IsNullOrEmpty(TitleLabel.Text) ? ViewStates.Gone : ViewStates.Visible;\r\n    }\r\n\r\n    internal void UpdateTitleColor()\r\n    {\r\n        if (Cell.TitleColor.IsNotDefault()) {\r\n            TitleLabel.SetTextColor(Cell.TitleColor.ToPlatform());\r\n        }\r\n        else if (CellParent != null && CellParent.CellTitleColor.IsNotDefault()) {\r\n            TitleLabel.SetTextColor(CellParent.CellTitleColor.ToPlatform());\r\n        }\r\n        else {\r\n            TitleLabel.SetTextColor(_defaultTextColor);\r\n        }\r\n    }\r\n\r\n    internal void UpdateTitleFontSize()\r\n    {\r\n        if (Cell.TitleFontSize > 0)\r\n        {\r\n            TitleLabel.SetTextSize(ComplexUnitType.Sp, (float)Cell.TitleFontSize);\r\n        }\r\n        else if (CellParent != null)\r\n        {\r\n            TitleLabel.SetTextSize(ComplexUnitType.Sp, (float)CellParent.CellTitleFontSize);\r\n        }\r\n        else\r\n        {\r\n            TitleLabel.SetTextSize(ComplexUnitType.Sp, _defaultFontSize);\r\n        }\r\n    }\r\n\r\n    internal void UpdateTitleFont()\r\n    {\r\n        var family = Cell.TitleFontFamily ?? CellParent?.CellTitleFontFamily;\r\n        var attr = Cell.TitleFontAttributes ?? CellParent.CellTitleFontAttributes;\r\n        var size = Cell.TitleFontSize > 0 ? Cell.TitleFontSize : CellParent.CellTitleFontSize;\r\n              \r\n        TitleLabel.Typeface = family.ToFont(size, attr).ToTypeface(_fontManager.Value); \r\n    }\r\n\r\n    internal void UpdateDescriptionText()\r\n    {\r\n        DescriptionLabel.Text = Cell.Description;\r\n        DescriptionLabel.Visibility = string.IsNullOrEmpty(DescriptionLabel.Text) ?\r\n            ViewStates.Gone : ViewStates.Visible;\r\n    }\r\n\r\n    internal void UpdateDescriptionFontSize()\r\n    {\r\n        if (Cell.DescriptionFontSize > 0) {\r\n            DescriptionLabel.SetTextSize(ComplexUnitType.Sp, (float)Cell.DescriptionFontSize);\r\n        }\r\n        else if (CellParent != null) {\r\n            DescriptionLabel.SetTextSize(ComplexUnitType.Sp, (float)CellParent.CellDescriptionFontSize);\r\n        }\r\n        else {\r\n            DescriptionLabel.SetTextSize(ComplexUnitType.Sp, _defaultFontSize);\r\n        }\r\n    }\r\n\r\n    internal void UpdateDescriptionFont()\r\n    {\r\n        var family = Cell.DescriptionFontFamily ?? CellParent?.CellDescriptionFontFamily;\r\n        var attr = Cell.DescriptionFontAttributes ?? CellParent.CellDescriptionFontAttributes;\r\n        var size = Cell.DescriptionFontSize > 0 ? Cell.DescriptionFontSize : CellParent.CellDescriptionFontSize;\r\n\r\n        DescriptionLabel.Typeface = family.ToFont(size, attr).ToTypeface(_fontManager.Value);\n    }\r\n\r\n    internal void UpdateDescriptionColor()\r\n    {\r\n        if (Cell.DescriptionColor.IsNotDefault()) {\r\n            DescriptionLabel.SetTextColor(Cell.DescriptionColor.ToPlatform());\r\n        }\r\n        else if (CellParent != null && CellParent.CellDescriptionColor.IsNotDefault()) {\r\n            DescriptionLabel.SetTextColor(CellParent.CellDescriptionColor.ToPlatform());\r\n        }\r\n        else {\r\n            DescriptionLabel.SetTextColor(_defaultTextColor);\r\n        }\r\n    }\r\n\r\n    internal void UpdateHintText()\r\n    {\r\n        var msg = Cell.HintText;\r\n        if (string.IsNullOrEmpty(msg)) {\r\n            HintLabel.Visibility = ViewStates.Gone;\r\n            return;\r\n        }\r\n\r\n        HintLabel.Text = msg;\r\n        HintLabel.Visibility = ViewStates.Visible;\r\n    }\r\n\r\n    internal void UpdateHintTextColor()\r\n    {\r\n        if (Cell.HintTextColor.IsNotDefault()) {\r\n            HintLabel.SetTextColor(Cell.HintTextColor.ToPlatform());\r\n        }\r\n        else if (CellParent != null && CellParent.CellHintTextColor.IsNotDefault()) {\r\n            HintLabel.SetTextColor(CellParent.CellHintTextColor.ToPlatform());\r\n        }\r\n        else {\r\n            HintLabel.SetTextColor(_defaultTextColor);\r\n        }\r\n    }\r\n\r\n    internal void UpdateHintFontSize()\r\n    {\r\n        if (Cell.HintFontSize > 0) {\r\n            HintLabel.SetTextSize(ComplexUnitType.Sp, (float)Cell.HintFontSize);\r\n        }\r\n        else if (CellParent != null) {\r\n            HintLabel.SetTextSize(ComplexUnitType.Sp, (float)CellParent.CellHintFontSize);\r\n        }\r\n        else {\r\n            HintLabel.SetTextSize(ComplexUnitType.Sp, _defaultFontSize);\r\n        }\r\n    }\r\n\r\n    internal void UpdateHintFont()\r\n    {\r\n        var family = Cell.HintFontFamily ?? CellParent?.CellHintFontFamily;\r\n        var attr = Cell.HintFontAttributes ?? CellParent.CellHintFontAttributes;\r\n        var size = Cell.HintFontSize > 0 ? Cell.HintFontSize : CellParent.CellHintFontSize;\r\n\r\n        HintLabel.Typeface = family.ToFont(size, attr).ToTypeface(_fontManager.Value);\r\n    }\r\n\r\n    /// <summary>\r\n    /// Updates the is enabled.\r\n    /// </summary>\r\n    internal virtual void UpdateIsEnabled()\r\n    {\r\n        SetEnabledAppearance(Cell.IsEnabled);\r\n    }\r\n\r\n    internal virtual void UpdateIsVisible()\n    {\n\n    }\r\n\r\n    /// <summary>\r\n    /// Sets the enabled appearance.\r\n    /// </summary>\r\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\r\n    internal virtual void SetEnabledAppearance(bool isEnabled)\r\n    {\r\n        if (isEnabled) {\r\n            Focusable = false;\r\n            DescendantFocusability = Android.Views.DescendantFocusability.AfterDescendants;\r\n            TitleLabel.Alpha = 1f;\r\n            DescriptionLabel.Alpha = 1f;\r\n            IconView.Alpha = 1f;\r\n        }\r\n        else {\r\n            // not to invoke a ripple effect and not to selected\r\n            Focusable = true;\r\n            DescendantFocusability = Android.Views.DescendantFocusability.BlockDescendants;\r\n            // to turn like disabled\r\n            TitleLabel.Alpha = 0.3f;\r\n            DescriptionLabel.Alpha = 0.3f;\r\n            IconView.Alpha = 0.3f;\r\n        }\r\n    }\r\n\r\n    internal void UpdateIconRadius()\r\n    {\r\n        if (Cell.IconRadius >= 0) {\r\n            _iconRadius = _Context.ToPixels(Cell.IconRadius);\r\n        }\r\n        else if (CellParent != null) {\r\n            _iconRadius = _Context.ToPixels(CellParent.CellIconRadius);\r\n        }\r\n    }\r\n\r\n    internal void UpdateIconSize()\r\n    {\r\n        Microsoft.Maui.Graphics.Size size;\r\n        if (Cell.IconSize != default(Microsoft.Maui.Graphics.Size)) {\r\n            size = Cell.IconSize;\r\n        }\r\n        else if (CellParent != null && CellParent.CellIconSize != default(Microsoft.Maui.Graphics.Size)) {\r\n            size = CellParent.CellIconSize;\r\n        }\r\n        else {\r\n            size = new Microsoft.Maui.Graphics.Size(36, 36);\r\n        }\r\n\r\n        IconView.LayoutParameters.Width = (int)_Context.ToPixels(size.Width);\r\n        IconView.LayoutParameters.Height = (int)_Context.ToPixels(size.Height);\r\n    }\r\n\r\n    internal void UpdateIcon(bool forceLoad = false)\r\n    {\r\n        UpdateIconSize();\r\n\r\n        _imageLoader?.Reset();\r\n\r\n        if (IconView.Drawable != null)\n        {\r\n            IconView.SetImageDrawable(null);\r\n            IconView.SetImageBitmap(null);\r\n        }\r\n\r\n        if (Cell.IconSource != null)\n        {\r\n            IconView.Visibility = ViewStates.Visible;\r\n\r\n            _imageLoader = new ImageSourcePartLoader(this);\r\n            _imageLoader?.UpdateImageSourceAsync();\r\n        }\r\n        else\n        {\r\n            IconView.Visibility = ViewStates.Gone;\r\n        }\r\n    }\n\n    void IImageSourcePartSetter.SetImageSource(Drawable platformImage)\n    {\n        IconView?.SetImageDrawable(platformImage);\n    }\r\n\r\n    Bitmap CreateRoundImage(Bitmap image)\r\n    {\r\n        var clipArea = Bitmap.CreateBitmap(image.Width, image.Height, Bitmap.Config.Argb8888);\r\n        var canvas = new Canvas(clipArea);\r\n        var paint = new Android.Graphics.Paint(PaintFlags.AntiAlias);\r\n        canvas.DrawARGB(0, 0, 0, 0);\r\n        canvas.DrawRoundRect(new Android.Graphics.RectF(0, 0, image.Width, image.Height), _iconRadius, _iconRadius, paint);\r\n\r\n\r\n        paint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.SrcIn));\r\n\r\n        var rect = new Android.Graphics.Rect(0, 0, image.Width, image.Height);\r\n        canvas.DrawBitmap(image, rect, rect, paint);\r\n\r\n        image.Recycle();\r\n        image.Dispose();\r\n        image = null;\r\n        canvas.Dispose();\r\n        canvas = null;\r\n        paint.Dispose();\r\n        paint = null;\r\n        rect.Dispose();\r\n        rect = null;\r\n\r\n        return clipArea;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Dispose the specified disposing.\r\n    /// </summary>\r\n    /// <returns>The dispose.</returns>\r\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\r\n    protected override void Dispose(bool disposing)\r\n    {\r\n        if (disposing)\r\n        {\r\n            _imageLoader?.Reset();\r\n            _imageLoader = null;\r\n\r\n            if (CellParent != null)\n            {\n                CellParent.PropertyChanged -= ParentPropertyChanged;\n            }\r\n\r\n            if (_cell != null)\n            {\n                _cell.PropertyChanged -= CellPropertyChanged;\n                if (_cell.Section != null)\n                {\n                    _cell.Section.PropertyChanged -= SectionPropertyChanged;\n                    _cell.Section = null;\n                }\n\n                //CellRenderer.SetRealCell(_cell, null);\n                _cell = null;\n            }           \r\n                       \r\n            HintLabel?.Dispose();\r\n            HintLabel = null;\r\n            TitleLabel?.Dispose();\r\n            TitleLabel = null;\r\n            DescriptionLabel?.Dispose();\r\n            DescriptionLabel = null;\r\n            IconView?.SetImageDrawable(null);\r\n            IconView?.SetImageBitmap(null);\r\n            IconView?.Dispose();\r\n            IconView = null;\r\n            ContentStack?.Dispose();\r\n            ContentStack = null;\r\n            AccessoryStack?.Dispose();\r\n            AccessoryStack = null;\r\n\r\n            _iconTokenSource?.Dispose();\r\n            _iconTokenSource = null;\r\n            _Context = null;\r\n\r\n            _backgroundColor?.Dispose();\r\n            _backgroundColor = null;\r\n            _selectedColor?.Dispose();\r\n            _selectedColor = null;\r\n            _ripple?.Dispose();\r\n            _ripple = null;\r\n\r\n            Background?.Dispose();\r\n            Background = null;\r\n        }\r\n        base.Dispose(disposing);\r\n    }    \n}\r\n\r\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/CheckboxCellView.cs",
    "content": "﻿using System;\nusing Android.Content;\nusing Android.Content.Res;\nusing Android.Graphics.Drawables;\nusing Android.Runtime;\nusing Android.Views;\nusing Android.Widget;\nusing AndroidX.AppCompat.Widget;\nusing Microsoft.Maui.Controls.Compatibility.Platform.Android;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Checkbox cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class CheckboxCellView : CellBaseView, CompoundButton.IOnCheckedChangeListener\n{\n    AppCompatCheckBox _checkbox;\n    CheckboxCell _CheckboxCell => Cell as CheckboxCell;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.CheckboxCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public CheckboxCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        _checkbox = new AppCompatCheckBox(context);\n        _checkbox.SetOnCheckedChangeListener(this);\n        _checkbox.Gravity = Android.Views.GravityFlags.Right;\n\n        var lparam = new LinearLayout.LayoutParams(\n            ViewGroup.LayoutParams.WrapContent,\n            ViewGroup.LayoutParams.WrapContent)\n        {\n            Width = (int)context.ToPixels(30),\n            Height = (int)context.ToPixels(30)\n        };\n\n        using (lparam)\n        {\n            AccessoryStack.AddView(_checkbox, lparam);\n        }\n\n        _checkbox.Focusable = false;\n        Focusable = false;\n        DescendantFocusability = Android.Views.DescendantFocusability.AfterDescendants;\n    }\n\n    public CheckboxCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        //UpdateAccentColor();\n        //UpdateChecked();\n        base.UpdateCell();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"adapter\">Adapter.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        _checkbox.Checked = !_checkbox.Checked;\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _checkbox.SetOnCheckedChangeListener(null);\n            _checkbox.Dispose();\n            _checkbox = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal override void SetEnabledAppearance(bool isEnabled)\n    {\n        if (isEnabled)\n        {\n            _checkbox.Enabled = true;\n            _checkbox.Alpha = 1.0f;\n        }\n        else\n        {\n            _checkbox.Enabled = false;\n            _checkbox.Alpha = 0.3f;\n        }\n        base.SetEnabledAppearance(isEnabled);\n    }\n\n    /// <summary>\n    /// Ons the checked changed.\n    /// </summary>\n    /// <param name=\"buttonView\">Button view.</param>\n    /// <param name=\"isChecked\">If set to <c>true</c> is checked.</param>\n    public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)\n    {\n        _CheckboxCell.Checked = isChecked;\n        buttonView.JumpDrawablesToCurrentState();\n    }\n\n    internal void UpdateChecked()\n    {\n        _checkbox.Checked = _CheckboxCell.Checked;\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_CheckboxCell.AccentColor.IsNotDefault())\n        {\n            ChangeCheckColor(_CheckboxCell.AccentColor.ToPlatform());\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            ChangeCheckColor(CellParent.CellAccentColor.ToPlatform());\n        }\n    }\n\n\n    void ChangeCheckColor(Android.Graphics.Color accent)\n    {\n\n        var colorList = new ColorStateList(\n            new int[][]{\n                    new int[]{global::Android.Resource.Attribute.StateChecked},\n                    new int[]{-global::Android.Resource.Attribute.StateChecked},\n            },\n            new int[]{\n                    accent,\n                    accent\n            }\n        );\n\n        _checkbox.SupportButtonTintList = colorList;\n\n        var rippleColor = new ColorStateList(\n            new int[][]{\n                    new int[]{global::Android.Resource.Attribute.StateChecked},\n                    new int[]{-global::Android.Resource.Attribute.StateChecked}\n            },\n            new int[] {\n                    Android.Graphics.Color.Argb(76,accent.R,accent.G,accent.B),\n                    Android.Graphics.Color.Argb(76, 117, 117, 117)\n            }\n        );\n        var ripple = _checkbox.Background as RippleDrawable;\n        ripple.SetColor(rippleColor);\n        _checkbox.Background = ripple;\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/CommandCellView.cs",
    "content": "﻿using System;\nusing Android.Content;\nusing Android.Runtime;\nusing Android.Views;\nusing Android.Widget;\nusing System.Windows.Input;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Command cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class CommandCellView : LabelCellView\n{\n    internal Action Execute { get; set; }\n    CommandCell _CommandCell => Cell as CommandCell;\n    ICommand _command;\n    ImageView _indicatorView;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.CommandCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public CommandCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        if (!CellParent.ShowArrowIndicatorForAndroid)\n        {\n            return;\n        }\n        if (_CommandCell.HideArrowIndicator)\n        {\n            return;\n        }\n        _indicatorView = new ImageView(context);\n        _indicatorView.SetImageResource(Resource.Drawable.ic_navigate_next);\n\n        var param = new LinearLayout.LayoutParams(\n            ViewGroup.LayoutParams.WrapContent,\n            ViewGroup.LayoutParams.WrapContent)\n        {\n        };\n\n        using (param)\n        {\n            AccessoryStack.AddView(_indicatorView, param);\n        }\n    }\n\n    public CommandCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);        \n    }\n\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        Execute?.Invoke();\n        if (_CommandCell.KeepSelectedUntilBack)\n        {\n            adapter.SelectedRow(this, position);\n        }\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        base.UpdateCell();\n        //UpdateCommand();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_command != null)\n            {\n                _command.CanExecuteChanged -= Command_CanExecuteChanged;\n            }\n            Execute = null;\n            _command = null;\n            _indicatorView?.RemoveFromParent();\n            _indicatorView?.SetImageDrawable(null);\n            _indicatorView?.SetImageBitmap(null);\n            _indicatorView?.Dispose();\n            _indicatorView = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    internal void UpdateCommand()\n    {\n        if (_command != null)\n        {\n            _command.CanExecuteChanged -= Command_CanExecuteChanged;\n        }\n\n        _command = _CommandCell.Command;\n\n        if (_command != null)\n        {\n            _command.CanExecuteChanged += Command_CanExecuteChanged;\n            Command_CanExecuteChanged(_command, System.EventArgs.Empty);\n        }\n\n        Execute = () =>\n        {\n            if (_command == null)\n            {\n                return;\n            }\n            if (_command.CanExecute(_CommandCell.CommandParameter))\n            {\n                _command.Execute(_CommandCell.CommandParameter);\n            }\n        };\n    }\n\n    /// <summary>\n    /// Updates the is enabled.\n    /// </summary>\n    internal override void UpdateIsEnabled()\n    {\n        if (_command != null && !_command.CanExecute(_CommandCell.CommandParameter))\n        {\n            return;\n        }\n        base.UpdateIsEnabled();\n    }\n\n    void Command_CanExecuteChanged(object sender, EventArgs e)\n    {\n        if (!Cell.IsEnabled)\n        {\n            return;\n        }\n\n        SetEnabledAppearance(_command.CanExecute(_CommandCell.CommandParameter));\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/CustomCellView.cs",
    "content": "﻿using System;\nusing Android.Widget;\nusing System.Windows.Input;\nusing Android.Content;\nusing Android.Runtime;\nusing Android.Views;\nusing Microsoft.Maui.Controls.Compatibility;\nusing Microsoft.Maui.Platform;\nusing ARelativeLayout = Android.Widget.RelativeLayout;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\r\n[Android.Runtime.Preserve(AllMembers = true)]\r\npublic class CustomCellView: CellBaseView\n{\n    protected Action Execute { get; set; }\n    protected CustomCell CustomCell => Cell as CustomCell;\n    protected ICommand _command;\n    protected ImageView _indicatorView;\n    protected LinearLayout _coreView;\n    FormsViewContainer _container;\n\n    public CustomCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        if (!CustomCell.ShowArrowIndicator)\n        {\n            return;\n        }\n        _indicatorView = new ImageView(context);\n        _indicatorView.SetImageResource(Resource.Drawable.ic_navigate_next);\n\n        var param = new LinearLayout.LayoutParams(\n            ViewGroup.LayoutParams.WrapContent,\n            ViewGroup.LayoutParams.WrapContent)\n        {\n        };\n\n        using (param)\n        {\n            AccessoryStack.AddView(_indicatorView, param);\n        }\n    }\n\n    public CustomCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    protected override void CreateContentView()\n    {\n        base.CreateContentView();\n\n        _container = new FormsViewContainer(Context);\n\n\n        _coreView = FindViewById<LinearLayout>(Resource.Id.CellBody);\n        ContentStack.RemoveFromParent();\n        DescriptionLabel.RemoveFromParent();\n\n        if (CustomCell.UseFullSize)\n        {\n            IconView.RemoveFromParent();\n            var layout = FindViewById<ARelativeLayout>(Resource.Id.CellLayout);\n            var rMargin = CustomCell.ShowArrowIndicator ? _Context.ToPixels(10) : 0;\n            layout.SetPadding(0, 0, (int)rMargin, 0);\n            _coreView.SetPadding(0, 0, 0, 0);\n        }\n\n        _coreView.AddView(_container);\n    }\n\n    public void UpdateContent()\n    {\n        _container.CustomCell = CustomCell;\n        _container.ContentView = CustomCell.Content;\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        if (!CustomCell.IsSelectable)\n        {\n            return;\n        }\n        Execute?.Invoke();\n        if (CustomCell.KeepSelectedUntilBack)\n        {\n            adapter.SelectedRow(this, position);\n        }\n    }\n\n    public override bool RowLongPressed(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        if (CustomCell.LongCommand == null)\n        {\n            return false;\n        }\n\n        CustomCell.SendLongCommand();\n\n        return true;\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        base.UpdateCell();\n        UpdateContent();\n        //UpdateCommand();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_command != null)\n            {\n                _command.CanExecuteChanged -= Command_CanExecuteChanged;\n            }\n            Execute = null;\n            _command = null;\n            _indicatorView?.RemoveFromParent();\n            _indicatorView?.SetImageDrawable(null);\n            _indicatorView?.SetImageBitmap(null);\n            _indicatorView?.Dispose();\n            _indicatorView = null;\n\n            _coreView?.RemoveFromParent();\n            _coreView?.Dispose();\n            _coreView = null;\n\n            _container?.RemoveFromParent();\n            _container?.Dispose();\n            _container = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    internal void UpdateCommand()\n    {\n        if (_command != null)\n        {\n            _command.CanExecuteChanged -= Command_CanExecuteChanged;\n        }\n\n        _command = CustomCell.Command;\n\n        if (_command != null)\n        {\n            _command.CanExecuteChanged += Command_CanExecuteChanged;\n            Command_CanExecuteChanged(_command, System.EventArgs.Empty);\n        }\n\n        Execute = () => {\n            if (_command == null)\n            {\n                return;\n            }\n            if (_command.CanExecute(CustomCell.CommandParameter))\n            {\n                _command.Execute(CustomCell.CommandParameter);\n            }\n        };\n    }\n\n    /// <summary>\n    /// Updates the is enabled.\n    /// </summary>\n    internal override void UpdateIsEnabled()\n    {\n        if (_command != null && !_command.CanExecute(CustomCell.CommandParameter))\n        {\n            return;\n        }\n        base.UpdateIsEnabled();\n    }\n\n    void Command_CanExecuteChanged(object sender, EventArgs e)\n    {\n        if (!Cell.IsEnabled)\n        {\n            return;\n        }\n\n        SetEnabledAppearance(_command.CanExecute(CustomCell.CommandParameter));\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/DatePickerCellView.cs",
    "content": "﻿using System;\nusing Android.App;\nusing Android.Content;\nusing Android.Runtime;\nusing Microsoft.Maui.Controls.Compatibility.Platform.Android;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Date picker cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class DatePickerCellView : LabelCellView\n{\n    DatePickerCell _datePickerCell => Cell as DatePickerCell;\n    DatePickerDialog _dialog;\n    Context _context;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.DatePickerCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public DatePickerCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        _context = context;\n    }\n\n    public DatePickerCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        base.UpdateCell();\n        //UpdateDate();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"adapter\">Adapter.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        ShowDialog();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_dialog != null)\n            {\n                _dialog.CancelEvent -= OnCancelButtonClicked;\n                _dialog?.Dispose();\n                _dialog = null;\n            }\n        }\n        base.Dispose(disposing);\n    }\n\n    void ShowDialog()\n    {\n        if (_datePickerCell.Date.HasValue)\n        {\n            CreateDatePickerDialog(_datePickerCell.Date.Value.Year, _datePickerCell.Date.Value.Month - 1, _datePickerCell.Date.Value.Day);\n        }\n        else\n        {\n            CreateDatePickerDialog(_datePickerCell.InitialDate.Year, _datePickerCell.InitialDate.Month - 1, _datePickerCell.InitialDate.Day);\n        }\n\n\n\n        UpdateMinimumDate();\n        UpdateMaximumDate();\n\n        if (_datePickerCell.MinimumDate > _datePickerCell.MaximumDate)\n        {\n            throw new ArgumentOutOfRangeException(\n                nameof(DatePickerCell.MaximumDate),\n                \"MaximumDate must be greater than or equal to MinimumDate.\"\n            );\n        }\n\n        _dialog.CancelEvent += OnCancelButtonClicked;\n\n        _dialog.Show();\n\n        if (!_datePickerCell.AndroidButtonColor.IsDefault())\n        {\n            _dialog.GetButton((int)DialogButtonType.Positive).SetTextColor(_datePickerCell.AndroidButtonColor.ToAndroid());\n            _dialog.GetButton((int)DialogButtonType.Negative).SetTextColor(_datePickerCell.AndroidButtonColor.ToAndroid());\n        }\n    }\n\n    void CreateDatePickerDialog(int year, int month, int day)\n    {\n        EventHandler<DatePickerDialog.DateSetEventArgs> callback = (o, e) => {\n            _datePickerCell.Date = e.Date;\n            ClearFocus();\n            if (_dialog != null)\n            {\n                _dialog.CancelEvent -= OnCancelButtonClicked;\n            }\n\n            _dialog = null;\n        };\n\n        if (_datePickerCell.IsAndroidSpinnerStyle)\n        {\n            _dialog = new DatePickerDialog(_context, global::AiForms.Settings.Resource.Style.datePickerDialogSpinnerTheme, callback, year, month, day);\n        }\n        else\n        {\n            _dialog = new DatePickerDialog(_context, callback, year, month, day);\n        }\n    }\n\n    void OnCancelButtonClicked(object sender, EventArgs e)\n    {\n        ClearFocus();\n    }\n\n    internal void UpdateDate()\n    {\n        if (_datePickerCell.Date.HasValue)\n        {\n            var format = _datePickerCell.Format;\n            vValueLabel.Text = _datePickerCell.Date.Value.ToString(format);\n        }\n        else\n        {\n            vValueLabel.Text = string.Empty;\n        }\n    }\n\n    internal void UpdateMaximumDate()\n    {\n        if (_dialog != null)\n        {\n            //when not to specify 23:59:59,last day can't be selected.\n            _dialog.DatePicker.MaxDate = (long)_datePickerCell.MaximumDate.Date.AddHours(23).AddMinutes(59).AddSeconds(59).ToUniversalTime().Subtract(DateTime.MinValue.AddYears(1969)).TotalMilliseconds;\n        }\n    }\n\n    internal void UpdateMinimumDate()\n    {\n        if (_dialog != null)\n        {\n            _dialog.DatePicker.MinDate = (long)_datePickerCell.MinimumDate.ToUniversalTime().Subtract(DateTime.MinValue.AddYears(1969)).TotalMilliseconds;\n        }\n    }\n\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/EntryCellView.cs",
    "content": "﻿using System;\nusing AiForms.Settings.Extensions;\nusing Android.Content;\nusing Android.Content.Res;\nusing Android.OS;\nusing Android.Runtime;\nusing Android.Text;\nusing Android.Text.Method;\nusing Android.Views;\nusing Android.Views.InputMethods;\nusing Android.Widget;\nusing Java.Lang;\nusing Microsoft.Maui.Controls;\nusing Microsoft.Maui.Controls.Compatibility.Platform.Android;\nusing Microsoft.Maui.Controls.Platform;\nusing Microsoft.Maui.Platform;\nusing AiEntryCell = AiForms.Settings.EntryCell;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Entry cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class EntryCellView : CellBaseView, ITextWatcher,\n    TextView.IOnFocusChangeListener, TextView.IOnEditorActionListener\n{\n    AiEntryCell _EntryCell => Cell as AiEntryCell;\n\n    AiEditText _EditText;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.EntryCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public EntryCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        _EditText = new AiEditText(context);\n\n        _EditText.Focusable = true;\n        _EditText.ImeOptions = ImeAction.Done;\n        _EditText.SetOnEditorActionListener(this);\n\n        _EditText.OnFocusChangeListener = this;\n        _EditText.SetSingleLine(true);\n        _EditText.Ellipsize = TextUtils.TruncateAt.End;\n\n        _EditText.InputType |= InputTypes.TextFlagNoSuggestions;  //disabled spell check\n        _EditText.Background.Alpha = 0;  //hide underline\n\n        _EditText.ClearFocusAction = DoneEdit;\n        Click += EntryCellView_Click;\n\n        _EntryCell.Focused += EntryCell_Focused;\n\n        //remove weight and change width due to fill _EditText.\n        var titleParam = TitleLabel.LayoutParameters as LinearLayout.LayoutParams;\n        titleParam.Weight = 0;\n        titleParam.Width = ViewGroup.LayoutParams.WrapContent;\n        titleParam = null;\n\n        var lparams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WrapContent, 1f);\n\n        using (lparams)\n        {\n            ContentStack.AddView(_EditText, lparams);\n        }\n    }\n\n    public EntryCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        //UpdateValueText();\n        //UpdateValueTextColor();\n        //UpdateValueTextFontSize();\n        //UpdateValueTextFont();\n        //UpdateKeyboard();\n        //UpdatePlaceholder();\n        //UpdateAccentColor();\n        //UpdateTextAlignment();\n        //UpdateIsPassword();\n        base.UpdateCell();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);        \n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellValueTextColorProperty.PropertyName)\n        {\n            UpdateValueTextColor();\n        }\n        else if (e.PropertyName == SettingsView.CellValueTextFontSizeProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateValueTextFontSize);\n        }\n        else if (e.PropertyName == SettingsView.CellValueTextFontFamilyProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellValueTextFontAttributesProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateValueTextFont);\n        }\n        else if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            Click -= EntryCellView_Click;\n            _EntryCell.Focused -= EntryCell_Focused;\n            _EditText.RemoveFromParent();\n            _EditText.SetOnEditorActionListener(null);\n            _EditText.RemoveTextChangedListener(this);\n            _EditText.OnFocusChangeListener = null;\n            _EditText.ClearFocusAction = null;\n            _EditText.Dispose();\n            _EditText = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal override void SetEnabledAppearance(bool isEnabled)\n    {\n        if (isEnabled)\n        {\n            _EditText.Enabled = true;\n            _EditText.Alpha = 1.0f;\n        }\n        else\n        {\n            _EditText.Enabled = false;\n            _EditText.Alpha = 0.3f;\n        }\n        base.SetEnabledAppearance(isEnabled);\n    }\n\n    void EntryCellView_Click(object sender, EventArgs e)\n    {\n        _EditText.RequestFocus();\n        ShowKeyboard(_EditText);\n    }\n\n    internal void UpdateValueText()\n    {\n        _EditText.RemoveTextChangedListener(this);\n        if (_EditText.Text != _EntryCell.ValueText)\n        {\n            _EditText.Text = _EntryCell.ValueText;\n        }\n        _EditText.AddTextChangedListener(this);\n    }\n\n    internal void UpdateValueTextFontSize()\n    {\n        if (_EntryCell.ValueTextFontSize > 0)\n        {\n            _EditText.SetTextSize(Android.Util.ComplexUnitType.Sp, (float)_EntryCell.ValueTextFontSize);\n        }\n        else if (CellParent != null)\n        {\n            _EditText.SetTextSize(Android.Util.ComplexUnitType.Sp, (float)CellParent.CellValueTextFontSize);\n        }\n    }\n\n    internal void UpdateValueTextFont()\n    {\n        var family = _EntryCell.ValueTextFontFamily ?? CellParent?.CellValueTextFontFamily;\n        var attr = _EntryCell.ValueTextFontAttributes ?? CellParent.CellValueTextFontAttributes;\n        var size = _EntryCell.ValueTextFontSize > 0 ? _EntryCell.ValueTextFontSize : CellParent.CellValueTextFontSize;\n\n        _EditText.Typeface = family.ToFont(size, attr).ToTypeface(_fontManager.Value);\n    }\n\n    internal void UpdateValueTextColor()\n    {\n        if (_EntryCell.ValueTextColor.IsNotDefault())\n        {\n            _EditText.SetTextColor(_EntryCell.ValueTextColor.ToPlatform());\n        }\n        else if (CellParent != null && CellParent.CellValueTextColor.IsNotDefault())\n        {\n            _EditText.SetTextColor(CellParent.CellValueTextColor.ToPlatform());\n        }\n    }\n\n    internal void UpdateKeyboard()\n    {\n        _EditText.InputType = _EntryCell.Keyboard.ToInputType() | InputTypes.TextFlagNoSuggestions;\n    }\n\n    internal void UpdateIsPassword()\n    {\n        _EditText.TransformationMethod = _EntryCell.IsPassword ? new PasswordTransformationMethod() : null;\n\n    }\n\n    internal void UpdatePlaceholder()\n    {\n        _EditText.Hint = _EntryCell.Placeholder;\n\n        var placeholderColor = _EntryCell.PlaceholderColor.IsDefault() ?\n                                    Android.Graphics.Color.Rgb(210, 210, 210) :\n                                    _EntryCell.PlaceholderColor.ToPlatform();\n        _EditText.SetHintTextColor(placeholderColor);\n    }\n\n    internal void UpdateTextAlignment()\n    {\n        _EditText.Gravity = _EntryCell.TextAlignment.ToGravityFlags();\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_EntryCell.AccentColor.IsNotDefault())\n        {\n            ChangeTextViewBack(_EntryCell.AccentColor.ToPlatform());\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            ChangeTextViewBack(CellParent.CellAccentColor.ToPlatform());\n        }\n    }\n\n    void ChangeTextViewBack(Android.Graphics.Color accent)\n    {\n        var colorlist = new ColorStateList(new int[][]\n        {\n                new int[]{global::Android.Resource.Attribute.StateFocused},\n                new int[]{-global::Android.Resource.Attribute.StateFocused},\n        },\n            new int[] {\n                    Android.Graphics.Color.Argb(255,accent.R,accent.G,accent.B),\n                    Android.Graphics.Color.Argb(255, 200, 200, 200)\n        });\n        _EditText.Background.SetTintList(colorlist);\n    }\n\n\n    bool TextView.IOnEditorActionListener.OnEditorAction(TextView v, ImeAction actionId, Android.Views.KeyEvent e)\n    {\n        if (actionId == ImeAction.Done ||\n                (actionId == ImeAction.ImeNull && e.KeyCode == Keycode.Enter))\n        {\n            HideKeyboard(v);\n            DoneEdit();\n        }\n\n        return true;\n    }\n\n    void DoneEdit()\n    {\n        var entryCell = (IEntryCellController)Cell;\n        //entryCell.SendCompleted();\n        _EditText.ClearFocus();\n        ClearFocus();\n    }\n\n    void HideKeyboard(Android.Views.View inputView)\n    {\n        using (var inputMethodManager = (InputMethodManager)_Context.GetSystemService(Context.InputMethodService))\n        {\n            IBinder windowToken = inputView.WindowToken;\n            if (windowToken != null)\n                inputMethodManager.HideSoftInputFromWindow(windowToken, HideSoftInputFlags.None);\n        }\n    }\n    void ShowKeyboard(Android.Views.View inputView)\n    {\n        using (var inputMethodManager = (InputMethodManager)_Context.GetSystemService(Context.InputMethodService))\n        {\n\n            inputMethodManager.ShowSoftInput(inputView, ShowFlags.Forced);\n            inputMethodManager.ToggleSoftInput(ShowFlags.Forced, HideSoftInputFlags.ImplicitOnly);\n\n        }\n    }\n\n    void ITextWatcher.AfterTextChanged(IEditable s)\n    {\n    }\n\n    void ITextWatcher.BeforeTextChanged(ICharSequence s, int start, int count, int after)\n    {\n    }\n\n    void ITextWatcher.OnTextChanged(ICharSequence s, int start, int before, int count)\n    {\n        if (string.IsNullOrEmpty(_EntryCell.ValueText) && s.Length() == 0)\n        {\n            return;\n        }\n\n        _EntryCell.ValueText = s?.ToString();\n    }\n\n    void IOnFocusChangeListener.OnFocusChange(Android.Views.View v, bool hasFocus)\n    {\n        if (hasFocus)\n        {\n            //show underline when on focus.\n            _EditText.Background.Alpha = 100;\n        }\n        else\n        {\n            //hide underline\n            _EditText.Background.Alpha = 0;\n            // consider as text inpute completed.\n            _EntryCell.SendCompleted();\n        }\n    }\n\n    void EntryCell_Focused(object sender, EventArgs e)\n    {\n        _EditText.RequestFocus();\n        ShowKeyboard(_EditText);\n    }\n\n}\n\ninternal class AiEditText : EditText\n{\n    public Action ClearFocusAction { get; set; }\n    SoftInput _startingMode;\n\n    public AiEditText(Context context) : base(context)\n    {\n    }\n\n    protected override void OnFocusChanged(bool gainFocus, [GeneratedEnum] FocusSearchDirection direction, Android.Graphics.Rect previouslyFocusedRect)\n    {\n        base.OnFocusChanged(gainFocus, direction, previouslyFocusedRect);\n        if (gainFocus)\n        {\n            Post(new Runnable(() =>\n            {\n                SetSelection(Text.Length);\n            }));\n        }\n    }\n\n    public override bool OnKeyPreIme(Keycode keyCode, KeyEvent e)\n    {\n        if (keyCode == Keycode.Back && e.Action == KeyEventActions.Up)\n        {\n            ClearFocus();\n            ClearFocusAction?.Invoke();\n        }\n        return base.OnKeyPreIme(keyCode, e);\n\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/LabelCellView.cs",
    "content": "﻿using System;\nusing Android.Content;\nusing Android.Runtime;\nusing Android.Text;\nusing Android.Views;\nusing Android.Widget;\nusing Microsoft.Maui.Controls.Compatibility.Platform.Android;\nusing System.ComponentModel;\nusing System.ComponentModel.Design.Serialization;\nusing AiForms.Settings.Extensions;\nusing Microsoft.Maui.Controls.Platform;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\r\n[Android.Runtime.Preserve(AllMembers = true)]\r\npublic class LabelCellView: CellBaseView\n{\n    LabelCell _LabelCell => Cell as LabelCell;\n    /// <summary>\n    /// Gets or sets the value label.\n    /// </summary>\n    /// <value>The value label.</value>\n    public TextView ValueLabel { get; set; }\n    /// <summary>\n    /// The v value label.\n    /// </summary>\n    public TextView vValueLabel;\n\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.LabelCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public LabelCellView(Context context, CellBase cell) : base(context, cell)\n    {\n\n        ValueLabel = new TextView(context);\n        ValueLabel.SetSingleLine(true);\n        ValueLabel.Ellipsize = TextUtils.TruncateAt.End;\n        ValueLabel.Gravity = GravityFlags.Right;\n\n        var textParams = new LinearLayout.LayoutParams(\n            ViewGroup.LayoutParams.WrapContent,\n            ViewGroup.LayoutParams.WrapContent)\n        {\n\n        };\n        using (textParams)\n        {\n            ContentStack.AddView(ValueLabel, textParams);\n        }\n\n        UpdateUseDescriptionAsValue();\n    }\n\n    public LabelCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);        \n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n\n        if (e.PropertyName == SettingsView.CellValueTextColorProperty.PropertyName)\n        {\n            UpdateValueTextColor();\n        }\n        else if (e.PropertyName == SettingsView.CellValueTextFontSizeProperty.PropertyName)\n        {\n            UpdateValueTextFontSize();\n        }\n        else if (e.PropertyName == SettingsView.CellValueTextFontFamilyProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellValueTextFontAttributesProperty.PropertyName)\n        {\n            UpdateValueTextFont();\n        }\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        base.UpdateCell();\n        //UpdateUseDescriptionAsValue();  //at first after base\n        //UpdateValueText();\n        //UpdateValueTextColor();\n        //UpdateValueTextFontSize();\n        //UpdateValueTextFont();\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal override void SetEnabledAppearance(bool isEnabled)\n    {\n        if (isEnabled)\n        {\n            ValueLabel.Alpha = 1f;\n        }\n        else\n        {\n            ValueLabel.Alpha = 0.3f;\n        }\n        base.SetEnabledAppearance(isEnabled);\n    }\n\n    internal void UpdateUseDescriptionAsValue()\n    {\n        if (!_LabelCell.IgnoreUseDescriptionAsValue && CellParent != null && CellParent.UseDescriptionAsValue)\n        {\n            vValueLabel = DescriptionLabel;\n            DescriptionLabel.Visibility = ViewStates.Visible;\n            ValueLabel.Visibility = ViewStates.Gone;\n        }\n        else\n        {\n            vValueLabel = ValueLabel;\n            ValueLabel.Visibility = ViewStates.Visible;\n        }\n    }\n\n    /// <summary>\n    /// Updates the value text.\n    /// </summary>\n    internal void UpdateValueText()\n    {\n        vValueLabel.Text = _LabelCell.ValueText;\n    }\n\n    internal void UpdateValueTextFontSize()\n    {\n        if (_LabelCell.ValueTextFontSize > 0)\n        {\n            ValueLabel.SetTextSize(Android.Util.ComplexUnitType.Sp, (float)_LabelCell.ValueTextFontSize);\n        }\n        else if (CellParent != null)\n        {\n            ValueLabel.SetTextSize(Android.Util.ComplexUnitType.Sp, (float)CellParent.CellValueTextFontSize);\n        }\n        Invalidate();\n    }\n\n    internal void UpdateValueTextFont()\n    {\n        var family = _LabelCell.ValueTextFontFamily ?? CellParent?.CellValueTextFontFamily;\n        var attr = _LabelCell.ValueTextFontAttributes ?? CellParent.CellValueTextFontAttributes;\n        var size = _LabelCell.ValueTextFontSize > 0 ? _LabelCell.ValueTextFontSize : CellParent.CellValueTextFontSize;\n\n        ValueLabel.Typeface = family.ToFont(size, attr).ToTypeface(_fontManager.Value);\n        Invalidate();\n    }\n\n    internal void UpdateValueTextColor()\n    {\n        if (_LabelCell.ValueTextColor.IsNotDefault())\n        {\n            ValueLabel.SetTextColor(_LabelCell.ValueTextColor.ToPlatform());\n        }\n        else if (CellParent != null && CellParent.CellValueTextColor.IsNotDefault())\n        {\n            ValueLabel.SetTextColor(CellParent.CellValueTextColor.ToPlatform());\n        }\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            ValueLabel?.Dispose();\n            ValueLabel = null;\n            vValueLabel = null;\n        }\n        base.Dispose(disposing);\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/NumberPickerCellView.cs",
    "content": "﻿using System;\nusing Android.Content;\nusing Android.Runtime;\nusing Android.Text;\nusing Android.Views;\nusing Android.Widget;\nusing Java.Lang;\nusing System.Windows.Input;\nusing APicker = Android.Widget.NumberPicker;\nusing Exception = System.Exception;\nusing Object = Java.Lang.Object;\nusing String = System.String;\nusing Android.App;\nusing Java.Lang.Reflect;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Number picker cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class NumberPickerCellView : LabelCellView\n{\n    NumberPickerCell _NumberPickerCell => Cell as NumberPickerCell;\n    APicker _picker;\n    AlertDialog _dialog;\n    Context _context;\n    string _title;\n    ICommand _command;\n    int _max;\n    int _min;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.NumberPickerCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public NumberPickerCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        _context = context;\n    }\n\n    public NumberPickerCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);        \n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"adapter\">Adapter.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        CreateDialog();\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        base.UpdateCell();\n        //UpdateMin();\n        //UpdateMax();\n        //UpdatePickerTitle();\n        //UpdateNumber();\n        //UpdateCommand();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            DestroyDialog();\n            _context = null;\n            _command = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    internal void UpdateMin()\n    {\n        _min = _NumberPickerCell.Min;\n    }\n\n    internal void UpdateMax()\n    {\n        _max = _NumberPickerCell.Max;\n    }\n\n    internal void UpdateNumber()\n    {\n        vValueLabel.Text = FormatNumber(_NumberPickerCell.Number);\n    }\n\n    private string FormatNumber(int? number)\n    {\n        return number.HasValue && !String.IsNullOrEmpty(_NumberPickerCell.Unit)\n            ? $\"{number} {_NumberPickerCell.Unit}\"\n            : number?.ToString() ?? \"\";\n    }\n\n    internal void UpdatePickerTitle()\n    {\n        _title = _NumberPickerCell.PickerTitle;\n    }\n\n    internal void UpdateCommand()\n    {\n        _command = _NumberPickerCell.SelectedCommand;\n    }\n\n    void CreateDialog()\n    {\n        _picker = new APicker(_context);\n        _picker.MinValue = _min;\n        _picker.MaxValue = _max;\n        if (_NumberPickerCell.Number.HasValue)\n        {\n            _picker.Value = _NumberPickerCell.Number.Value;\n        }\n\n        if (!String.IsNullOrEmpty(_NumberPickerCell.Unit))\n        {\n            _picker.SetFormatter(new UnitFormatter(_NumberPickerCell.Unit));\n            ApplyInitialFormattingBugfix(_picker);\n        }\n\n        if (_dialog == null)\n        {\n            using (var builder = new AlertDialog.Builder(_context))\n            {\n\n                builder.SetTitle(_title);\n\n                Android.Widget.FrameLayout parent = new Android.Widget.FrameLayout(_context);\n                parent.AddView(_picker, new Android.Widget.FrameLayout.LayoutParams(\n                        ViewGroup.LayoutParams.WrapContent,\n                        ViewGroup.LayoutParams.WrapContent,\n                       GravityFlags.Center));\n                builder.SetView(parent);\n\n\n                builder.SetNegativeButton(global::Android.Resource.String.Cancel, (o, args) =>\n                {\n                    ClearFocus();\n                });\n                builder.SetPositiveButton(global::Android.Resource.String.Ok, (o, args) =>\n                {\n                    _NumberPickerCell.Number = _picker.Value;\n                    _command?.Execute(_picker.Value);\n                    ClearFocus();\n                });\n\n                _dialog = builder.Create();\n            }\n            _dialog.SetCanceledOnTouchOutside(true);\n            _dialog.DismissEvent += (ss, ee) =>\n            {\n                DestroyDialog();\n            };\n\n            _dialog.Show();\n        }\n\n    }\n\n    // see bug https://stackoverflow.com/questions/17708325/android-numberpicker-with-formatter-doesnt-format-on-first-rendering/54083214#54083214\n    // and https://issuetracker.google.com/issues/36952035\n    private static void ApplyInitialFormattingBugfix(APicker picker)\n    {\n        try\n        {\n            Class klass = Java.Lang.Class.FromType(typeof(NumberPicker));\n            Field f = klass.GetDeclaredField(\"mInputText\");\n            f.Accessible = true;\n            EditText inputText = (EditText)f.Get(picker);\n            inputText.SetFilters(new IInputFilter[0]);\n        }\n        catch (Exception)\n        {\n            // silently ignore this\n        }\n    }\n\n    void DestroyDialog()\n    {\n        if (_dialog != null)\n        {\n            // Set _dialog to null to avoid racing attempts to destroy dialog - e.g. in response to dismiss event\n            var dialog = _dialog;\n            _dialog = null;\n            _picker.RemoveFromParent();\n            _picker.Dispose();\n            _picker = null;\n            // Dialog.Dispose() does not close an open dialog view so explicitly dismiss it before disposing\n            dialog.Dismiss();\n            dialog.Dispose();\n        }\n    }\n}\n\ninternal class UnitFormatter : Object, NumberPicker.IFormatter\n{\n    private readonly string _unit;\n\n    public UnitFormatter(string unit)\n    {\n        _unit = unit;\n    }\n\n    public string Format(int value)\n    {\n        return value + \" \" + _unit;\n    }\n}"
  },
  {
    "path": "SettingsView/Native/Android/Cells/RadioCellView.cs",
    "content": "﻿using System;\nusing Android.Content;\nusing Android.Runtime;\nusing Android.Views;\nusing Android.Widget;\nusing Microsoft.Maui.Controls.Compatibility.Platform.Android;\nusing System.ComponentModel;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Radio cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class RadioCellView : CellBaseView\n{\n    SimpleCheck _simpleCheck;\n    RadioCell _radioCell => Cell as RadioCell;\n\n    private object SelectedValue\n    {\n        get\n        {\n            return RadioCell.GetSelectedValue(_radioCell.Section) ?? RadioCell.GetSelectedValue(CellParent);\n        }\n        set\n        {\n            if (RadioCell.GetSelectedValue(_radioCell.Section) != null)\n            {\n                RadioCell.SetSelectedValue(_radioCell.Section, value);\n            }\n            else\n            {\n                RadioCell.SetSelectedValue(CellParent, value);\n            }\n        }\n    }\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.RadioCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public RadioCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        _simpleCheck = new SimpleCheck(context);\n        _simpleCheck.Focusable = false;\n\n        var lparam = new LinearLayout.LayoutParams(\n            ViewGroup.LayoutParams.WrapContent,\n            ViewGroup.LayoutParams.WrapContent)\n        {\n            Width = (int)context.ToPixels(30),\n            Height = (int)context.ToPixels(30)\n        };\n\n        using (lparam)\n        {\n            AccessoryStack.AddView(_simpleCheck, lparam);\n        }\n    }\n\n    public RadioCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _simpleCheck.RemoveFromParent();\n            _simpleCheck.Dispose();\n            _simpleCheck = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        //UpdateAccentColor();\n        UpdateSelectedValue();\n        base.UpdateCell();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }\n        else if (e.PropertyName == RadioCell.SelectedValueProperty.PropertyName)\n        {\n            UpdateSelectedValue();\n        }\n    }\n\n    /// <summary>\n    /// Sections the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void SectionPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.SectionPropertyChanged(sender, e);\n        if (e.PropertyName == RadioCell.SelectedValueProperty.PropertyName)\n        {\n            UpdateSelectedValue();\n        }\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"adapter\">Adapter.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        if (!_simpleCheck.Selected)\n        {\n            SelectedValue = _radioCell.Value;\n        }\n    }\n\n    void UpdateSelectedValue()\n    {\n        bool result;\n        if (_radioCell.Value.GetType().IsValueType || _radioCell.Value is string)\n        {\n            result = object.Equals(_radioCell.Value, SelectedValue);\n        }\n        else\n        {\n            result = object.ReferenceEquals(_radioCell.Value, SelectedValue);\n        }\n\n        _simpleCheck.Selected = result;\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_radioCell.AccentColor.IsNotDefault())\n        {\n            _simpleCheck.Color = _radioCell.AccentColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            _simpleCheck.Color = CellParent.CellAccentColor.ToPlatform();\n        }\n        _simpleCheck.Invalidate();\n    }\n}"
  },
  {
    "path": "SettingsView/Native/Android/Cells/SimpleCheck.cs",
    "content": "﻿using System;\nusing Android.Graphics;\nusing Microsoft.Maui.Graphics;\nusing Microsoft.Maui.Platform;\nusing AView = Android.Views.View;\nusing Color = Android.Graphics.Color;\nusing Paint = Android.Graphics.Paint;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class SimpleCheck : AView\n{\n    /// <summary>\n    /// Gets or sets the color.\n    /// </summary>\n    /// <value>The color.</value>\n    public Color Color { get; set; }\n    Paint _paint = new Paint();\n    Android.Content.Context _context;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.SimpleCheck\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    public SimpleCheck(Android.Content.Context context) : base(context)\n    {\n        _context = context;\n        SetWillNotDraw(false);\n    }\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.Droid.SimpleCheck\"/> is selected.\n    /// </summary>\n    /// <value><c>true</c> if selected; otherwise, <c>false</c>.</value>\n    public override bool Selected\n    {\n        get\n        {\n            return base.Selected;\n        }\n        set\n        {\n            base.Selected = value;\n            Invalidate();\n        }\n    }\n\n    /// <summary>\n    /// Ons the draw.\n    /// </summary>\n    /// <param name=\"canvas\">Canvas.</param>\n    protected override void OnDraw(Canvas canvas)\n    {\n        base.OnDraw(canvas);\n\n        if (!base.Selected)\n        {\n            return;\n        }\n\n        _paint.SetStyle(Paint.Style.Stroke);\n        _paint.Color = Color;\n        _paint.StrokeWidth = _context.ToPixels(2);\n        _paint.AntiAlias = true;\n\n        var fromX = 22f / 100f * canvas.Width;\n        var fromY = 52f / 100f * canvas.Height;\n        var toX = 38f / 100f * canvas.Width;\n        var toY = 68f / 100f * canvas.Height;\n\n        canvas.DrawLine(fromX, fromY, toX, toY, _paint);\n\n        fromX = 36f / 100f * canvas.Width;\n        fromY = 66f / 100f * canvas.Height;\n\n        toX = 74f / 100f * canvas.Width;\n        toY = 28f / 100f * canvas.Height;\n\n        canvas.DrawLine(fromX, fromY, toX, toY, _paint);\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _paint?.Dispose();\n            _paint = null;\n            _context = null;\n        }\n        base.Dispose(disposing);\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/SimpleCheckCellView.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing Android.Content;\nusing Android.Views;\nusing Android.Widget;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\r\n[Android.Runtime.Preserve(AllMembers = true)]\r\npublic class SimpleCheckCellView: CellBaseView\n{\n    SimpleCheck _checkView;\n    SimpleCheckCell _simpleCheckCell => Cell as SimpleCheckCell;\n\n    public SimpleCheckCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        _checkView = new SimpleCheck(context);\n        _checkView.Focusable = false;\n\n        var lparam = new LinearLayout.LayoutParams(\n            ViewGroup.LayoutParams.WrapContent,\n            ViewGroup.LayoutParams.WrapContent)\n        {\n            Width = (int)context.ToPixels(30),\n            Height = (int)context.ToPixels(30)\n        };\n\n        using (lparam)\n        {\n            AccessoryStack.AddView(_checkView, lparam);\n        }\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _checkView.RemoveFromParent();\n            _checkView.Dispose();\n            _checkView = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    public override void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }\n    }\n\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        base.RowSelected(adapter, position);\n    }\n\n    internal void UpdateChecked()\n    {\n        _checkView.Selected = _simpleCheckCell.Checked;\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_simpleCheckCell.AccentColor.IsNotDefault())\n        {\n            _checkView.Color = _simpleCheckCell.AccentColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            _checkView.Color = CellParent.CellAccentColor.ToPlatform();\n        }\n        _checkView.Invalidate();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/Cells/SwitchCellView.cs",
    "content": "﻿using System;\nusing Android.Content;\nusing Android.Content.Res;\nusing Android.Graphics.Drawables;\nusing Android.Runtime;\nusing Android.Views;\nusing Android.Widget;\nusing AndroidX.AppCompat.Widget;\nusing Microsoft.Maui.Controls.Compatibility.Platform.Android;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Switch cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class SwitchCellView : CellBaseView, CompoundButton.IOnCheckedChangeListener\n{\n    SwitchCompat _switch { get; set; }\n    SwitchCell _SwitchCell => Cell as SwitchCell;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.SwitchCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public SwitchCellView(Context context, CellBase cell) : base(context, cell)\n    {\n\n        _switch = new SwitchCompat(context);\n\n        _switch.SetOnCheckedChangeListener(this);\n        _switch.Gravity = Android.Views.GravityFlags.Right | GravityFlags.CenterVertical;\n\n        var switchParam = new LinearLayout.LayoutParams(\n            ViewGroup.LayoutParams.WrapContent,\n            ViewGroup.LayoutParams.WrapContent)\n        {\n        };\n\n        using (switchParam)\n        {\n            AccessoryStack.AddView(_switch, switchParam);\n        }\n\n        _switch.Focusable = false;\n        Focusable = false;\n        DescendantFocusability = Android.Views.DescendantFocusability.AfterDescendants;\n    }\n\n    public SwitchCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        //UpdateAccentColor();\n        //UpdateOn();\n        base.UpdateCell();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }\n    }\n\n    /// <summary>\n    /// Ons the checked changed.\n    /// </summary>\n    /// <param name=\"buttonView\">Button view.</param>\n    /// <param name=\"isChecked\">If set to <c>true</c> is checked.</param>\n    public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)\n    {\n        _SwitchCell.On = isChecked;\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"adapter\">Adapter.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        _switch.Checked = !_switch.Checked;\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _switch.SetOnCheckedChangeListener(null);\n            _switch.Background?.Dispose();\n            _switch.Background = null;\n            _switch.ThumbDrawable?.Dispose();\n            _switch.ThumbDrawable = null;\n            _switch.Dispose();\n            _switch = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal override void SetEnabledAppearance(bool isEnabled)\n    {\n        if (isEnabled)\n        {\n            _switch.Enabled = true;\n            _switch.Alpha = 1.0f;\n        }\n        else\n        {\n            _switch.Enabled = false;\n            _switch.Alpha = 0.3f;\n        }\n        base.SetEnabledAppearance(isEnabled);\n    }\n\n    internal void UpdateOn()\n    {\n        _switch.Checked = _SwitchCell.On;\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_SwitchCell.AccentColor.IsNotDefault())\n        {\n            ChangeSwitchColor(_SwitchCell.AccentColor.ToPlatform());\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            ChangeSwitchColor(CellParent.CellAccentColor.ToPlatform());\n        }\n    }\n\n    void ChangeSwitchColor(Android.Graphics.Color accent)\n    {\n        var trackColors = new ColorStateList(new int[][]\n              {\n                            new int[]{global::Android.Resource.Attribute.StateChecked},\n                            new int[]{-global::Android.Resource.Attribute.StateChecked},\n              },\n             new int[] {\n                            Android.Graphics.Color.Argb(76,accent.R,accent.G,accent.B),\n                            Android.Graphics.Color.Argb(76, 117, 117, 117)\n              });\n\n\n        _switch.TrackDrawable.SetTintList(trackColors);\n\n        var thumbColors = new ColorStateList(new int[][]\n             {\n                            new int[]{global::Android.Resource.Attribute.StateChecked},\n                            new int[]{-global::Android.Resource.Attribute.StateChecked},\n             },\n            new int[] {\n                            accent,\n                            Android.Graphics.Color.Argb(255, 244, 244, 244)\n             });\n\n        _switch.ThumbDrawable.SetTintList(thumbColors);\n\n        var ripple = _switch.Background as RippleDrawable;\n        ripple.SetColor(trackColors);\n    }\n}"
  },
  {
    "path": "SettingsView/Native/Android/Cells/TextPickerCellView.cs",
    "content": "﻿using System;\nusing Android.Content;\nusing Android.Runtime;\nusing Android.Views;\nusing System.Windows.Input;\nusing APicker = Android.Widget.NumberPicker;\nusing Android.App;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Text picker cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class TextPickerCellView : LabelCellView\n{\n    TextPickerCell _TextPickerCell => Cell as TextPickerCell;\n    APicker _picker;\n    AlertDialog _dialog;\n    Context _context;\n    string _title;\n    ICommand _command;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.TextPickerCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public TextPickerCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        _context = context;\n    }\n\n    public TextPickerCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"adapter\">Adapter.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        CreateDialog();\n    }\n\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        base.UpdateCell();\n        //UpdatePickerTitle();\n        //UpdateSelectedItem();\n        //UpdateCommand();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            DestroyDialog();\n            _context = null;\n            _command = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    internal void UpdateSelectedItem()\n    {\n        vValueLabel.Text = _TextPickerCell.SelectedItem?.ToString();\n    }\n\n    internal void UpdatePickerTitle()\n    {\n        _title = _TextPickerCell.PickerTitle;\n    }\n\n    internal void UpdateCommand()\n    {\n        _command = _TextPickerCell.SelectedCommand;\n    }\n\n    void CreateDialog()\n    {\n        if (_TextPickerCell.Items == null || _TextPickerCell.Items.Count == 0)\n        {\n            return;\n        }\n\n        var displayValues = _TextPickerCell.Items.Cast<object>().Select(x => x.ToString()).ToArray();\n\n        _picker = new APicker(_context);\n        _picker.DescendantFocusability = DescendantFocusability.BlockDescendants;\n        _picker.MinValue = 0;\n        _picker.MaxValue = _TextPickerCell.Items.Count - 1;\n        _picker.SetDisplayedValues(displayValues);\n        _picker.Value = Math.Max(_TextPickerCell.Items.IndexOf(_TextPickerCell.SelectedItem), 0);\n        _picker.WrapSelectorWheel = _TextPickerCell.IsCircularPicker;\n\n        if (_dialog == null)\n        {\n            using (var builder = new AlertDialog.Builder(_context))\n            {\n\n                builder.SetTitle(_title);\n\n                Android.Widget.FrameLayout parent = new Android.Widget.FrameLayout(_context);\n                parent.AddView(_picker, new Android.Widget.FrameLayout.LayoutParams(\n                        ViewGroup.LayoutParams.WrapContent,\n                        ViewGroup.LayoutParams.WrapContent,\n                       GravityFlags.Center));\n                builder.SetView(parent);\n\n\n                builder.SetNegativeButton(global::Android.Resource.String.Cancel, (o, args) => {\n                    ClearFocus();\n                });\n                builder.SetPositiveButton(global::Android.Resource.String.Ok, (o, args) => {\n                    _TextPickerCell.SelectedItem = _TextPickerCell.Items[_picker.Value];\n                    _command?.Execute(_TextPickerCell.Items[_picker.Value]);\n                    ClearFocus();\n                });\n\n                _dialog = builder.Create();\n            }\n            _dialog.SetCanceledOnTouchOutside(true);\n            _dialog.DismissEvent += (ss, ee) => {\n                DestroyDialog();\n            };\n\n            _dialog.Show();\n        }\n\n    }\n\n    void DestroyDialog()\n    {\n        if (_dialog != null)\n        {\n            // Set _dialog to null to avoid racing attempts to destroy dialog - e.g. in response to dismiss event\n            var dialog = _dialog;\n            _dialog = null;\n            _picker.RemoveFromParent();\n            _picker.Dispose();\n            _picker = null;\n            // Dialog.Dispose() does not close an open dialog view so explicitly dismiss it before disposing\n            dialog.Dismiss();\n            dialog.Dispose();\n        }\n    }\n}"
  },
  {
    "path": "SettingsView/Native/Android/Cells/TimePickerCellView.cs",
    "content": "﻿using System;\nusing Android.App;\nusing Android.Content;\nusing Android.Runtime;\nusing Android.Widget;\nusing Android.Text.Format;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Time picker cell view.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class TimePickerCellView : LabelCellView\n{\n    TimePickerCell _TimePickerCell => Cell as TimePickerCell;\n    TimePickerDialog _dialog;\n    Context _context;\n    string _title;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.TimePickerCellView\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"cell\">Cell.</param>\n    public TimePickerCellView(Context context, CellBase cell) : base(context, cell)\n    {\n        _context = context;\n    }\n\n    public TimePickerCellView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell()\n    {\n        base.UpdateCell();\n        //UpdateTime();\n        //UpdatePickerTitle();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"adapter\">Adapter.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void RowSelected(SettingsViewRecyclerAdapter adapter, int position)\n    {\n        CreateDialog();\n    }\n\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _dialog?.Dispose();\n            _dialog = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    void CreateDialog()\n    {\n\n        if (_dialog == null)\n        {\n            bool is24HourFormat = DateFormat.Is24HourFormat(_context);\n            _dialog = new TimePickerDialog(_context, TimeSelected, _TimePickerCell.Time.Hours, _TimePickerCell.Time.Minutes, is24HourFormat);\n\n            var title = new TextView(_context);\n\n            if (!string.IsNullOrEmpty(_title))\n            {\n                title.Gravity = Android.Views.GravityFlags.Center;\n                title.SetPadding(10, 10, 10, 10);\n                title.Text = _title;\n                _dialog.SetCustomTitle(title);\n            }\n\n            _dialog.SetCanceledOnTouchOutside(true);\n\n            _dialog.DismissEvent += (ss, ee) =>\n            {\n                title.Dispose();\n                _dialog.Dispose();\n                _dialog = null;\n            };\n\n            _dialog.Show();\n        }\n\n    }\n\n    internal void UpdateTime()\n    {\n        vValueLabel.Text = DateTime.Today.Add(_TimePickerCell.Time).ToString(_TimePickerCell.Format);\n    }\n\n    internal void UpdatePickerTitle()\n    {\n        _title = _TimePickerCell.PickerTitle;\n    }\n\n    void TimeSelected(object sender, TimePickerDialog.TimeSetEventArgs e)\n    {\n        _TimePickerCell.Time = new TimeSpan(e.HourOfDay, e.Minute, 0);\n        UpdateTime();\n    }\n\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/DrawableUtility.cs",
    "content": "﻿using System;\nusing Android.Content.Res;\nusing Android.Graphics.Drawables;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\r\n/// <summary>\n/// Drawable utility.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic static class DrawableUtility\n{\n    /// <summary>\n    /// Creates the ripple.\n    /// </summary>\n    /// <returns>The ripple.</returns>\n    /// <param name=\"color\">Color.</param>\n    /// <param name=\"background\">Background.</param>\n    public static RippleDrawable CreateRipple(Android.Graphics.Color color, Drawable background = null)\n    {\n        if (background == null) {\n            var mask = new ColorDrawable(Android.Graphics.Color.White);\n            return new RippleDrawable(GetPressedColorSelector(color), null, mask);\n        }\n\n        return new RippleDrawable(GetPressedColorSelector(color), background, null);\n    }\n\n    /// <summary>\n    /// Gets the pressed color selector.\n    /// </summary>\n    /// <returns>The pressed color selector.</returns>\n    /// <param name=\"pressedColor\">Pressed color.</param>\n    public static ColorStateList GetPressedColorSelector(int pressedColor)\n    {\n        return new ColorStateList(\n            new int[][]\n            {\n                new int[]{}\n            },\n            new int[]\n            {\n                pressedColor,\n            });\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/Extensions/LayoutAlignmentExtensions.cs",
    "content": "﻿using System;\nusing Android.Views;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\r\n/// <summary>\n/// Layout alignment extensions.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic static class LayoutAlignmentExtensions\n{\n    /// <summary>\n    /// Tos the native vertical.\n    /// </summary>\n    /// <returns>The native vertical.</returns>\n    /// <param name=\"forms\">Forms.</param>\n    public static GravityFlags ToNativeVertical(this LayoutAlignment forms)\n    {\n        switch (forms) {\n            case LayoutAlignment.Start:\n                return GravityFlags.Top;\n            case LayoutAlignment.Center:\n                return GravityFlags.CenterVertical;\n            case LayoutAlignment.End:\n                return GravityFlags.Bottom;\n            default:\n                return GravityFlags.FillHorizontal;\n        }\n    }\n\n    /// <summary>\n    /// Tos the native horizontal.\n    /// </summary>\n    /// <returns>The native horizontal.</returns>\n    /// <param name=\"forms\">Forms.</param>\n    public static GravityFlags ToNativeHorizontal(this LayoutAlignment forms)\n    {\n        switch (forms) {\n            case LayoutAlignment.Start:\n                return GravityFlags.Start;\n            case LayoutAlignment.Center:\n                return GravityFlags.CenterHorizontal;\n            case LayoutAlignment.End:\n                return GravityFlags.End;\n            default:\n                return GravityFlags.FillVertical;\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/Extensions/TextAlignmentExtensions.cs",
    "content": "﻿using System;\nusing GravityFlags = Android.Views.GravityFlags;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\r\n/// <summary>\n/// Text alignment extensions.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic static class TextAlignmentExtensions\n{\n    /// <summary>\n    /// Tos the gravity flags.\n    /// </summary>\n    /// <returns>The gravity flags.</returns>\n    /// <param name=\"forms\">Forms.</param>\n    public static GravityFlags ToGravityFlags(this TextAlignment forms)\n    {\n        switch (forms) {\n            case TextAlignment.Start:\n                return GravityFlags.Left | GravityFlags.CenterVertical;\n            case TextAlignment.Center:\n                return GravityFlags.Center | GravityFlags.CenterVertical;\n            case TextAlignment.End:\n                return GravityFlags.Right | GravityFlags.CenterVertical;\n            default:\n                return GravityFlags.Right | GravityFlags.CenterVertical;\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/Extensions/ViewExtension.cs",
    "content": "﻿#nullable enable\nusing System;\nusing Android.Views;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\r\n[Android.Runtime.Preserve(AllMembers = true)]\r\npublic static class ViewExtension\n{\n    public static T? GetParentOfType<T>(this Android.Views.View view)\n       where T : class\n    {\n        if (view is T t)\n            return t;\n\n        return view.GetParent().GetParentOfType<T>();\n    }\n    internal static T? GetParentOfType<T>(this Android.Views.IViewParent? view)\n            where T : class\n    {\n        if (view is T t)\n            return t;\n\n        while (view != null)\n        {\n            T? parent = view?.GetParent() as T;\n            if (parent != null)\n                return parent;\n\n            view = view?.GetParent();\n        }\n\n        return default;\n    }\n    public static IViewParent? GetParent(this Android.Views.View view)\n    {\n        return view.Parent;\n    }\n\n    public static IViewParent? GetParent(this IViewParent? view)\n    {\n        return view?.Parent;\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/Extensions/ViewHandlerExtension.cs",
    "content": "﻿#nullable enable\nusing System;\nusing Android.Views;\nusing Microsoft.Maui.Platform;\nusing static Android.Views.View;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\r\n/// <summary>\n/// Copy form Microsoft.Maui.ViewHandlerExtensions.Android.cs\n/// </summary>\r\n[Android.Runtime.Preserve(AllMembers = true)]\r\npublic static class ViewHandlerExtension\n{\n    // TODO: Possibly reconcile this code with LayoutViewGroup.OnLayout\n    // If you make changes here please review if those changes should also\n    // apply to LayoutViewGroup.OnLayout\n    public static Size LayoutVirtualView(\n            this IPlatformViewHandler viewHandler,\n            int l, int t, int r, int b,\n            Func<Rect, Size>? arrangeFunc = null)\n    {\n        var context = viewHandler.MauiContext?.Context;\n        var virtualView = viewHandler.VirtualView;\n        var platformView = viewHandler.PlatformView;\n\n        if (context == null || virtualView == null || platformView == null)\n        {\n            return Size.Zero;\n        }\n\n        var destination = context.ToCrossPlatformRectInReferenceFrame(l, t, r, b);\n        arrangeFunc ??= virtualView.Arrange;\n        return arrangeFunc(destination);\n    }\n\n    // TODO: Possibly reconcile this code with LayoutViewGroup.OnMeasure\n    // If you make changes here please review if those changes should also\n    // apply to LayoutViewGroup.OnMeasure\n    public static Size MeasureVirtualView(\n        this IPlatformViewHandler viewHandler,\n        int platformWidthConstraint,\n        int platformHeightConstraint,\n        Func<double, double, Size>? measureFunc = null)\n    {\n        var context = viewHandler.MauiContext?.Context;\n        var virtualView = viewHandler.VirtualView;\n        var platformView = viewHandler.PlatformView;\n\n        if (context == null || virtualView == null || platformView == null)\n        {\n            return Size.Zero;\n        }\n\n        var deviceIndependentWidth = platformWidthConstraint.ToDouble(context);\n        var deviceIndependentHeight = platformHeightConstraint.ToDouble(context);\n\n        var widthMode = MeasureSpec.GetMode(platformWidthConstraint);\n        var heightMode = MeasureSpec.GetMode(platformHeightConstraint);\n\n        measureFunc ??= virtualView.Measure;\n        var measure = measureFunc(deviceIndependentWidth, deviceIndependentHeight);\n\n        // If the measure spec was exact, we should return the explicit size value, even if the content\n        // measure came out to a different size\n        var width = widthMode == MeasureSpecMode.Exactly ? deviceIndependentWidth : measure.Width;\n        var height = heightMode == MeasureSpecMode.Exactly ? deviceIndependentHeight : measure.Height;\n\n        var platformWidth = context.ToPixels(width);\n        var platformHeight = context.ToPixels(height);\n\n        // Minimum values win over everything\n        platformWidth = Math.Max(platformView.MinimumWidth, platformWidth);\n        platformHeight = Math.Max(platformView.MinimumHeight, platformHeight);\n\n        return new Size(platformWidth, platformHeight);\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/Android/FormsViewContainer.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing System.Linq;\nusing Android.Content;\nusing Android.Views;\nusing Android.Widget;\nusing Android.Graphics.Drawables;\nusing AView = Android.Views.View;\nusing View = Microsoft.Maui.Controls.View;\nusing Microsoft.Maui.Platform;\nusing AiForms.Settings.Extensions;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal class FormsViewContainer : FrameLayout\n{\n    public ViewHolder ViewHolder { get; set; }\n    public Element Element => ContentView;\n    public bool IsEmpty => _contentView == null;\n    public bool IsMeasureOnce => CustomCell?.IsMeasureOnce ?? false;\n    public CustomCell CustomCell { get; set; }\n\n    IPlatformViewHandler _viewHandler;\n    AView _currentView;\n\n\n    public FormsViewContainer(Context context) : base(context)\n    {\n        Clickable = true;\n    }\n\n    View _contentView;\n    public View ContentView\n    {\n        get { return _contentView; }\n        set\n        {\n            if (_contentView == value)\n                return;\n            UpdateCell(value);\n        }\n    }\n\n    public override bool OnTouchEvent(MotionEvent e)\n    {\n        return false; // pass to parent (ripple effect)\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_contentView != null)\n            {\n                _contentView.PropertyChanged -= CellPropertyChanged;\n                _contentView = null;\n            }\n            CustomCell = null;\n\n            ViewHolder = null;\n\n            _viewHandler?.DisconnectHandler();\n            _viewHandler = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    protected override void OnLayout(bool changed, int l, int t, int r, int b)\n    {\n        if (IsEmpty)\n        {\n            return;\n        }\n\n        _viewHandler.LayoutVirtualView(l,t,r,b);       \n    }\n\n    int _heightCache;\n\n    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)\n    {\n        int pxWidth = MeasureSpec.GetSize(widthMeasureSpec);\n\n        if (IsMeasureOnce && _heightCache > 0)\n        {\n            SetMeasuredDimension(pxWidth, _heightCache);\n            return;\n        }\n\n        var dpWidth = Context.FromPixels(pxWidth);\n        var size = _viewHandler.VirtualView.Measure(dpWidth, double.PositiveInfinity);\n        // This way can't measure correctly.\n        //var measure = _viewHandler.MeasureVirtualView(width, heightMeasureSpec);\n        int pxHeight = (int)Context.ToPixels(size.Height);\n\n        SetMeasuredDimension(pxWidth, pxHeight);\n        _heightCache = pxHeight;\n    }\n\n    public virtual void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        if (e.PropertyName == CellBase.IsEnabledProperty.PropertyName)\n        {\n            UpdateIsEnabled();\n        }\n    }\n\n    public virtual void UpdateNativeCell()\n    {\n        UpdateIsEnabled();\n    }\n\n    public void UpdateIsEnabled()\n    {\n        Enabled = _contentView.IsEnabled;\n    }\n\n    protected virtual void CreateNewHandler(View view)\n    {\n        _contentView = view;\n        var platformView = _contentView.ToPlatform(view.FindMauiContext());\n        _viewHandler = (IPlatformViewHandler)_contentView.Handler;\n        platformView.RemoveFromParent();\n        AddView(platformView);       \n\n        _contentView.IsPlatformEnabled = true;\n        UpdateNativeCell();\n    }\n\n    public void DisconnectHandler()\n    {\n        var oldView = _currentView ?? _viewHandler.PlatformView;\n        if (oldView != null)\n            RemoveView(oldView);\n\n        _contentView.Handler?.DisconnectHandler();\n    }\n\n    public void UpdateCell(View view)\n    {\n        // Workaround GestureRecognizer bug\n        // TODO: if fix this issue, remove the following code.\n        // https://github.com/dotnet/maui/issues/17948\n        view.Parent = Application.Current.MainPage;\n\n        if (_contentView == view && !CustomCell.IsForceLayout)\n        {\n            return;\n        }\n        CustomCell.IsForceLayout = false;\n\n        if (_contentView != null)\n        {\n            _contentView.PropertyChanged -= CellPropertyChanged;\n        }\n\n        view.PropertyChanged += CellPropertyChanged;\n\n        if (_viewHandler == null)\n        {\n            CreateNewHandler(view);\n            return;\n        }\n\n        var viewHandlerType = _viewHandler.MauiContext.Handlers.GetHandlerType(view.GetType());\n        var reflectableType = _viewHandler as System.Reflection.IReflectableType;\n        var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : (_viewHandler != null ? _viewHandler.GetType() : typeof(System.Object));\n        if (_viewHandler != null && rendererType == viewHandlerType)\n        {\n            _contentView = view;\n\n            if (_viewHandler != view.Handler)\n            {\n                if (view.Handler?.PlatformView is AView oldCellView &&\n                    oldCellView.GetParent().GetParentOfType<FormsViewContainer>() is FormsViewContainer vc)\n                {\n                    vc.DisconnectHandler();\n                }\n\n                var oldView = _currentView ?? _viewHandler.PlatformView;\n                if (oldView != null)\n                    RemoveView(oldView);\n\n                _contentView.Handler?.DisconnectHandler();\n                _viewHandler.SetVirtualView(_contentView);\n                AddView(_viewHandler.PlatformView);\n            }\n\n            UpdateNativeCell();\n            Invalidate();\n\n            return;\n        }\n\n        RemoveView(_currentView ?? _viewHandler.PlatformView);\n        _contentView.Handler?.DisconnectHandler();\n        _contentView.IsPlatformEnabled = false;\n        _viewHandler.DisconnectHandler();\n\n        CreateNewHandler(view);\n    }\n\n\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/HeaderFooterContainer.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing System.Linq;\nusing Android.Content;\nusing Android.Widget;\nusing Android.Graphics.Drawables;\nusing Microsoft.Maui.Platform;\nusing AView = Android.Views.View;\nusing AiForms.Settings.Extensions;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal class HeaderFooterContainer : FrameLayout\n{   \n    public ViewHolder ViewHolder { get; set; }\n    public bool IsEmpty => _contentView == null;\n\n    IPlatformViewHandler _viewHandler;\n    AView _currentView;\n\n    public HeaderFooterContainer(Context context) : base(context)\n    {\n        Clickable = true;\n    }\n\n    View _contentView;\n    public View ContentView\n    {\n        get { return _contentView; }\n        set\n        {\n            if (_contentView == value)\n                return;\n            UpdateCell(value);\n        }\n    }\n\n    public override bool OnTouchEvent(Android.Views.MotionEvent e)\n    {\n        return false; // pass to parent (ripple effect)\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_contentView != null)\n            {\n                _contentView.PropertyChanged -= CellPropertyChanged;                \n                _contentView = null;\n            }\n\n            ViewHolder = null;\n\n            _viewHandler?.DisconnectHandler();\n            _viewHandler = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    protected override void OnLayout(bool changed, int l, int t, int r, int b)\n    {\n        if (IsEmpty)\n        {\n            return;\n        }\n\n        _viewHandler.LayoutVirtualView(l, t, r, b);\n    }\n\n    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)\n    {\n        int pxWidth = MeasureSpec.GetSize(widthMeasureSpec);\n        if (_viewHandler == null)\n        {\n            SetMeasuredDimension(pxWidth, 0);\n            return;\n        }\n        if(ViewHolder.RowInfo.ViewType == ViewType.CustomFooter && !ViewHolder.RowInfo.Section.FooterVisible)\n        {\n            SetMeasuredDimension(pxWidth, 0);\n            return;\n        }\n\n        var dpWidth = Context.FromPixels(pxWidth);\n        var size = _viewHandler.VirtualView.Measure(dpWidth, double.PositiveInfinity);\n        int pxHeight = (int)Context.ToPixels(size.Height);\n\n        SetMeasuredDimension(pxWidth, pxHeight);\n    }\n\n    public virtual void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)\n        {\n            UpdateIsEnabled();\n        }\n    }\n\n    public virtual void UpdateNativeCell()\n    {\n        UpdateIsEnabled();\n    }\n\n    public void UpdateIsEnabled()\n    {\n        Enabled = _contentView.IsEnabled;\n    }\n\n    public void UpdateCell(View view)\n    {\n        // Workaround GestureRecognizer bug\n        // TODO: if fix this issue, remove the following code.\n        // https://github.com/dotnet/maui/issues/17948\n        view.Parent = Application.Current.MainPage;\n\n        if (_contentView != null)\n        {\n            _contentView.PropertyChanged -= CellPropertyChanged;\n        }\n\n        view.PropertyChanged += CellPropertyChanged;\n\n        if (_viewHandler == null)\n        {\n            CreateNewHandler(view);\n            return;\n        }\n\n        var viewHandlerType = _viewHandler.MauiContext.Handlers.GetHandlerType(view.GetType());\n        var reflectableType = _viewHandler as System.Reflection.IReflectableType;\n        var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : (_viewHandler != null ? _viewHandler.GetType() : typeof(System.Object));\n        if (_viewHandler != null && rendererType == viewHandlerType)\n        {\n            _contentView = view;\n\n            if(_viewHandler != view.Handler)\n            {\n                if (view.Handler?.PlatformView is AView oldCellView &&\n                    oldCellView.GetParent().GetParentOfType<HeaderFooterContainer>() is HeaderFooterContainer vc)\n                {\n                    vc.DisconnectHandler();\n                }\n\n                var oldView = _currentView ?? _viewHandler.PlatformView;\n                if (oldView != null)\n                    RemoveView(oldView);\n\n                _contentView.Handler?.DisconnectHandler();\n                _viewHandler.SetVirtualView(_contentView);\n                AddView(_viewHandler.PlatformView);\n            }\n\n            UpdateNativeCell();\n            Invalidate();\n\n            return;\n        }\n\n        RemoveView(_currentView ?? _viewHandler.PlatformView);\n        _contentView.Handler?.DisconnectHandler();\n        _contentView.IsPlatformEnabled = false;\n        _viewHandler.DisconnectHandler();\n\n        CreateNewHandler(view);\n    }\n\n    public void DisconnectHandler()\n    {\n        var oldView = _currentView ?? _viewHandler.PlatformView;\n        if (oldView != null)\n            RemoveView(oldView);\n\n        _contentView.Handler?.DisconnectHandler();\n    }\n\n    protected virtual void CreateNewHandler(View view)\n    {\n        _contentView = view;\n\n        _contentView.MeasureInvalidated += _contentView_MeasureInvalidated;\n\n        var platformView = _contentView.ToPlatform(view.FindMauiContext());\n        _viewHandler = (IPlatformViewHandler)_contentView.Handler;\n        AddView(platformView);\n        UpdateNativeCell();\n    }\n\n    private void _contentView_MeasureInvalidated(object sender, EventArgs e)\n    {\n        ;\n    }\n\n    public override void AddView(AView child)\n    {\n        child.RemoveFromParent();\n        base.AddView(child);\n\n        _currentView = child;\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/ModelProxy.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Collections.Specialized;\nusing System.Linq;\nusing Android.OS;\nusing AndroidX.RecyclerView.Widget;\nusing AiForms.Settings.Extensions;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\npublic enum ViewType\n{\n    TextHeader,\n    TextFooter,\n    CustomHeader,\n    CustomFooter,\n}\n\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class ModelProxy:List<RowInfo>,IDisposable\n{\n    public Dictionary<Type, int> ViewTypes { get; private set; }\n\n    SettingsModel _model;\n    SettingsRoot _root;\n    SettingsViewRecyclerAdapter _adapter;\n    RecyclerView _recyclerView;\n    bool _disposed;\n\n    public ModelProxy(SettingsView settingsView,SettingsViewRecyclerAdapter adapter,RecyclerView recyclerView)\n    {\n        _model = settingsView.Model;\n        _root = settingsView.Root;\n        _adapter = adapter;\n        _recyclerView = recyclerView;\n\n        _root.SectionCollectionChanged += OnRootSectionCollectionChanged;\n        _root.CollectionChanged += OnRootCollectionChanged;\n\n        FillProxy();\n    }\n\n    public void Dispose()\n    {\n        if (_disposed) return;\n        _disposed = true;\n\n        if (_root != null)\n        {\n            _root.SectionCollectionChanged -= OnRootSectionCollectionChanged;\n            _root.CollectionChanged -= OnRootCollectionChanged;\n        }\n        _model = null;\n        _root = null;\n        _adapter = null;\n        _recyclerView = null;\n        this?.Clear();\n        ViewTypes?.Clear();\n        ViewTypes = null;\n    }\n\n    void OnRootCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        if (_disposed) return;\n\n        switch(e.Action)\n        {\n            case NotifyCollectionChangedAction.Add:\n                if (e.NewStartingIndex == -1 || e.NewItems == null)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n                AddSection(e);\n                break;\n            case NotifyCollectionChangedAction.Remove:\n                if (e.OldStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n                RemoveSection(e);\n                break;\n            case NotifyCollectionChangedAction.Replace: // no support on Android.\n            case NotifyCollectionChangedAction.Move:\n            case NotifyCollectionChangedAction.Reset:\n                FillProxy();\n                _adapter.NotifyDataSetChanged();\n                break;\n        }\n    }\n\n\n    void OnRootSectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        if (_disposed) return;\n\n        switch(e.Action)\n        {\n            case NotifyCollectionChangedAction.Add:\n                if (e.NewStartingIndex == -1 || e.NewItems == null)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n                AddCell(sender, e);\n                break;\n            case NotifyCollectionChangedAction.Remove:\n                if (e.OldStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n                RemoveCell(sender, e);\n                break;\n            case NotifyCollectionChangedAction.Replace:\n                if (e.OldStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n                ReplaceCell(sender, e);\n                break;\n\n            case NotifyCollectionChangedAction.Move:\n            case NotifyCollectionChangedAction.Reset:\n                FillProxy();\n                _adapter.NotifyDataSetChanged();\n                break;\n        }\n    }\n\n    void AddSection(NotifyCollectionChangedEventArgs e)\n    {\n        // regard as coming only one item.\n        var section = e.NewItems[0] as Section;\n        var startIndex = RowIndexFromParentCollection(e.NewStartingIndex);\n\n        this.Insert(startIndex,new RowInfo {\n            Section = section,\n            ViewType = section.HeaderView == null ? ViewType.TextHeader : ViewType.CustomHeader,\n        });\n\n        for (var i = 0; i < section.Count; i++)\n        {\n            var cell = section[i];\n            if(!ViewTypes.ContainsKey(cell.GetType()))\n            {\n                ViewTypes.Add(cell.GetType(), GetNextTypeIndex());\n            }\n\n            var rowInfo = new RowInfo {\n                Section = section,\n                Cell = cell,\n                ViewType = (ViewType)ViewTypes[cell.GetType()],\n            };\n\n            this.Insert(i + 1 + startIndex, rowInfo);\n        }\n\n        this.Insert(startIndex + section.Count() + 1,new RowInfo {\n            Section = section,\n            ViewType = section.FooterView == null ? ViewType.TextFooter : ViewType.CustomFooter,\n        });\n\n        _adapter.NotifyItemRangeInserted(startIndex, section.Count + 2); // add a header and footer\n    }\n\n    void RemoveSection(NotifyCollectionChangedEventArgs e)\n    {\n        // regard as coming only one item.\n        var section = e.OldItems[0] as Section;\n        var startIndex = RowIndexFromParentCollection(e.OldStartingIndex);\n\n        this.RemoveRange(startIndex, section.Count + 2);\n\n        _adapter.NotifyItemRangeRemoved(startIndex, section.Count + 2);\n    }\n\n\n    void AddCell(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        var section = sender as Section;\n        var startIndex = RowIndexFromChildCollection(section, e.NewStartingIndex);\n        var newCells = e.NewItems.Cast<CellBase>().ToList();\n        for (var i = 0; i < newCells.Count; i++)\n        {\n            var cell = newCells[i];\n            if(!ViewTypes.ContainsKey(cell.GetType()))\n            {\n                ViewTypes.Add(cell.GetType(), GetNextTypeIndex());\n            }\n\n            var rowInfo = new RowInfo {\n                Section = section,\n                Cell = cell,\n                ViewType = (ViewType)ViewTypes[cell.GetType()],\n            };\n            this.Insert(i + startIndex,rowInfo);\n        }\n\n        _adapter.NotifyItemRangeInserted(startIndex, newCells.Count);\n    }\n\n    void RemoveCell(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        var section = sender as Section;\n        var startIndex = RowIndexFromChildCollection(section, e.OldStartingIndex);\n        this.RemoveAt(startIndex);\n\n        _adapter.NotifyItemRangeRemoved(startIndex, 1);\n    }\n\n    void ReplaceCell(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        var section = sender as Section;\n        var startIndex = RowIndexFromChildCollection(section, e.OldStartingIndex);\n        var repCell = e.NewItems[0] as CellBase;\n        this[startIndex] = new RowInfo {\n            Section = section,\n            Cell = repCell,\n            ViewType = (ViewType)ViewTypes[repCell.GetType()],\n        };\n\n        // Stop animation.\n        (_recyclerView.GetItemAnimator() as DefaultItemAnimator).SupportsChangeAnimations = false;\n\n        _adapter.NotifyItemRangeChanged(startIndex, 1);\n\n        new Handler(Looper.MainLooper).PostDelayed(() =>\n        {\n            // Restart animation.\n            (_recyclerView.GetItemAnimator() as DefaultItemAnimator).SupportsChangeAnimations = true;\n        },100);\n    }\n\n    int RowIndexFromChildCollection(object sender,int index)\n    {\n        var section = sender as Section;\n        var targetSectionIndex = this.IndexOf(x => x.Section == section);\n\n        if (targetSectionIndex < 0) return -1;\n\n        return index + targetSectionIndex + 1;\n    }\n\n    int RowIndexFromParentCollection(int index)\n    {\n        var groups = this.Select((x, idx) => new { index = idx, x.Section }).GroupBy(x => x.Section);\n        var match = groups.ElementAtOrDefault(index)?.Min(x => x.index);\n\n        return match.HasValue ? match.Value : this.Count;\n    }\n\n    int GetNextTypeIndex()\n    {\n        var idx = ViewTypes.Values.LastOrDefault();            \n        return idx == 0 ? Enum.GetNames(typeof(ViewType)).Length : idx + 1;\n    }\n\n    public void FillProxy()\n    {\n        this.Clear();\n\n        ViewTypes = _root.SelectMany(x => x).Select(x => x.GetType()).Distinct()\n            .Select((type,idx) => new { type,index = idx })\n            .ToDictionary(key =>key.type , val => val.index + Enum.GetNames(typeof(ViewType)).Length);\n\n        int sectionCount = _model.GetSectionCount();\n\n        for (var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++)\n        {\n            var sectionRowCount = _model.GetRowCount(sectionIndex);\n            var isTextHeader = _model.GetSectionHeaderView(sectionIndex) == null;\n            var curSection = _model.GetSection(sectionIndex);\n\n            this.Add(new RowInfo {\n                Section = curSection,\n                ViewType = isTextHeader ? ViewType.TextHeader : ViewType.CustomHeader,\n            });\n\n            for (int i = 0; i < sectionRowCount; i++)\n            {\n                var cell = _model.GetCell(sectionIndex, i);\n                this.Add(new RowInfo {\n                    Section = curSection,\n                    Cell = cell,\n                    ViewType = (ViewType)ViewTypes[cell.GetType()],\n                });\n            }\n\n            var isTextFooter = _model.GetSectionFooterView(sectionIndex) == null;\n\n            this.Add(new RowInfo {\n                Section = curSection,\n                ViewType = isTextFooter ? ViewType.TextFooter : ViewType.CustomFooter,\n            });\n        }\n    }\n\n\n}\n\npublic class RowInfo\n{\n    public Section Section { get; set; }\n    public CellBase Cell { get; set; }\n    public ViewType ViewType { get; set; }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/SVItemdecoration.cs",
    "content": "﻿using System.Linq;\nusing Android.Graphics;\nusing Android.Graphics.Drawables;\nusing AndroidX.RecyclerView.Widget;\nusing Rect = Android.Graphics.Rect;\nusing View = Android.Views.View;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class SVItemdecoration : RecyclerView.ItemDecoration\n{\n    Drawable _drawable;\n    SettingsView _settingsView;\n\n    public SVItemdecoration(Drawable drawable,SettingsView settingsView)\n    {\n        _drawable = drawable;\n        _settingsView = settingsView;\n    }\n\n    public override void GetItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)\n    {\n        var holder = parent.GetChildViewHolder(view) as ViewHolder;\n        if (!CellIsVisible(holder?.RowInfo.Cell))\n        {\n            return;\n        }\n\n        outRect.Set(0, _drawable.IntrinsicHeight, 0, 0);\n    }\n\n    public override void OnDraw(Canvas c, RecyclerView parent, RecyclerView.State state)\n    {\n        var left = parent.Left;\n        var right = parent.Right;\n\n        var childCount = parent.ChildCount;\n        ViewHolder prevHolder = null;\n        for(var i = 0; i < childCount; i++)\n        {\n            var child = parent.GetChildAt(i);\n            var holder = parent.GetChildViewHolder(child) as ViewHolder;\n\n            if(prevHolder != null && prevHolder is IHeaderViewHolder && !_settingsView.ShowSectionTopBottomBorder ||\n               holder is IFooterViewHolder && !_settingsView.ShowSectionTopBottomBorder ||\n               holder is IFooterViewHolder && !holder.RowInfo.Section.Any() ||\n               holder is IHeaderViewHolder ||\n               !SectionIsVisible(holder?.RowInfo.Section) ||\n               !CellIsVisible(holder?.RowInfo.Cell))\n            {\n                prevHolder = holder;\n                continue;\n            }\n\n            var bottom = child.Top;\n            var top = bottom - _drawable.IntrinsicHeight;\n            _drawable.SetBounds(left, top, right, bottom);\n            _drawable.Draw(c);\n\n            prevHolder = holder;\n        }\n    }\n\n    private bool SectionIsVisible(Section section)\n    {\n        return section?.IsVisible ?? true;\n    }\n    private bool CellIsVisible(CellBase cell)\n    {\n        return cell?.IsVisible ?? true;\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if(disposing)\n        {\n            _settingsView = null;\n            _drawable = null;\n        }\n        base.Dispose(disposing);\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/SettingsViewLayoutManager.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\nusing AndroidX.RecyclerView.Widget;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class SettingsViewLayoutManager:LinearLayoutManager\n{\n    SettingsView _settingsView;\n    Android.Content.Context _context;\n    Dictionary<Android.Views.View, int> ItemHeights = new Dictionary<Android.Views.View, int>();\n    bool _disposed;\n\n    public SettingsViewLayoutManager(Android.Content.Context context,SettingsView settingsView):base(context)\n    {\n        _context = context;\n        _settingsView = settingsView;\n    }\n\n    public override int GetDecoratedMeasuredHeight(Android.Views.View child)\n    {\n        if (_disposed) return 0;\n\n        var height =  base.GetDecoratedMeasuredHeight(child);\n        ItemHeights[child] = height;\n        return height;\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (_disposed) return;\n        _disposed = true;\n\n        if(disposing)\n        {\n            ItemHeights?.Clear();\n            ItemHeights = null;\n            _context = null;\n            _settingsView = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    public override void OnLayoutCompleted(RecyclerView.State state)\n    {\n        base.OnLayoutCompleted(state);\n\n        if (_disposed || _settingsView == null || _context == null || ItemHeights == null)\n        {\n            return;\n        }\n\n        var total = ItemHeights.Sum(x => x.Value);\n\n        _settingsView.VisibleContentHeight = _context.FromPixels(total);\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/Android/SettingsViewRecyclerAdapter.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing AiForms.Settings.Extensions;\nusing Android.Content;\nusing Android.Views;\nusing Android.Widget;\nusing AndroidX.RecyclerView.Widget;\nusing Microsoft.Maui.Controls.Platform;\nusing Microsoft.Maui.Platform;\nusing AView = Android.Views.View;\n//using Resource = AiForms.Settings.Resource;\nusing View = Microsoft.Maui.Controls.View;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n/// <summary>\n/// Settings view recycler adapter.\n/// </summary>\n[Android.Runtime.Preserve(AllMembers = true)]\npublic class SettingsViewRecyclerAdapter:RecyclerView.Adapter,AView.IOnClickListener, AView.IOnLongClickListener\n{\n    float MinRowHeight => _context.ToPixels(44);\n\n    //Item click. correspond to AdapterView.IOnItemClickListener\n    int _selectedIndex = -1;\n    Android.Views.View _preSelectedCell = null;\n\n    Context _context;\n    SettingsView _settingsView;\n    RecyclerView _recyclerView;\n    ModelProxy _proxy;\n    bool _disposed;\n\n    List<ViewHolder> _viewHolders = new List<ViewHolder>();\n    protected Lazy<IFontManager> _fontManager;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Droid.SettingsViewRecyclerAdapter\"/> class.\n    /// </summary>\n    /// <param name=\"context\">Context.</param>\n    /// <param name=\"settingsView\">Settings view.</param>\n    /// <param name=\"recyclerView\">Recycler view.</param>\n    public SettingsViewRecyclerAdapter(Context context, SettingsView settingsView,RecyclerView recyclerView)\n    {\n        _context = context;\n        _settingsView = settingsView;\n        _recyclerView = recyclerView;\n        _proxy = new ModelProxy(settingsView, this,recyclerView);\n\n        _settingsView.ModelChanged += _settingsView_ModelChanged;\n        _settingsView.SectionPropertyChanged += OnSectionPropertyChanged;\n        _settingsView.CellPropertyChanged += OnCellPropertyChanged;\n\n        _fontManager = new Lazy<IFontManager>(() =>\n        {\n            return settingsView.FindMauiContext().Services.GetService<IFontManager>();\n        });\n    }        \n\n    void _settingsView_ModelChanged(object sender, EventArgs e)\n    {\n        if (_disposed) return;\n        if (_recyclerView != null)\n        {\n            _proxy.FillProxy();\n            NotifyDataSetChanged();\n        }\n    }\n\n    void OnSectionPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        if (_disposed) return;\n        if (e.PropertyName == Section.IsVisibleProperty.PropertyName)\n        {\n            UpdateSectionVisible((Section)sender);\n        }\n        else if (e.PropertyName == TableSectionBase.TitleProperty.PropertyName ||\n                 e.PropertyName == Section.HeaderViewProperty.PropertyName ||\n                 e.PropertyName == Section.HeaderHeightProperty.PropertyName)\n        {\n            UpdateSectionHeader((Section)sender);\n        }\n        else if (e.PropertyName == Section.FooterTextProperty.PropertyName ||\n                 e.PropertyName == Section.FooterViewProperty.PropertyName ||\n                 e.PropertyName == Section.FooterVisibleProperty.PropertyName) \n        {\n            UpdateSectionFooter((Section)sender);\n        }\n    }\n\n    void OnCellPropertyChanged(object sender, CellPropertyChangedEventArgs e)\n    {\n        if (_disposed) return;\n        if(e.PropertyName == CellBase.IsVisibleProperty.PropertyName)\n        {\n            UpdateCellVisible(e.Section, (CellBase)sender);\n        }\n    }\n\n    void UpdateSectionVisible(Section section)\n    {\n        var indexes = _proxy.Select((x, idx) => new { idx, x.Section }).Where(x => x.Section == section).Select(x => x.idx).ToList();\n        NotifyItemRangeChanged(indexes[0], indexes.Count);\n    }\n\n    void UpdateCellVisible(Section section, CellBase cell)\n    {\n        var result = _proxy.Select((x, idx) => new { idx, x.Section, x.Cell }).FirstOrDefault(x => x.Section == section && x.Cell == cell);\n        if(result == null)\n        {\n            return;\n        }\n        NotifyItemChanged(result.idx);\n    }\n\n    void UpdateSectionHeader(Section section)\n    {\n        var index = _proxy.FindIndex(x => x.Section == section);\n        NotifyItemChanged(index);\n    }\n\n    void UpdateSectionFooter(Section section)\n    {\n        var index = _proxy.FindLastIndex(x => x.Section == section);\n        NotifyItemChanged(index);\n    }\n\n\n    /// <summary>\n    /// Gets the item count.\n    /// </summary>\n    /// <value>The item count.</value>\n    public override int ItemCount => _proxy?.Count ?? 0;\n\n    /// <summary>\n    /// return ID (As in paticular it doesn't exist, return the position.)\n    /// </summary>\n    /// <returns>The item identifier.</returns>\n    /// <param name=\"position\">Position.</param>\n    public override long GetItemId(int position)\n    {\n        return position;\n    }\n\n    /// <summary>\n    /// Gets the type of the item view.\n    /// </summary>\n    /// <returns>The item view type.</returns>\n    /// <param name=\"position\">Position.</param>\n    public override int GetItemViewType(int position)\n    {\n        return (int)_proxy[position].ViewType;\n    }\n\n    /// <summary>\n    /// Ons the create view holder.\n    /// </summary>\n    /// <returns>The create view holder.</returns>\n    /// <param name=\"parent\">Parent.</param>\n    /// <param name=\"viewType\">View type.</param>\n    public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)\n    {\n        ViewHolder viewHolder;\n\n        var inflater = LayoutInflater.FromContext(_context);\n\n        switch ((ViewType)viewType)\n        {\n            case ViewType.TextHeader:\n                viewHolder = new HeaderViewHolder(inflater.Inflate(Resource.Layout.headercell, parent, false));\n                break;\n            case ViewType.TextFooter:\n                viewHolder = new FooterViewHolder(inflater.Inflate(Resource.Layout.footercell, parent, false));\n                break;\n            case ViewType.CustomHeader:\n                var hContainer = new HeaderFooterContainer(_context);\n                viewHolder = new CustomHeaderViewHolder(hContainer);\n                break;\n            case ViewType.CustomFooter:\n                var fContainer = new HeaderFooterContainer(_context);\n                viewHolder = new CustomFooterViewHolder(fContainer);\n                break;\n            default:\n                viewHolder = new ContentBodyViewHolder(inflater.Inflate(Resource.Layout.contentcell, parent, false));\n                viewHolder.ItemView.SetOnClickListener(this);\n                viewHolder.ItemView.SetOnLongClickListener(this);\n                break;\n        }\n\n        _viewHolders.Add(viewHolder);\n\n        inflater.Dispose();\n\n        return viewHolder;\n    }\n\n    /// <summary>\n    /// Ons the bind view holder.\n    /// </summary>\n    /// <param name=\"holder\">Holder.</param>\n    /// <param name=\"position\">Position.</param>\n    public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)\n    {\n        var rowInfo = _proxy[position];\n\n        var vHolder = holder as ViewHolder;\n        vHolder.RowInfo = rowInfo;\n\n        bool cellVisible = (rowInfo.Cell as CellBase)?.IsVisible ?? true;\n        \n        if(!rowInfo.Section.IsVisible ||\n           !cellVisible ||\n           (rowInfo.ViewType == ViewType.CustomFooter && !rowInfo.Section.FooterVisible))\n        {\n            vHolder.ItemView.Visibility = ViewStates.Gone;\n            vHolder.ItemView.SetMinimumHeight(0);\n            vHolder.ItemView.LayoutParameters.Height = 0;\n            return;\n        }\n        \n        vHolder.ItemView.Visibility = ViewStates.Visible;\n        vHolder.ItemView.LayoutParameters.Height = -2; //wrap_content\n        \n        switch (rowInfo.ViewType)\n        {\n            case ViewType.TextHeader:\n                BindHeaderView((HeaderViewHolder)vHolder);\n                break;\n            case ViewType.TextFooter:\n                BindFooterView((FooterViewHolder)vHolder);\n                break;\n            case ViewType.CustomHeader:\n                BindCustomHeaderFooterView(vHolder, rowInfo.Section.HeaderView);\n                break;\n            case ViewType.CustomFooter:\n                BindCustomHeaderFooterView(vHolder, rowInfo.Section.FooterView);\n                break;\n            default:\n                BindContentView((ContentBodyViewHolder)vHolder, position);\n                break;\n        }\n    }\n\n\n    /// <summary>\n    /// Ons the click.\n    /// </summary>\n    /// <param name=\"view\">View.</param>\n    public void OnClick(AView view)\n    {\n        var position = _recyclerView.GetChildAdapterPosition(view);\n\n        //TODO: It is desirable that the forms side has Selected property and reflects it.\n        //      But do it at a later as iOS side doesn't have that process.\n        DeselectRow();\n\n        var cell = view.FindViewById<LinearLayout>(Resource.Id.ContentCellBody).GetChildAt(0) as CellBaseView;\n\n        if(cell == null || !_proxy[position].Cell.IsEnabled){\n            //if FormsCell IsEnable is false, does nothing. \n            return;\n        }\n\n        _settingsView.Model.OnRowSelected(_proxy[position].Cell);\n\n        cell.RowSelected(this,position);\n    }\n\n    public virtual bool OnLongClick(AView v)\n    {\n        var position = _recyclerView.GetChildAdapterPosition(v);\n\n        DeselectRow();\n\n        if(_proxy[position].Section.UseDragSort)\n        {\n            return false;\n        }\n\n        var cell = v.FindViewById<LinearLayout>(Resource.Id.ContentCellBody).GetChildAt(0) as CellBaseView;\n\n        if (cell == null || !_proxy[position].Cell.IsEnabled)\n        {\n            //if FormsCell IsEnable is false, does nothing. \n            return false;\n        }\n\n        cell.RowLongPressed(this, position);\n\n        return true;\n    }\n\n\n    /// <summary>\n    /// Deselects the row.\n    /// </summary>\n    public void DeselectRow()\n    {\n        if (_preSelectedCell != null)\n        {\n            _preSelectedCell.Selected = false;\n            _preSelectedCell = null;\n        }\n        _selectedIndex = -1;\n    }\n\n    /// <summary>\n    /// Selecteds the row.\n    /// </summary>\n    /// <param name=\"cell\">Cell.</param>\n    /// <param name=\"position\">Position.</param>\n    public void SelectedRow(AView cell, int position)\n    {\n        _preSelectedCell = cell;\n        _selectedIndex = position;\n        cell.Selected = true;\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (_disposed) return;\n        _disposed = true;\n\n        if(disposing){\n            if (_settingsView != null)\n            {\n                _settingsView.ModelChanged -= _settingsView_ModelChanged;\n                _settingsView.SectionPropertyChanged -= OnSectionPropertyChanged;\n                _settingsView.CellPropertyChanged -= OnCellPropertyChanged;\n            }\n            _proxy?.Dispose();\n            _proxy = null;\n            _settingsView = null;\n\n            if (_viewHolders != null)\n            {\n                foreach (var holder in _viewHolders)\n                {\n                    holder.Dispose();\n                }\n                _viewHolders.Clear();\n                _viewHolders = null;\n            }\n        }\n        base.Dispose(disposing);\n    }\n\n   \n    void BindHeaderView(HeaderViewHolder holder)\n    {\n        var section = holder.RowInfo.Section;\n        var view = holder.ItemView;\n\n        //judging cell height\n        int cellHeight = (int)_context.ToPixels(44);\n        var individualHeight = section.HeaderHeight;\n\n        if (individualHeight > 0d)\n        {\n            cellHeight = (int)_context.ToPixels(individualHeight);\n        }\n        else if (_settingsView.HeaderHeight > -1)\n        {\n            cellHeight = (int)_context.ToPixels(_settingsView.HeaderHeight);\n        }\n        else\n        {\n            cellHeight = -1; // Height Auto\n        }\n\n        if (cellHeight >= 0)\n        {\n            view.SetMinimumHeight(cellHeight);\n            view.LayoutParameters.Height = cellHeight;\n        }\n\n        //textview setting\n        holder.TextView.SetPadding(\n            (int)view.Context.ToPixels(_settingsView.HeaderPadding.Left),\n            (int)view.Context.ToPixels(_settingsView.HeaderPadding.Top),\n            (int)view.Context.ToPixels(_settingsView.HeaderPadding.Right),\n            (int)view.Context.ToPixels(_settingsView.HeaderPadding.Bottom)\n        );\n\n        holder.TextView.Gravity = _settingsView.HeaderTextVerticalAlign.ToNativeVertical() | GravityFlags.Left;\n        holder.TextView.TextAlignment = Android.Views.TextAlignment.Gravity;\n        holder.TextView.Typeface = _settingsView.HeaderFontFamily\n            .ToFont(_settingsView.HeaderFontSize, _settingsView.HeaderFontAttributes)\n            .ToTypeface(_fontManager.Value);\n        holder.TextView.SetTextSize(Android.Util.ComplexUnitType.Sp, (float)_settingsView.HeaderFontSize);\n        holder.TextView.SetBackgroundColor(_settingsView.HeaderBackgroundColor.ToPlatform());\n\n        if (_settingsView.HeaderTextColor.IsNotDefault())\n        {\n            holder.TextView.SetTextColor(_settingsView.HeaderTextColor.ToPlatform());\n        }\n\n        //update text\n        holder.TextView.Text = section.Title;\n    }\n\n    void BindFooterView(FooterViewHolder holder)\n    {\n        var section = holder.RowInfo.Section;\n        var view = holder.ItemView;\n\n        //footer visible setting\n        if (string.IsNullOrEmpty(section.FooterText))\n        {\n            //if text is empty, hidden (height 0)\n            holder.TextView.Visibility = ViewStates.Gone;\n            view.Visibility = ViewStates.Gone;\n        }\n        else\n        {\n            holder.TextView.Visibility = ViewStates.Visible;\n            view.Visibility = ViewStates.Visible;\n        }\n\n        //textview setting\n        holder.TextView.SetPadding(\n            (int)view.Context.ToPixels(_settingsView.FooterPadding.Left),\n            (int)view.Context.ToPixels(_settingsView.FooterPadding.Top),\n            (int)view.Context.ToPixels(_settingsView.FooterPadding.Right),\n            (int)view.Context.ToPixels(_settingsView.FooterPadding.Bottom)\n        );\n\n        holder.TextView.Typeface = _settingsView.FooterFontFamily\n            .ToFont(_settingsView.FooterFontSize, _settingsView.FooterFontAttributes)\n            .ToTypeface(_fontManager.Value);\n        holder.TextView.SetTextSize(Android.Util.ComplexUnitType.Sp, (float)_settingsView.FooterFontSize);\n        holder.TextView.SetBackgroundColor(_settingsView.FooterBackgroundColor.ToPlatform());\n        if (_settingsView.FooterTextColor.IsNotDefault())\n        {\n            holder.TextView.SetTextColor(_settingsView.FooterTextColor.ToPlatform());\n        }\n\n        //update text\n        holder.TextView.Text = section.FooterText;\n    }\n\n    void BindCustomHeaderFooterView(ViewHolder holder, View formsView)\n    {\n        var nativeCell = holder.ItemView as HeaderFooterContainer;\n        nativeCell.ViewHolder = holder;\n        nativeCell.ContentView = formsView;\n    }\n\n\n    void BindContentView(ContentBodyViewHolder holder, int position)\n    {\n        var virtualCell = holder.RowInfo.Cell;\n        AView nativeCell = null;\n        AView layout = holder.ItemView;\n\n        holder.RowInfo = _proxy[position];\n\n        nativeCell = holder.Body.GetChildAt(0);\n        if (nativeCell != null)\n        {\n            holder.Body.RemoveViewAt(0);\n        }\n\n        virtualCell.Handler?.DisconnectHandler();\n        virtualCell.ConvertView = nativeCell;        \n        nativeCell = virtualCell.ToPlatform(virtualCell.FindMauiContext());\n\n        if (position == _selectedIndex)\n        {\n\n            DeselectRow();\n            nativeCell.Selected = true;\n\n            _preSelectedCell = nativeCell;\n        }\n\n        var minHeight = (int)Math.Max(_context.ToPixels(_settingsView.RowHeight), MinRowHeight);\n\n        //it is neccesary to set both\n        layout.SetMinimumHeight(minHeight);\n        nativeCell.SetMinimumHeight(minHeight);\n\n        if (!_settingsView.HasUnevenRows)\n        {\n            // if not Uneven, set the larger one of RowHeight and MinRowHeight.\n            layout.LayoutParameters.Height = minHeight;\n        }\n        else if (virtualCell.Height > -1)\n        {\n            // if the cell itself was specified height, set it.\n            layout.SetMinimumHeight((int)_context.ToPixels(virtualCell.Height));\n            layout.LayoutParameters.Height = (int)_context.ToPixels(virtualCell.Height);\n        }        \n        else\n        {\n            layout.LayoutParameters.Height = -2; //wrap_content\n        }\n\n        holder.Body.AddView(nativeCell, 0);\n    }\n\n\n    /// <summary>\n    /// Cells the moved.\n    /// </summary>\n    /// <param name=\"fromPos\">From position.</param>\n    /// <param name=\"toPos\">To position.</param>\n    public void CellMoved(int fromPos,int toPos)\n    {\n        var tmp = _proxy[fromPos];\n        _proxy.RemoveAt(fromPos);\n        _proxy.Insert(toPos,tmp);\n    }\n\n}\n\n\n"
  },
  {
    "path": "SettingsView/Native/Android/ViewHolders.cs",
    "content": "﻿using Android.Views;\nusing Android.Widget;\nusing AndroidX.RecyclerView.Widget;\nusing Microsoft.Maui.Controls.Compatibility;\nusing AView = Android.Views.View;\nusing Resource = global::AiForms.Settings.Resource;\n\nnamespace AiForms.Settings.Platforms.Droid;\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal class ViewHolder : RecyclerView.ViewHolder\n{\n    public RowInfo RowInfo { get; set; }\n\n    public ViewHolder(AView view) : base(view) { }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            ItemView?.Dispose();\n            ItemView = null;\n        }\n        base.Dispose(disposing);\n    }\n}\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal interface IHeaderViewHolder\n{ \n}\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal interface IFooterViewHolder\n{\n}\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal class HeaderViewHolder :ViewHolder, IHeaderViewHolder\n{\n    public TextView TextView { get; private set; }\n\n    public HeaderViewHolder(AView view) : base(view)\n    {\n        TextView = view.FindViewById<TextView>(Resource.Id.HeaderCellText);\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            TextView?.Dispose();\n            TextView = null;\n        }\n        base.Dispose(disposing);\n    }\n}\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal class FooterViewHolder :ViewHolder, IFooterViewHolder\n{\n    public TextView TextView { get; private set; }\n\n    public FooterViewHolder(AView view) : base(view)\n    {\n        TextView = view.FindViewById<TextView>(Resource.Id.FooterCellText);\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            TextView?.Dispose();\n            TextView = null;\n        }\n        base.Dispose(disposing);\n    }\n}\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal class CustomHeaderViewHolder :ViewHolder, IHeaderViewHolder\n{\n    public CustomHeaderViewHolder(AView view) : base(view)\n    {\n        view.LayoutParameters = new ViewGroup.LayoutParams(-1, -2);\n    }       \n}\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal class CustomFooterViewHolder :ViewHolder, IFooterViewHolder\n{\n    public CustomFooterViewHolder(AView view) : base(view)\n    {\n        view.LayoutParameters = new ViewGroup.LayoutParams(-1, -2);\n    }\n}\n\n[Android.Runtime.Preserve(AllMembers = true)]\ninternal class ContentBodyViewHolder : ViewHolder\n{\n    public LinearLayout Body { get; private set; }\n    //public RowInfo RowInfo { get; set; }\n\n    public ContentBodyViewHolder(AView view) : base(view)\n    {\n        Body = view.FindViewById<LinearLayout>(Resource.Id.ContentCellBody);\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            var nativeCell = Body.GetChildAt(0);            \n            nativeCell?.Dispose();\n            Body?.Dispose();\n            Body = null;\n            ItemView.SetOnClickListener(null);\n            ItemView.SetOnLongClickListener(null);\n        }\n        base.Dispose(disposing);\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/AiTableView.cs",
    "content": "﻿using System;\nusing System.Collections.Specialized;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Controls;\nusing Microsoft.Maui.Controls.Compatibility.Platform.iOS;\nusing MobileCoreServices;\nusing ObjCRuntime;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\npublic class AiTableView: UITableView, IUITableViewDragDelegate, IUITableViewDropDelegate\n{\n    internal static readonly string TextHeaderId = \"textHeaderView\";\n    internal static readonly string TextFooterId = \"textFooterView\";\n    internal static readonly string CustomHeaderId = \"customHeaderView\";\n    internal static readonly string CustomFooterId = \"customFooterView\";\n    internal static float MinRowHeight = 48;\n\n    SettingsView _settingsView;\n    SettingsModel _model => _settingsView.Model;\n\n    public AiTableView(SettingsView settingsView) : base(CGRect.Empty, UITableViewStyle.Grouped)\n    {\n        _settingsView = settingsView;\n\n        DragDelegate = this;\n        DropDelegate = this;\n\n        DragInteractionEnabled = true;\n        Source = new SettingsTableSource(settingsView);\n\n        ScrollEnabled = true;\n        RowHeight = UITableView.AutomaticDimension;\n        KeyboardDismissMode = UIScrollViewKeyboardDismissMode.OnDrag;\n\n        CellLayoutMarginsFollowReadableWidth = false;\n\n        SectionHeaderHeight = UITableView.AutomaticDimension;\n        EstimatedSectionHeaderHeight = UITableView.AutomaticDimension;\n\n        SectionFooterHeight = UITableView.AutomaticDimension;\n        EstimatedSectionFooterHeight = UITableView.AutomaticDimension;\n\n        RegisterClassForHeaderFooterViewReuse(typeof(TextHeaderView), TextHeaderId);\n        RegisterClassForHeaderFooterViewReuse(typeof(TextFooterView), TextFooterId);\n        RegisterClassForHeaderFooterViewReuse(typeof(CustomHeaderView), CustomHeaderId);\n        RegisterClassForHeaderFooterViewReuse(typeof(CustomFooterView), CustomFooterId);               \n        \n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            Source?.Dispose();\n            Source = null;\n            foreach (UIView subview in Subviews)\n            {\n                DisposeSubviews(subview);\n            }\n            _settingsView = null;\n        }\n        base.Dispose(disposing);\n    }   \n\n    void DisposeSubviews(UIView view)\n    {\n        var ver = view as IVisualElementRenderer;\n\n        if (ver == null)\n        {\n            foreach (UIView subView in view.Subviews)\n            {\n                DisposeSubviews(subView);\n            }\n\n            view.RemoveFromSuperview();\n        }\n\n        view.Dispose();\n    }\n\n    internal void UpdateSections(NotifyCollectionChangedEventArgs e)\n    {\n        switch (e.Action)\n        {\n            case NotifyCollectionChangedAction.Add:\n                if (e.NewStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n                BeginUpdates();\n                InsertSections(NSIndexSet.FromIndex(e.NewStartingIndex), UITableViewRowAnimation.Automatic);\n                EndUpdates();\n                break;\n            case NotifyCollectionChangedAction.Remove:\n                if (e.OldStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n                BeginUpdates();\n                DeleteSections(NSIndexSet.FromIndex(e.OldStartingIndex), UITableViewRowAnimation.Automatic);\n                EndUpdates();\n                break;\n\n            case NotifyCollectionChangedAction.Replace:\n                if (e.OldStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n                BeginUpdates();\n                ReloadSections(NSIndexSet.FromIndex(e.OldStartingIndex), UITableViewRowAnimation.Automatic);\n                EndUpdates();\n\n                break;\n\n            case NotifyCollectionChangedAction.Move:\n            case NotifyCollectionChangedAction.Reset:\n\n                ReloadData();\n                return;\n        }\n    }\n\n    internal void UpdateItems(NotifyCollectionChangedEventArgs e, int section, bool resetWhenGrouped)\n    {\n        // This means the UITableView hasn't rendered any cells yet\n        // so there's no need to synchronize the rows on the UITableView\n        if (IndexPathsForVisibleRows == null && e.Action != NotifyCollectionChangedAction.Reset)\n            return;\n\n        // If the section is not visible, do nothing.\n        if (!_model.GetSection(section).IsVisible)\n        {\n            return;\n        }\n\n        switch (e.Action)\n        {\n            case NotifyCollectionChangedAction.Add:\n                if (e.NewStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n\n                BeginUpdates();\n                InsertRows(GetPaths(section, e.NewStartingIndex, e.NewItems.Count), UITableViewRowAnimation.Automatic);\n                EndUpdates();\n\n                break;\n\n            case NotifyCollectionChangedAction.Remove:\n                if (e.OldStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n\n                BeginUpdates();\n                DeleteRows(GetPaths(section, e.OldStartingIndex, e.OldItems.Count), UITableViewRowAnimation.Automatic);\n                EndUpdates();\n\n                break;\n\n            case NotifyCollectionChangedAction.Move:\n                if (e.OldStartingIndex == -1 || e.NewStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n\n                BeginUpdates();\n                for (var i = 0; i < e.OldItems.Count; i++)\n                {\n                    var oldi = e.OldStartingIndex;\n                    var newi = e.NewStartingIndex;\n\n                    if (e.NewStartingIndex < e.OldStartingIndex)\n                    {\n                        oldi += i;\n                        newi += i;\n                    }\n\n                    MoveRow(NSIndexPath.FromRowSection(oldi, section), NSIndexPath.FromRowSection(newi, section));\n                }\n                EndUpdates();\n\n                break;\n\n            case NotifyCollectionChangedAction.Replace:\n                if (e.OldStartingIndex == -1)\n                {\n                    goto case NotifyCollectionChangedAction.Reset;\n                }\n\n                BeginUpdates();\n                ReloadRows(GetPaths(section, e.OldStartingIndex, e.OldItems.Count), UITableViewRowAnimation.None);\n                EndUpdates();\n\n                break;\n\n            case NotifyCollectionChangedAction.Reset:\n                ReloadData();\n                return;\n        }\n    }   \n\n    internal void UpdateSectionVisible(Section section)\n    {\n        var secIndex = _model.GetSectionIndex(section);\n        BeginUpdates();\n        ReloadSections(NSIndexSet.FromIndex(secIndex), UITableViewRowAnimation.Automatic);\n        EndUpdates();\n    }\n\n    internal void UpdateCellVisible(Section section, CellBase cell)\n    {\n        var secIndex = _model.GetSectionIndex(section);\n        var rowIndex = section.IndexOf(cell);\n        BeginUpdates();\n        ReloadRows(GetPaths(secIndex, rowIndex, 1), UITableViewRowAnimation.Automatic);\n        EndUpdates();\n    }\n\n    internal void ReloadCell(CellBase cell)\n    {\n        var secIndex = _model.GetSectionIndex(cell.Section);\n        var rowIndex = cell.Section.IndexOf(cell);\n        BeginUpdates();\n        ReloadRows(GetPaths(secIndex, rowIndex, 1), UITableViewRowAnimation.None);\n        EndUpdates();\n    }\n\n    internal void UpdateSectionNoAnimation(Section section)\n    {\n        var secIndex = _model.GetSectionIndex(section);\n        BeginUpdates();\n        ReloadSections(NSIndexSet.FromIndex(secIndex), UITableViewRowAnimation.None);\n        EndUpdates();\n    }\n\n    internal void UpdateSectionFade(Section section)\n    {\n        var secIndex = _model.GetSectionIndex(section);\n        BeginUpdates();\n        ReloadSections(NSIndexSet.FromIndex(secIndex), UITableViewRowAnimation.Fade);\n        EndUpdates();\n    }\n\n    public UIDragItem[] GetItemsForBeginningDragSession(UITableView tableView, IUIDragSession session, NSIndexPath indexPath)\n    {\n        var section = _model.GetSection(indexPath.Section);\n        if (!section.UseDragSort)\n        {\n            return new UIDragItem[] { };\n        }\n\n        var cell = _model.GetCell(indexPath.Section, indexPath.Row);\n        if (!cell.IsEnabled)\n        {\n            return new UIDragItem[] { };\n        }\n\n        // set \"sectionIndex,rowIndex\" as string\n        var data = NSData.FromString($\"{indexPath.Section},{indexPath.Row}\");\n\n        var itemProvider = new NSItemProvider();\n        itemProvider.RegisterDataRepresentation(UTType.PlainText, NSItemProviderRepresentationVisibility.All, (completionHandler) =>\n        {\n            completionHandler(data, null);\n            return null;\n        });\n\n        return new UIDragItem[] { new UIDragItem(itemProvider) };\n    }\n\n    public void PerformDrop(UITableView tableView, IUITableViewDropCoordinator coordinator)\n    {\n        var destinationIndexPath = coordinator.DestinationIndexPath;\n        if (destinationIndexPath == null)\n        {\n            return;\n        }\n\n        coordinator.Session.LoadObjects<NSString>(items => {\n            var path = items[0].ToString().Split(new char[] { ',' }, StringSplitOptions.None).Select(x => int.Parse(x)).ToList();\n            var secIdx = path[0];\n            var rowIdx = path[1];\n\n\n            var section = _model.GetSection(secIdx);\n            var destSection = _model.GetSection(destinationIndexPath.Section);\n            if (!destSection.UseDragSort)\n            {\n                return;\n            }\n\n            // save scroll position\n            var offset = ContentOffset;\n            var fromCell = CellAt(NSIndexPath.FromRowSection(rowIdx, secIdx));\n\n            if (section.ItemsSource == null)\n            {\n                // Don't use PerformBatchUpdates. Because can't cancel animations well.\n                BeginUpdates();\n\n                var cell = section.DeleteCellWithoutNotify(rowIdx);\n                destSection.InsertCellWithoutNotify(cell, destinationIndexPath.Row);\n                DeleteRows(GetPaths(secIdx, rowIdx, 1), UITableViewRowAnimation.None);\n                InsertRows(GetPaths(destinationIndexPath.Section, destinationIndexPath.Row, 1), UITableViewRowAnimation.None);\n\n                EndUpdates();\n\n                _settingsView.SendItemDropped(destSection, cell);\n            }\n            else\n            {\n                // Don't use PerformBatchUpdates. Because can't cancel animations well.\n                BeginUpdates();\n\n                var deletedSet = section.DeleteSourceItemWithoutNotify(rowIdx);\n                destSection.InsertSourceItemWithoutNotify(deletedSet.Cell, deletedSet.Item, destinationIndexPath.Row);\n                DeleteRows(GetPaths(secIdx, rowIdx, 1), UITableViewRowAnimation.None);\n                InsertRows(GetPaths(destinationIndexPath.Section, destinationIndexPath.Row, 1), UITableViewRowAnimation.None);\n\n                EndUpdates();\n                _settingsView.SendItemDropped(destSection, deletedSet.Cell);\n            }\n\n            // Cancel animations and restore the scroll position.\n            var toCell = CellAt(destinationIndexPath);\n            toCell?.Layer?.RemoveAllAnimations();\n            fromCell?.Layer?.RemoveAllAnimations();\n            Layer.RemoveAllAnimations();\n            SetContentOffset(offset, false);\n\n            // nothing occur, even if use the following code.\n            //coordinator.DropItemToRow(coordinator.Items.First().DragItem, destinationIndexPath);\n        });\n    }\n\n    protected virtual NSIndexPath[] GetPaths(int section, int index, int count)\n    {\n        var paths = new NSIndexPath[count];\n        for (var i = 0; i < paths.Length; i++)\n        {\n            paths[i] = NSIndexPath.FromRowSection(index + i, section);\n        }\n\n        return paths;\n    }\n\n    /// <summary>\n    /// Ensure that the drop session contains a drag item with a data representation that the view can consume.\n    /// </summary>\n    [Export(\"tableView:canHandleDropSession:\")]\n    public bool CanHandleDropSession(UITableView tableView, IUIDropSession session)\n    {\n        return session.CanLoadObjects(typeof(NSString));\n    }\n\n    [Export(\"tableView:dropSessionDidEnter:\")]\n    public void DropSessionDidEnter(UITableView tableView, IUIDropSession session)\n    {\n    }\n\n    [Export(\"tableView:dropSessionDidEnd:\")]\n    public void DropSessionDidEnd(UITableView tableView, IUIDropSession session)\n    {\n    }\n\n    [Export(\"tableView:dropSessionDidExit:\")]\n    public void DropSessionDidExit(UITableView tableView, IUIDropSession session)\n    {\n    }\n\n    /// <summary>\n    /// A drop proposal from a table view includes two items: a drop operation,\n    /// typically .move or .copy; and an intent, which declares the action the\n    /// table view will take upon receiving the items. (A drop proposal from a\n    /// custom view does includes only a drop operation, not an intent.)\n    /// </summary>\n    [Export(\"tableView:dropSessionDidUpdate:withDestinationIndexPath:\")]\n    public UITableViewDropProposal DropSessionDidUpdate(UITableView tableView, IUIDropSession session, NSIndexPath destinationIndexPath)\n    {\n        if (destinationIndexPath == null)\n        {\n            return new UITableViewDropProposal(UIDropOperation.Cancel);\n        }\n\n        // this dragging is from UITableView.\n        if (tableView.HasActiveDrag)\n        {\n            if (session.Items.Length > 1)\n            {\n                return new UITableViewDropProposal(UIDropOperation.Cancel);\n            }\n            else\n            {\n                return new UITableViewDropProposal(UIDropOperation.Move, UITableViewDropIntent.Automatic);\n            }\n        }\n\n        return new UITableViewDropProposal(UIDropOperation.Cancel);\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/ButtonCellView.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\nusing Foundation;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Button cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class ButtonCellView : CellBaseView\n{\n    Action Execute { get; set; }\n    ButtonCell _ButtonCell => Cell as ButtonCell;\n    ICommand _command;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.ButtonCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public ButtonCellView(CellBase virtualCell) : base(virtualCell)\n    {\n        DescriptionLabel.Hidden = true;\n        SelectionStyle = UIKit.UITableViewCellSelectionStyle.Default;\n        TitleLabel.TextAlignment = UIKit.UITextAlignment.Right;\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);        \n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        tableView.DeselectRow(indexPath, true);\n        Execute?.Invoke();\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n        if (TitleLabel is null)\n            return; // For HotReload\n\n        //UpdateCommand();\n        //UpdateTitleAlignment();\n    }\n\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_command != null)\n            {\n                _command.CanExecuteChanged -= Command_CanExecuteChanged;\n            }\n            Execute = null;\n            _command = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    internal void UpdateTitleAlignment()\n    {\n        TitleLabel.TextAlignment = _ButtonCell.TitleAlignment.ToUITextAlignment();\n    }\n\n    internal void UpdateCommand()\n    {\n        if (_command != null)\n        {\n            _command.CanExecuteChanged -= Command_CanExecuteChanged;\n        }\n\n        _command = _ButtonCell.Command;\n\n        if (_command != null)\n        {\n            _command.CanExecuteChanged += Command_CanExecuteChanged;\n            Command_CanExecuteChanged(_command, System.EventArgs.Empty);\n        }\n\n        Execute = () =>\n        {\n            if (_command == null)\n            {\n                return;\n            }\n            if (_command.CanExecute(_ButtonCell.CommandParameter))\n            {\n                _command.Execute(_ButtonCell.CommandParameter);\n            }\n        };\n\n    }\n\n    /// <summary>\n    /// Updates the is enabled.\n    /// </summary>\n    internal override void UpdateIsEnabled()\n    {\n        if (_command != null && !_command.CanExecute(_ButtonCell.CommandParameter))\n        {\n            return;\n        }\n        base.UpdateIsEnabled();\n    }\n\n    void Command_CanExecuteChanged(object sender, EventArgs e)\n    {\n        if (!Cell.IsEnabled)\n        {\n            return;\n        }\n\n        SetEnabledAppearance(_command.CanExecute(_ButtonCell.CommandParameter));\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/CellBaseView.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing UIKit;\nusing Foundation;\nusing CoreGraphics;\nusing CoreFoundation;\nusing Microsoft.Maui.Controls.Handlers.Compatibility;\nusing Microsoft.Maui.Platform;\nusing System.Runtime.InteropServices;\nusing Microsoft.Maui.Controls.Compatibility;\nusing AiForms.Settings.Handlers;\nusing System.Security.Cryptography;\nusing AiForms.Settings.Extensions;\nusing Microsoft.Maui.Controls.Platform;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\n/// <summary>\n/// Cell base view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class CellBaseView : UITableViewCell, IImageSourcePartSetter\n{\n    /// <summary>\n    /// Gets the hint label.\n    /// </summary>\n    /// <value>The hint label.</value>\n    public UILabel HintLabel { get; private set; }\n    /// <summary>\n    /// Gets the title label.\n    /// </summary>\n    /// <value>The title label.</value>\n    public UILabel TitleLabel { get; private set; }\n    /// <summary>\n    /// Gets the description label.\n    /// </summary>\n    /// <value>The description label.</value>\n    public UILabel DescriptionLabel { get; private set; }\n    /// <summary>\n    /// Gets the icon view.\n    /// </summary>\n    /// <value>The icon view.</value>\n    public UIImageView IconView { get; private set; }\n\n    /// <summary>\n    /// Gets the cell parent.\n    /// </summary>\n    /// <value>The cell parent.</value>\n    public SettingsView CellParent => Cell.Parent as SettingsView;\n\n    CellBase _cell;\n    public CellBase Cell\n    {\n        get { return _cell; }\n        set\n        {\n            if (_cell == value)\n                return;\n\n            if (_cell != null)\n            {\n                _cell.PropertyChanged -= CellPropertyChanged;\n                _imageLoader?.Reset();\n                _imageLoader = null;\n            }\n            _cell = value;\n\n            if (_cell != null)\n            {\n                _cell.PropertyChanged += CellPropertyChanged;                \n            }\n        }\n    }\n\n    protected Lazy<IFontManager> _fontManager;\n    ImageSourcePartLoader _imageLoader;\n\n    /// <summary>\n    /// Gets the content stack.\n    /// </summary>\n    /// <value>The content stack.</value>\n    protected UIStackView ContentStack { get; private set; }\n\n    IElementHandler IImageSourcePartSetter.Handler => Cell.Handler;\n    IImageSourcePart IImageSourcePartSetter.ImageSourcePart => Cell;\n\n    protected UIStackView StackH;\n    protected UIStackView StackV;\n\n    \n    Size _iconSize;\n    NSLayoutConstraint _iconConstraintHeight;\n    NSLayoutConstraint _iconConstraintWidth;\n    NSLayoutConstraint _minheightConstraint;\n    CancellationTokenSource _iconTokenSource;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.CellBaseView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public CellBaseView(CellBase virtualCell) : base(UIKit.UITableViewCellStyle.Default, virtualCell.GetType().FullName)\n    {\n        Cell = virtualCell;\n\n        SelectionStyle = UITableViewCellSelectionStyle.None;\n        SetUpHintLabel();\n        SetUpContentView();\n\n        UpdateSelectedColor();\n\n        _fontManager = new Lazy<IFontManager>(() =>\n        {\n            return virtualCell.FindMauiContext().Services.GetService<IFontManager>();\n        });\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public virtual void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {       \n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public virtual void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        if (e.PropertyName == SettingsView.CellTitleColorProperty.PropertyName)\n        {\n            UpdateTitleColor();\n        }\n        else if (e.PropertyName == SettingsView.CellTitleFontSizeProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellTitleFontFamilyProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellTitleFontAttributesProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateTitleFont);\n        }\n        else if (e.PropertyName == SettingsView.CellDescriptionColorProperty.PropertyName)\n        {\n            UpdateDescriptionColor();\n        }\n        else if (e.PropertyName == SettingsView.CellDescriptionFontSizeProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellDescriptionFontFamilyProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellDescriptionFontAttributesProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateDescriptionFont);\n        }\n        else if (e.PropertyName == SettingsView.CellBackgroundColorProperty.PropertyName)\n        {\n            UpdateBackgroundColor();\n        }\n        else if (e.PropertyName == SettingsView.CellHintTextColorProperty.PropertyName)\n        {\n            UpdateHintTextColor();\n        }\n        else if (e.PropertyName == SettingsView.CellHintFontSizeProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellHintFontFamilyProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellHintFontAttributesProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateHintFont);\n        }\n        else if (e.PropertyName == SettingsView.CellIconSizeProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateIconSize);\n        }\n        else if (e.PropertyName == SettingsView.CellIconRadiusProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateIconRadius);\n        }\n        else if (e.PropertyName == SettingsView.SelectedColorProperty.PropertyName)\n        {\n            UpdateSelectedColor();\n        }\n        else if (e.PropertyName == SettingsView.RowHeightProperty.PropertyName)\n        {\n            UpdateMinRowHeight();\n        }\n    }\n\n    /// <summary>\n    /// Sections the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public virtual void SectionPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public virtual void RowSelected(UITableView tableView,NSIndexPath indexPath)\n    {\n    }\n\n    public virtual bool RowLongPressed(UITableView tableView,NSIndexPath indexPath)\n    {\n        return false;\n    }\n\n    /// <summary>\n    /// Updates the with force layout.\n    /// </summary>\n    /// <param name=\"updateAction\">Update action.</param>\n    internal void UpdateWithForceLayout(System.Action updateAction)\n    {\n        updateAction();\n        SetNeedsLayout();\n    }\n\n    internal void UpdateLayout()\n    {\n        SetNeedsLayout();\n    }\n\n    internal void UpdateSelectedColor()\n    {\n        if (CellParent != null && CellParent.SelectedColor.IsNotDefault()) {\n            if (SelectedBackgroundView != null) {\n                SelectedBackgroundView.BackgroundColor = CellParent.SelectedColor.ToPlatform();\n            }\n            else {\n                SelectedBackgroundView = new UIView { BackgroundColor = CellParent.SelectedColor.ToPlatform() };\n            }\n        }\n    }\n\n    internal void UpdateBackgroundColor()\n    {\n        if (Cell.BackgroundColor.IsNotDefault()) {\n            BackgroundColor = Cell.BackgroundColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellBackgroundColor.IsNotDefault()) {\n            BackgroundColor = CellParent.CellBackgroundColor.ToPlatform();\n        }\n    }\n\n    internal void UpdateHintText()\n    {\n        if (HintLabel is null)\n            return; // for HotReload\n\n        HintLabel.Text = Cell.HintText;\n        HintLabel.Hidden = string.IsNullOrEmpty(Cell.HintText);\n    }\n\n    internal void UpdateHintTextColor()\n    {\n        if (HintLabel is null)\n            return; // for HotReload\n\n        if (Cell.HintTextColor.IsNotDefault())\n        {\n            HintLabel.TextColor = Cell.HintTextColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellHintTextColor.IsNotDefault())\n        {\n            HintLabel.TextColor = CellParent.CellHintTextColor.ToPlatform();\n        }\n    }\n\n    internal void UpdateHintFont()\n    {\n        if (HintLabel is null)\n            return; // for HotReload\n\n        var family = Cell.HintFontFamily ?? CellParent.CellHintFontFamily;\n        var attr = Cell.HintFontAttributes ?? CellParent.CellHintFontAttributes;\n\n        if (Cell.HintFontSize > 0)\n        {\n            HintLabel.Font = family.ToFont(Cell.HintFontSize, attr).ToUIFont(_fontManager.Value);\n        }\n        else if (CellParent != null)\n        {\n            HintLabel.Font = family.ToFont(CellParent.CellHintFontSize, attr).ToUIFont(_fontManager.Value);\n        }\n    }\n\n    internal void UpdateTitleText()\n    {\n        if (TitleLabel is null)\n            return; // for HotReload\n\n        TitleLabel.Text = Cell.Title;\n        //Since Layout breaks when text empty, prevent Label height from resizing 0.\n        if (string.IsNullOrEmpty(TitleLabel.Text))\n        {\n            TitleLabel.Hidden = true;\n            TitleLabel.Text = \" \";\n        }\n        else\n        {\n            TitleLabel.Hidden = false;\n        }\n\n    }\n\n    internal void UpdateTitleColor()\n    {\n        if (TitleLabel is null)\n            return; // for HotReload\n\n        if (Cell.TitleColor.IsNotDefault())\n        {\n            TitleLabel.TextColor = Cell.TitleColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellTitleColor.IsNotDefault())\n        {\n            TitleLabel.TextColor = CellParent.CellTitleColor.ToPlatform();\n        }\n    }\n\n    internal void UpdateTitleFont()\n    {\n        if (TitleLabel is null)\n            return; // for HotReload\n\n        var family = Cell.TitleFontFamily ?? CellParent.CellTitleFontFamily;\n        var attr = Cell.TitleFontAttributes ?? CellParent.CellTitleFontAttributes;\n\n        if (Cell.TitleFontSize > 0)\n        {\n            TitleLabel.Font = family.ToFont(Cell.TitleFontSize, attr).ToUIFont(_fontManager.Value);\n        }\n        else if (CellParent != null)\n        {\n            TitleLabel.Font = family.ToFont(CellParent.CellTitleFontSize, attr).ToUIFont(_fontManager.Value); \n        }\n    }\n\n    internal void UpdateDescriptionText()\n    {\n        if (DescriptionLabel is null)\n            return; // for HotReload\n\n        DescriptionLabel.Text = Cell.Description;\n        //layout break because of StackView spacing.DescriptionLabel hidden to fix it. \n        DescriptionLabel.Hidden = string.IsNullOrEmpty(DescriptionLabel.Text);\n\n        if (CellParent.HasUnevenRows)\n        {\n            if (CellParent.Handler.PlatformView is AiTableView tv)\n            {\n                // TODO: The following code is needed to dynamically change the cell height\n                // according to the contents of the Description, but it is commented out\n                // because it causes scrolling problems.\n                // The workaround is probably to do it at the timing of PropertyChanged.\n                //tv.BeginUpdates();\n                //tv.EndUpdates();                \n            }\n        }       \n    }\n\n    internal void UpdateDescriptionFont()\n    {\n        if (DescriptionLabel is null)\n            return; // for HotReload\n\n        var family = Cell.DescriptionFontFamily ?? CellParent.CellDescriptionFontFamily;\n        var attr = Cell.DescriptionFontAttributes ?? CellParent.CellDescriptionFontAttributes;\n\n        if (Cell.DescriptionFontSize > 0)\n        {\n            DescriptionLabel.Font = family.ToFont(Cell.DescriptionFontSize, attr).ToUIFont(_fontManager.Value); \n        }\n        else if (CellParent != null)\n        {\n            DescriptionLabel.Font = family.ToFont(CellParent.CellDescriptionFontSize, attr).ToUIFont(_fontManager.Value);\n        }\n    }\n\n    internal void UpdateDescriptionColor()\n    {\n        if (DescriptionLabel is null)\n            return; // for HotReload\n\n        if (Cell.DescriptionColor.IsNotDefault()) {\n            DescriptionLabel.TextColor = Cell.DescriptionColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellDescriptionColor.IsNotDefault()) {\n            DescriptionLabel.TextColor = CellParent.CellDescriptionColor.ToPlatform();\n        }\n    }\n\n    /// <summary>\n    /// Updates the is enabled.\n    /// </summary>\n    internal virtual void UpdateIsEnabled()\n    {\n        SetEnabledAppearance(Cell.IsEnabled);\n    }\n\n    /// <summary>\n    /// Updates the IsVisible\n    /// </summary>\n    internal virtual void UpdateIsVisible()\n    {\n        // If AccessoryView is set, hide the view because it overflows outside when IsVisible is false. \n        if (AccessoryView != null)\n        {\n            AccessoryView.Hidden = !Cell.IsVisible;\n        }\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal virtual void SetEnabledAppearance(bool isEnabled)\n    {\n        if (TitleLabel is null)\n            return; // for HotReload\n\n        if (isEnabled)\n        {\n            UserInteractionEnabled = true;\n            TitleLabel.Alpha = 1f;\n            DescriptionLabel.Alpha = 1f;\n            IconView.Alpha = 1f;\n        }\n        else\n        {\n            UserInteractionEnabled = false;\n            TitleLabel.Alpha = 0.3f;\n            DescriptionLabel.Alpha = 0.3f;\n            IconView.Alpha = 0.3f;\n        }\n    }\n\n    internal void UpdateIconSize()\n    {\n        Size size;\n        if (Cell.IconSize != default(Size)) {\n            size = Cell.IconSize;\n        }\n        else if (CellParent != null && CellParent.CellIconSize != default(Size)) {\n            size = CellParent.CellIconSize;\n        }\n        else {\n            size = new Size(32, 32);\n        }\n\n        //do nothing when current size is previous size\n        if (size == _iconSize) {\n            return;\n        }\n\n        if (_iconSize != default(Size)) {\n            //remove previous constraint\n            _iconConstraintHeight.Active = false;\n            _iconConstraintWidth.Active = false;\n            _iconConstraintHeight?.Dispose();\n            _iconConstraintWidth?.Dispose();\n        }\n\n        _iconConstraintHeight = IconView.HeightAnchor.ConstraintEqualTo((NFloat)size.Height);\n        _iconConstraintWidth = IconView.WidthAnchor.ConstraintEqualTo((NFloat)size.Width);\n\n        _iconConstraintHeight.Priority = 999f; // fix warning-log:Unable to simultaneously satisfy constraints.\n        _iconConstraintHeight.Active = true;\n        _iconConstraintWidth.Active = true;\n\n        IconView.UpdateConstraints();\n\n        _iconSize = size;\n    }\n\n    internal void UpdateIconRadius()\n    {\n        if (IconView is null)\n            return; // for HotReload\n\n        if (Cell.IconRadius >= 0) {\n            IconView.Layer.CornerRadius = (float)Cell.IconRadius;\n        }\n        else if (CellParent != null) {\n            IconView.Layer.CornerRadius = (float)CellParent.CellIconRadius;\n        }\n    }\n\n    internal void UpdateIcon()\n    {        \n        if (IconView is null)\n            return; // for HotReload\n\n        _imageLoader?.Reset();\n       \n        UpdateIconSize();\n\n        if (IconView.Image != null)\n        {           \n            IconView.Image = null;\n        }\n\n        if (Cell.IconSource != null)\n        {\n            //image未設定の時はhiddenにしないとstackviewのDistributionが機能しなくなる\n            //hide IconView because UIStackView Distribution won't work when a image isn't set.\n            IconView.Hidden = false;\n\n            _imageLoader = new ImageSourcePartLoader(this);\n            _imageLoader.UpdateImageSourceAsync();                 \n        }\n        else\n        {\n            IconView.Hidden = true;\n        }\n    }\n\n    void IImageSourcePartSetter.SetImageSource(UIImage platformImage)\n    {\n        IconView.Image = platformImage;\n        SetNeedsLayout();\n    }\n\n\n    internal void UpdateMinRowHeight()\n    {\n        if (_minheightConstraint != null) {\n            _minheightConstraint.Active = false;\n            _minheightConstraint.Dispose();\n            _minheightConstraint = null;\n        }\n\n        if (CellParent.HasUnevenRows) {\n            _minheightConstraint = StackH.HeightAnchor.ConstraintGreaterThanOrEqualTo(CellParent.RowHeight);\n            _minheightConstraint.Priority = 999f;\n            _minheightConstraint.Active = true;\n\n        }\n\n        StackH.UpdateConstraints();\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public virtual void UpdateCell(UITableView tableView = null)\n    {\n        if (TitleLabel is null)\n            return; // For HotReload\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _imageLoader?.Reset();\n            _imageLoader = null;\n\n            if(_cell != null)\n            {\n                CellParent.PropertyChanged -= ParentPropertyChanged;\n                _cell.PropertyChanged -= CellPropertyChanged;\n                if (_cell.Section != null)\n                {\n                    _cell.Section.PropertyChanged -= SectionPropertyChanged;\n                    _cell.Section = null;\n                }\n\n\n                //CellRenderer.SetRealCell(_cell, null);\n                _cell = null;\n            }\n\n            SelectedBackgroundView?.Dispose();\n            SelectedBackgroundView = null;\n\n            BeginInvokeOnMainThread(() =>\n            {\n                HintLabel.RemoveFromSuperview();\n                HintLabel.Dispose();\n                HintLabel = null;\n                TitleLabel?.Dispose();\n                TitleLabel = null;\n                DescriptionLabel?.Dispose();\n                DescriptionLabel = null;\n                IconView.RemoveFromSuperview();\n                IconView.Image?.Dispose();\n                IconView.Dispose();\n                IconView = null;\n                _iconTokenSource?.Dispose();\n                _iconTokenSource = null;\n                _iconConstraintWidth?.Dispose();\n                _iconConstraintHeight?.Dispose();\n                _iconConstraintHeight = null;\n                _iconConstraintWidth = null;\n                ContentStack?.RemoveFromSuperview();\n                ContentStack?.Dispose();\n                ContentStack = null;\n\n                StackV?.RemoveFromSuperview();\n                StackV?.Dispose();\n                StackV = null;\n\n                StackH.RemoveFromSuperview();\n                StackH.Dispose();\n                StackH = null;\n\n            });\n        }\n\n        base.Dispose(disposing);\n    }\n\n    void SetUpHintLabel()\n    {\n        HintLabel = new UILabel();\n        HintLabel.LineBreakMode = UILineBreakMode.Clip;\n        HintLabel.Lines = 0;\n        HintLabel.TintAdjustmentMode = UIViewTintAdjustmentMode.Automatic;\n        HintLabel.AdjustsFontSizeToFitWidth = true;\n        HintLabel.BaselineAdjustment = UIBaselineAdjustment.AlignCenters;\n        HintLabel.TextAlignment = UITextAlignment.Right;\n        HintLabel.AdjustsLetterSpacingToFitWidth = true;\n\n        this.AddSubview(HintLabel);\n\n        HintLabel.TranslatesAutoresizingMaskIntoConstraints = false;\n        HintLabel.TopAnchor.ConstraintEqualTo(this.TopAnchor, 2).Active = true;\n        HintLabel.LeftAnchor.ConstraintEqualTo(this.LeftAnchor, 16).Active = true;\n        HintLabel.RightAnchor.ConstraintEqualTo(ContentView.RightAnchor, -10).Active = true;\n        HintLabel.BottomAnchor.ConstraintLessThanOrEqualTo(this.BottomAnchor, -12).Active = true;\n\n        HintLabel.SizeToFit();\n        BringSubviewToFront(HintLabel);\n    }\n\n    /// <summary>\n    /// Sets the right margin zero.\n    /// </summary>\n    protected void SetRightMarginZero()\n    {\n        if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))\n        {\n            StackH.LayoutMargins = new UIEdgeInsets(6, 16, 6, 0);\n        }\n    }\n\n\n    protected virtual void SetUpContentView()\n    {\n        //remove existing views \n        ImageView.RemoveFromSuperview();\n        TextLabel.RemoveFromSuperview();\n        ImageView.Hidden = true;\n        TextLabel.Hidden = true;\n\n        //外側のHorizontalStackView\n        //Outer HorizontalStackView\n        StackH = new UIStackView\n        {\n            Axis = UILayoutConstraintAxis.Horizontal,\n            Alignment = UIStackViewAlignment.Center,\n            Spacing = 16,\n            Distribution = UIStackViewDistribution.Fill\n        };\n        //set margin\n        StackH.LayoutMargins = new UIEdgeInsets(6, 16, 6, 16);\n        StackH.LayoutMarginsRelativeArrangement = true;\n\n        IconView = new UIImageView();\n\n        //round corners\n        IconView.ClipsToBounds = true;\n\n        StackH.AddArrangedSubview(IconView);\n\n        UpdateIconSize();\n\n        //右に配置するVerticalStackView（コアの部品とDescriptionを格納）\n        //VerticalStackView that is arranged at right. ( put main parts and Description ) \n        StackV = new UIStackView\n        {\n            Axis = UILayoutConstraintAxis.Vertical,\n            Alignment = UIStackViewAlignment.Fill,\n            Spacing = 4,\n            Distribution = UIStackViewDistribution.Fill,\n        };\n\n        //右側上段に配置するHorizontalStackView(LabelTextとValueTextを格納）\n        //HorizontalStackView that is arranged at upper in right.(put LabelText and ValueText)\n        ContentStack = new UIStackView\n        {\n            Axis = UILayoutConstraintAxis.Horizontal,\n            Alignment = UIStackViewAlignment.Fill,\n            Spacing = 6,\n            Distribution = UIStackViewDistribution.Fill,\n        };\n\n        TitleLabel = new UILabel();\n        DescriptionLabel = new UILabel();\n\n        DescriptionLabel.Lines = 0;\n        DescriptionLabel.LineBreakMode = UILineBreakMode.WordWrap;\n\n        ContentStack.AddArrangedSubview(TitleLabel);\n\n        StackV.AddArrangedSubview(ContentStack);\n        StackV.AddArrangedSubview(DescriptionLabel);\n\n        StackH.AddArrangedSubview(StackV);\n\n        //余った領域を広げる優先度の設定（低いものが優先して拡大する）\n        IconView.SetContentHuggingPriority(999f, UILayoutConstraintAxis.Horizontal); //if possible, not to expand. 極力広げない\n        StackV.SetContentHuggingPriority(1f, UILayoutConstraintAxis.Horizontal);\n        ContentStack.SetContentHuggingPriority(1f, UILayoutConstraintAxis.Horizontal);\n        TitleLabel.SetContentHuggingPriority(1f, UILayoutConstraintAxis.Horizontal);\n        DescriptionLabel.SetContentHuggingPriority(1f, UILayoutConstraintAxis.Horizontal);\n\n\n        //縮まりやすさの設定（低いものが優先して縮まる）\n        IconView.SetContentCompressionResistancePriority(999f, UILayoutConstraintAxis.Horizontal); //if possible, not to shrink. 極力縮めない\n        StackV.SetContentCompressionResistancePriority(999f, UILayoutConstraintAxis.Horizontal);\n        ContentStack.SetContentCompressionResistancePriority(999f, UILayoutConstraintAxis.Horizontal);\n        TitleLabel.SetContentCompressionResistancePriority(999f, UILayoutConstraintAxis.Horizontal);\n        DescriptionLabel.SetContentCompressionResistancePriority(999f, UILayoutConstraintAxis.Horizontal);\n\n        IconView.SetContentCompressionResistancePriority(999f, UILayoutConstraintAxis.Vertical);\n        IconView.SetContentHuggingPriority(1f, UILayoutConstraintAxis.Vertical);\n        StackV.SetContentCompressionResistancePriority(999f, UILayoutConstraintAxis.Vertical);\n        StackV.SetContentHuggingPriority(1f, UILayoutConstraintAxis.Vertical);\n\n        ContentView.AddSubview(StackH);\n\n        StackH.TranslatesAutoresizingMaskIntoConstraints = false;\n        StackH.TopAnchor.ConstraintEqualTo(ContentView.TopAnchor).Active = true;\n        StackH.LeftAnchor.ConstraintEqualTo(ContentView.LeftAnchor).Active = true;\n        StackH.BottomAnchor.ConstraintEqualTo(ContentView.BottomAnchor).Active = true;\n        StackH.RightAnchor.ConstraintEqualTo(ContentView.RightAnchor).Active = true;\n\n\n        var minHeight = Math.Max(CellParent?.RowHeight ?? 44, SettingsViewHandler.MinRowHeight);\n        _minheightConstraint = StackH.HeightAnchor.ConstraintGreaterThanOrEqualTo(minHeight);\n        // fix warning-log:Unable to simultaneously satisfy constraints.\n        _minheightConstraint.Priority = 999f; // this is superior to any other view.\n        _minheightConstraint.Active = true;\n        \n        if (!String.IsNullOrEmpty(Cell.AutomationId)) \n        {\n            ContentStack.AccessibilityIdentifier = Cell.AutomationId;\n        }\n    }\n\n    \n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/CheckboxCellView.cs",
    "content": "﻿using CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Checkbox cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class CheckboxCellView : CellBaseView\n{\n    CheckBox _checkbox;\n    CheckboxCell _CheckboxCell => Cell as CheckboxCell;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.CheckboxCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public CheckboxCellView(CellBase virtualCell) : base(virtualCell)\n    {\n        _checkbox = new CheckBox(new CGRect(0, 0, 20, 20));\n        _checkbox.Layer.BorderWidth = 2;\n        _checkbox.Layer.CornerRadius = 3;\n        _checkbox.Inset = new UIEdgeInsets(10, 10, 10, 10);\n\n        _checkbox.CheckChanged = CheckChanged;\n\n        AccessoryView = _checkbox;\n        EditingAccessoryView = _checkbox;\n    }\n\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        base.RowSelected(tableView, indexPath);\n        _checkbox.Selected = !_checkbox.Selected;\n        CheckChanged(_checkbox);\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        //UpdateAccentColor();\n        //UpdateChecked();\n        base.UpdateCell(tableView);\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _checkbox.CheckChanged = null;\n            _checkbox?.Dispose();\n            _checkbox = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal override void SetEnabledAppearance(bool isEnabled)\n    {\n        if (isEnabled)\n        {\n            _checkbox.Alpha = 1.0f;\n        }\n        else\n        {\n            _checkbox.Alpha = 0.3f;\n        }\n        base.SetEnabledAppearance(isEnabled);\n    }\n\n    void CheckChanged(UIButton button)\n    {\n        _CheckboxCell.Checked = button.Selected;\n    }\n\n    internal void UpdateChecked()\n    {\n        _checkbox.Selected = _CheckboxCell.Checked;\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_CheckboxCell.AccentColor.IsNotDefault())\n        {\n            ChangeCheckColor(_CheckboxCell.AccentColor.ToCGColor());\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            ChangeCheckColor(CellParent.CellAccentColor.ToCGColor());\n        }\n    }\n\n    void ChangeCheckColor(CGColor accent)\n    {\n        _checkbox.Layer.BorderColor = accent;\n        _checkbox.FillColor = accent;\n        _checkbox.SetNeedsDisplay(); //update inner rect\n    }\n}\n\n/// <summary>\n/// Check box.\n/// </summary>\npublic class CheckBox : UIButton\n{\n    /// <summary>\n    /// Gets or sets the inset.\n    /// </summary>\n    /// <value>The inset.</value>\n    public UIEdgeInsets Inset { get; set; } = new UIEdgeInsets(20, 20, 20, 20);\n    /// <summary>\n    /// Gets or sets the color of the fill.\n    /// </summary>\n    /// <value>The color of the fill.</value>\n    public CGColor FillColor { get; set; }\n    /// <summary>\n    /// Gets or sets the check changed.\n    /// </summary>\n    /// <value>The check changed.</value>\n    public Action<UIButton> CheckChanged { get; set; }\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.CheckBox\"/> class.\n    /// </summary>\n    /// <param name=\"rect\">Rect.</param>\n    public CheckBox(CGRect rect) : base(rect)\n    {\n        this.AddGestureRecognizer(new UITapGestureRecognizer((obj) =>\n        {\n            Selected = !Selected;\n            CheckChanged?.Invoke(this);\n        }));\n    }\n\n    /// <summary>\n    /// Draw the specified rect.\n    /// </summary>\n    /// <returns>The draw.</returns>\n    /// <param name=\"rect\">Rect.</param>\n    public override void Draw(CGRect rect)\n    {\n        base.Draw(rect);\n\n        var lineWidth = rect.Size.Width / 10;\n\n        // Draw check mark\n        if (Selected)\n        {\n            this.Layer.BackgroundColor = FillColor;\n\n\n            var checkmark = new UIBezierPath();\n            var size = rect.Size;\n            checkmark.MoveTo(new CGPoint(x: 22f / 100f * size.Width, y: 52f / 100f * size.Height));\n            checkmark.AddLineTo(new CGPoint(x: 38f / 100f * size.Width, y: 68f / 100f * size.Height));\n            checkmark.AddLineTo(new CGPoint(x: 76f / 100f * size.Width, y: 30f / 100f * size.Height));\n\n            checkmark.LineWidth = lineWidth;\n            UIColor.White.SetStroke();\n            checkmark.Stroke();\n        }\n\n        else\n        {\n            this.Layer.BackgroundColor = new CGColor(0, 0, 0, 0);\n        }\n    }\n\n    /// <summary>\n    /// Points the inside.\n    /// </summary>\n    /// <returns><c>true</c>, if inside was pointed, <c>false</c> otherwise.</returns>\n    /// <param name=\"point\">Point.</param>\n    /// <param name=\"uievent\">Uievent.</param>\n    public override bool PointInside(CGPoint point, UIEvent uievent)\n    {\n        var rect = this.Bounds;\n        rect.X -= Inset.Left;\n        rect.Y -= Inset.Top;\n        rect.Width += Inset.Left + Inset.Right;\n        rect.Height += Inset.Top + Inset.Bottom;\n\n        return rect.Contains(point);\n    }\n\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/CommandCellView.cs",
    "content": "﻿using System;\nusing System;\nusing UIKit;\nusing System.Windows.Input;\nusing Foundation;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Command cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class CommandCellView : LabelCellView\n{\n    internal Action Execute { get; set; }\n    CommandCell _CommandCell => Cell as CommandCell;\n    ICommand _command;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.CommandCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public CommandCellView(CellBase virtualCell) : base(virtualCell)\n    {\n        SelectionStyle = UITableViewCellSelectionStyle.Default;\n\n        if (!_CommandCell.HideArrowIndicator)\n        {\n            Accessory = UITableViewCellAccessory.DisclosureIndicator;\n            EditingAccessory = UITableViewCellAccessory.DisclosureIndicator;\n            SetRightMarginZero();\n        }\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);        \n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        Execute?.Invoke();\n        if (!_CommandCell.KeepSelectedUntilBack)\n        {\n            tableView.DeselectRow(indexPath, true);\n        }\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n        //UpdateCommand();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_command != null)\n            {\n                _command.CanExecuteChanged -= Command_CanExecuteChanged;\n            }\n            Execute = null;\n            _command = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    internal void UpdateCommand()\n    {\n        if (_command != null)\n        {\n            _command.CanExecuteChanged -= Command_CanExecuteChanged;\n        }\n\n        _command = _CommandCell.Command;\n\n        if (_command != null)\n        {\n            _command.CanExecuteChanged += Command_CanExecuteChanged;\n            Command_CanExecuteChanged(_command, System.EventArgs.Empty);\n        }\n\n        Execute = () =>\n        {\n            if (_command == null)\n            {\n                return;\n            }\n            if (_command.CanExecute(_CommandCell.CommandParameter))\n            {\n                _command.Execute(_CommandCell.CommandParameter);\n            }\n        };\n\n    }\n\n    /// <summary>\n    /// Updates the is enabled.\n    /// </summary>\n    internal override void UpdateIsEnabled()\n    {\n        if (_command != null && !_command.CanExecute(_CommandCell.CommandParameter))\n        {\n            return;\n        }\n        base.UpdateIsEnabled();\n    }\n\n    void Command_CanExecuteChanged(object sender, EventArgs e)\n    {\n        if (!Cell.IsEnabled)\n        {\n            return;\n        }\n\n        SetEnabledAppearance(_command.CanExecute(_CommandCell.CommandParameter));\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/CustomCellContent.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing System.Reflection;\nusing System.Reflection.Metadata;\nusing System.Runtime.InteropServices;\nusing System.Threading;\nusing AiForms.Settings.Extensions;\nusing Microsoft.Maui;\nusing Microsoft.Maui.Controls;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n[Foundation.Preserve(AllMembers = true)]\npublic class CustomCellContent: UIView\n{\n    static MethodInfo ElementDescendantsInfo = typeof(Element).GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name == \"Descendants\" && !x.IsGenericMethod);\n    bool _disposed;\n    NSLayoutConstraint _heightConstraint;\n    View _virtualCell;\n    public CustomCell CustomCell { get; set; }\n    double _lastFrameWidth = -9999d;\n    double _lastMeasureWidth = -9999d;\n    double _lastMeasureHeight = -9999d;\n    IMauiContext _mauiContext => _virtualCell.FindMauiContext();\n    UITableView _tableView;\n\n    public CustomCellContent()\n    {\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (_disposed)\n        {\n            return;\n        }\n\n        if (disposing)\n        {\n            _cts?.Cancel();\n            _cts?.Dispose();\n            _cts = null;\n            \n            if (_virtualCell != null)\n            {\n                _virtualCell.PropertyChanged -= CellPropertyChanged;\n                _virtualCell.MeasureInvalidated -= OnMeasureInvalidated;\n                foreach (var child in CustomCellContent.ElementDescendants(_virtualCell))\n                {\n                    if (child is Layout layout)\n                    {\n                        layout.SizeChanged -= OnInnerLayoutSizeChanged;\n                    }\n                    child.MeasureInvalidated -= OnMeasureInvalidated;\n                }\n            }\n\n            CustomCell = null;\n\n            _heightConstraint?.Dispose();\n            _heightConstraint = null;\n\n\n            if(_virtualCell.Handler is IPlatformViewHandler handler)\n            {\n                handler.VirtualView.DisposeModalAndChildHandlers();\n                handler?.DisconnectHandler();\n            }\n            \n            _virtualCell = null;\n            _tableView = null;\n        }\n\n        _disposed = true;\n\n        base.Dispose(disposing);\n    }\n\n    \n\n    public virtual void UpdateNativeCell()\n    {\n        UpdateIsEnabled();\n    }\n\n    public virtual void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        if (e.PropertyName == CellBase.IsEnabledProperty.PropertyName)\n        {\n            UpdateIsEnabled();\n        }\n    }\n\n    protected virtual void UpdateIsEnabled()\n    {\n        UserInteractionEnabled = _virtualCell.IsEnabled;\n    }\n\n    public virtual void UpdateCell(View newCell, UITableView tableView)\n    {\n        // Workaround GestureRecognizer bug\n        // TODO: if fix this issue, remove the following code.\n        // https://github.com/dotnet/maui/issues/17948\n        // newCell.Parent = Application.Current.MainPage;\n\n        _tableView = tableView;       \n\n        var oldCell = _virtualCell;\n        // If oldCell and newCell are the same\n        if (oldCell == newCell)\n        {            \n            if (!CustomCell.IsForceLayout && Subviews.Any())\n            {\n                // do nothing.\n                return;\n            }\n            CustomCell.IsForceLayout = false;\n        }\n\n\n        if (oldCell != null)\n        {\n            _cts?.Cancel();\n            oldCell.PropertyChanged -= CellPropertyChanged;\n            oldCell.MeasureInvalidated -= OnMeasureInvalidated;\n            // Delete previous child element\n            foreach (var subView in Subviews)\n            {\n                subView.RemoveFromSuperview();\n            }\n\n            foreach (var child in CustomCellContent.ElementDescendants(oldCell))\n            {\n                if (child is Layout layout)\n                {\n                    layout.SizeChanged -= OnInnerLayoutSizeChanged;\n                }\n                child.MeasureInvalidated -= OnMeasureInvalidated;\n            }\n        }\n\n        IPlatformViewHandler handler;\n        if (newCell.Handler != null)\n        {\n            // TODO:\n            // Currently, the performance is not good because the number of\n            // NativieView is kept as many as the number of Cells. To improve this,\n            // it is necessary to virtualize the Content part of CustomCell as well.\n            // This can probably be achieved by replacing the Handler and\n            // resetting the VirtualView.\n\n            // If it has already been generated, use it as is.\n            handler = newCell.Handler as IPlatformViewHandler;\n            // If the incoming Cell belongs to another parent, peel it off.\n            handler.PlatformView?.RemoveFromSuperview();            \n        }\n        else\n        {\n            // Workaround GestureRecognizer bug\n            // TODO: if fix this issue, remove the following code.\n            // https://github.com/dotnet/maui/issues/17948\n            // https://github.com/dotnet/maui/issues/1718\n            // newCell.Parent = Application.Current.MainPage;\n\n            // If Handler is not generated, generate it.            \n            handler = newCell.ToHandler(newCell.FindMauiContext());\n        }\n\n        _virtualCell = newCell;\n        _virtualCell.PropertyChanged += CellPropertyChanged;\n        \n        var viewHandlerType = _mauiContext.Handlers.GetHandlerType(_virtualCell.GetType());\n        var reflectableType = handler as System.Reflection.IReflectableType;\n        var handlerType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : (handler != null ? handler.GetType() : typeof(System.Object));\n\n        if (handlerType == viewHandlerType)\n        {\n            handler.SetVirtualView(this._virtualCell);\n        }\n        else\n        {\n            //when cells are getting reused the element could be already set to another cell\n            //so we should dispose based on the renderer and not the renderer.Element\n            handler.DisposeHandlersAndChildren();\n            handler = _virtualCell.ToHandler(_virtualCell.FindMauiContext());\n        }\n\n\n        if (!CustomCell.IsMeasureOnce || tableView.Frame.Width != _lastFrameWidth)\n        {\n            _lastFrameWidth = tableView.Frame.Width;\n            var height = double.PositiveInfinity;\n\n            var accessoryWidth = CustomCell.ShowArrowIndicator ? 27 : 0;\n            var width = tableView.Frame.Width - (CustomCell.UseFullSize ? accessoryWidth : 32); // CellBaseView layout margin\n            var result = _virtualCell.Measure(tableView.Frame.Width, height);\n            _lastMeasureWidth = result.Width;\n            if (_virtualCell.HorizontalOptions.Alignment == LayoutAlignment.Fill)\n            {\n                _lastMeasureWidth = width;\n            }\n            _lastMeasureHeight = result.Height;\n        }\n\n        // Add PlatformView as a child\n        ArrangeSubView(handler);\n\n        UpdateNativeCell();\n\n        //SetNeedsLayout();\n\n        _virtualCell.MeasureInvalidated += OnMeasureInvalidated;\n        foreach (var child in CustomCellContent.ElementDescendants(_virtualCell))\n        {\n            if(child is Layout layout)\n            {\n                // Also detects changes in the size of descendant layout(BindableLayout)\n                layout.SizeChanged += OnInnerLayoutSizeChanged;\n            }\n            // Also detects changes in the size of descendant elements\n            child.MeasureInvalidated += OnMeasureInvalidated;\n        }\n    }\n\n    private void OnInnerLayoutSizeChanged(object sender, EventArgs e)\n    {\n        LayoutDispacher();\n    }    \n\n    private void OnMeasureInvalidated(object sender, EventArgs e)\n    {       \n        LayoutDispacher();\n    }\n\n    async Task ForceLayout(CancellationToken token)\n    {\n        if(_tableView == null || _tableView.IsDisposed())\n        {\n            return;\n        }\n        var tableView = _tableView;\n        if (_virtualCell?.Handler is not IPlatformViewHandler handler)\n        {\n            return;\n        }\n\n        // Wait a little and execute layout processing only on the last event\n        await Task.Delay(100, token);\n        if (token.IsCancellationRequested)\n        {\n            return;\n        }\n\n        _lastFrameWidth = tableView.Frame.Width;\n        var height = double.PositiveInfinity;\n\n        var accessoryWidth = CustomCell.ShowArrowIndicator ? 27 : 0;\n        var width = tableView.Frame.Width - (CustomCell.UseFullSize ? accessoryWidth : 32); // CellBaseView layout margin\n        var result = _virtualCell.Measure(tableView.Frame.Width, height);\n        _lastMeasureWidth = result.Width;\n        if (_virtualCell.HorizontalOptions.Alignment == LayoutAlignment.Fill)\n        {\n            _lastMeasureWidth = width;\n        }\n        _lastMeasureHeight = result.Height;\n\n        if (_heightConstraint != null)\n        {\n            _heightConstraint.Active = false;\n            _heightConstraint.Priority = 1f;\n            _heightConstraint?.Dispose();\n        }\n\n        var native = handler.PlatformView;\n        if (native is null)\n        {\n            return;\n        }\n\n        _heightConstraint = native.HeightAnchor.ConstraintEqualTo((NFloat)_lastMeasureHeight);\n        _heightConstraint.Priority = 999f;\n        _heightConstraint.Active = true;\n\n        _virtualCell.Arrange(new Rect(0, 0, _lastMeasureWidth, _lastMeasureHeight));\n\n        native.SetNeedsUpdateConstraints();\n        SetNeedsLayout();\n\n        tableView.BeginUpdates();\n        tableView.EndUpdates();\n    }\n\n    void ArrangeSubView(IPlatformViewHandler handler)\n    {\n        var native = handler.PlatformView;\n        AddSubview(native);\n        \n        native.TranslatesAutoresizingMaskIntoConstraints = false;\n\n        if (_heightConstraint != null)\n        {\n            _heightConstraint.Active = false;\n            _heightConstraint.Priority = 1f;            \n            _heightConstraint?.Dispose();\n            //native.SetNeedsUpdateConstraints();\n            //native.UpdateConstraintsIfNeeded();\n        }\n\n        _heightConstraint = native.HeightAnchor.ConstraintEqualTo((NFloat)_lastMeasureHeight);\n        _heightConstraint.Priority = 999f;\n        _heightConstraint.Active = true;        \n\n        native.TopAnchor.ConstraintEqualTo(TopAnchor).Active = true;\n        native.LeftAnchor.ConstraintEqualTo(LeftAnchor).Active = true;\n        native.BottomAnchor.ConstraintEqualTo(BottomAnchor).Active = true;\n        native.RightAnchor.ConstraintEqualTo(RightAnchor).Active = true;\n\n        //native.SetNeedsUpdateConstraints();\n        //native.UpdateConstraintsIfNeeded();\n    }\n\n    CancellationTokenSource _cts = new CancellationTokenSource();\n    void LayoutDispacher()\n    {\n        _cts?.Cancel();\n        _cts = new CancellationTokenSource();\n        _ = ForceLayout(_cts.Token);\n    }\n\n    internal static IEnumerable<VisualElement> ElementDescendants(Element element)\n    {\n        return (ElementDescendantsInfo.Invoke(element, new object[] { }) as IEnumerable<Element>).OfType<VisualElement>();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/CustomCellView.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\nusing Foundation;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\n[Foundation.Preserve(AllMembers = true)]\r\npublic class CustomCellView: CellBaseView\n{\n    protected CustomCell CustomCell => Cell as CustomCell;\n    protected Action Execute { get; set; }\n    protected ICommand _command;\n    protected CustomCellContent _coreView;\n    Dictionary<UIView, UIColor> _colorCache = new Dictionary<UIView, UIColor>();\n\n    public CustomCellView(CellBase virtualCell) : base(virtualCell)\n    {\n        SelectionStyle = CustomCell.IsSelectable ? UITableViewCellSelectionStyle.Default : UITableViewCellSelectionStyle.None;\n    }\n\n    public override void UpdateConstraints()\n    {\n        base.UpdateConstraints();\n        // It works fine even if disable this code.\n        //LayoutIfNeeded(); // let the layout immediately reflect when update constraints.\n    }\n\n    protected override void SetUpContentView()\n    {\n        base.SetUpContentView();\n\n        if (CustomCell.ShowArrowIndicator)\n        {\n            Accessory = UITableViewCellAccessory.DisclosureIndicator;\n            EditingAccessory = UITableViewCellAccessory.DisclosureIndicator;\n\n            SetRightMarginZero();\n        }\n\n        StackV.RemoveArrangedSubview(ContentStack);\n        StackV.RemoveArrangedSubview(DescriptionLabel);\n        ContentStack.RemoveFromSuperview();\n        DescriptionLabel.RemoveFromSuperview();\n\n        _coreView = new CustomCellContent();\n\n        if (CustomCell.UseFullSize)\n        {\n            StackH.RemoveArrangedSubview(IconView);\n            IconView.RemoveFromSuperview();\n\n            StackH.LayoutMargins = new UIEdgeInsets(0, 0, 0, 0);\n            StackH.Spacing = 0;\n        }\n\n        StackV.AddArrangedSubview(_coreView);\n    }\n\n    internal virtual void UpdateContent(UITableView tableView)\n    {\n        if (_coreView is null)\n        {\n            return; // for HotReload;\n        }\n        if(tableView is null)\n        {\n            return;\n        }\n\n        _coreView.CustomCell = CustomCell;\n        _coreView.UpdateCell(CustomCell.Content, tableView);        \n    }\n\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        if (!CustomCell.IsSelectable)\n        {\n            return;\n        }\n        Execute?.Invoke();\n        if (!CustomCell.KeepSelectedUntilBack)\n        {\n            tableView.DeselectRow(indexPath, true);\n        }\n    }\n\n    public override bool RowLongPressed(UITableView tableView, NSIndexPath indexPath)\n    {\n        if (CustomCell.LongCommand == null)\n        {\n            return false;\n        }\n\n        CustomCell.SendLongCommand();\n\n        return true;\n    }\n\n    public override void SetHighlighted(bool highlighted, bool animated)\n    {\n        if (!highlighted)\n        {\n            base.SetHighlighted(highlighted, animated);\n            return;\n        }\n\n        // https://stackoverflow.com/questions/6745919/uitableviewcell-subview-disappears-when-cell-is-selected\n\n        BackupSubviewsColor(_coreView.Subviews[0], _colorCache);\n\n        base.SetHighlighted(highlighted, animated);\n\n        RestoreSubviewsColor(_coreView.Subviews[0], _colorCache);\n    }\n\n    public override void SetSelected(bool selected, bool animated)\n    {\n        if (!selected)\n        {\n            base.SetSelected(selected, animated);\n            return;\n        }\n\n        base.SetSelected(selected, animated);\n\n        RestoreSubviewsColor(_coreView.Subviews[0], _colorCache);\n    }\n\n    void BackupSubviewsColor(UIView view, Dictionary<UIView, UIColor> colors)\n    {\n        colors[view] = view.BackgroundColor;\n\n        foreach (UIView subView in view.Subviews)\n        {\n            BackupSubviewsColor(subView, colors);\n        }\n    }\n\n    void RestoreSubviewsColor(UIView view, Dictionary<UIView, UIColor> colors)\n    {\n        if (colors.TryGetValue(view, out var color))\n        {\n            view.BackgroundColor = color;\n        }\n\n        foreach (UIView subView in view.Subviews)\n        {\n            RestoreSubviewsColor(subView, colors);\n        }\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n        UpdateContent(tableView);\n        //UpdateCommand();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_command != null)\n            {\n                _command.CanExecuteChanged -= Command_CanExecuteChanged;\n            }\n            Execute = null;\n            _command = null;\n\n            _colorCache.Clear();\n            _colorCache = null;\n\n            _coreView?.RemoveFromSuperview();\n            _coreView?.Dispose();\n            _coreView = null;\n        }\n\n        base.Dispose(disposing);\n    }\n\n    internal virtual void UpdateCommand()\n    {\n        if (_command != null)\n        {\n            _command.CanExecuteChanged -= Command_CanExecuteChanged;\n        }\n\n        _command = CustomCell.Command;\n\n        if (_command != null)\n        {\n            _command.CanExecuteChanged += Command_CanExecuteChanged;\n            Command_CanExecuteChanged(_command, System.EventArgs.Empty);\n        }\n\n        Execute = () => {\n            if (_command == null)\n            {\n                return;\n            }\n            if (_command.CanExecute(CustomCell.CommandParameter))\n            {\n                _command.Execute(CustomCell.CommandParameter);\n            }\n        };\n\n    }\n\n    /// <summary>\n    /// Updates the is enabled.\n    /// </summary>\n    internal override void UpdateIsEnabled()\n    {\n        if (_command != null && !_command.CanExecute(CustomCell.CommandParameter))\n        {\n            return;\n        }\n        base.UpdateIsEnabled();\n    }\n\n    protected virtual void Command_CanExecuteChanged(object sender, EventArgs e)\n    {\n        if (!Cell.IsEnabled)\n        {\n            return;\n        }\n\n        SetEnabledAppearance(_command.CanExecute(CustomCell.CommandParameter));\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/DatePickerCellView.cs",
    "content": "﻿using System;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Date picker cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class DatePickerCellView : LabelCellView\n{\n    DatePickerCell _DatePickerCell => Cell as DatePickerCell;\n    /// <summary>\n    /// Gets or sets the dummy field.\n    /// </summary>\n    /// <value>The dummy field.</value>\n    public UITextField DummyField { get; set; }\n    NSDate _preSelectedDate;\n    UIDatePicker _picker;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.DatePickerCellView\"/> class.\n    /// </summary>\n    /// <param name=\"formsCell\">Forms cell.</param>\n    public DatePickerCellView(CellBase formsCell) : base(formsCell)\n    {\n        DummyField = new NoCaretField();\n        DummyField.BorderStyle = UITextBorderStyle.None;\n        DummyField.BackgroundColor = UIColor.Clear;\n        ContentView.AddSubview(DummyField);\n        ContentView.SendSubviewToBack(DummyField);\n\n        SelectionStyle = UITableViewCellSelectionStyle.Default;\n\n        SetUpDatePicker();\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n        //UpdateMaximumDate();\n        //UpdateMinimumDate();\n        //UpdateDate();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        tableView.DeselectRow(indexPath, true);\n        DummyField.BecomeFirstResponder();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            DummyField.RemoveFromSuperview();\n            DummyField?.Dispose();\n            DummyField = null;\n            _picker.Dispose();\n            _picker = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Layouts the subviews.\n    /// </summary>\n    public override void LayoutSubviews()\n    {\n        base.LayoutSubviews();\n\n        DummyField.Frame = new CGRect(0, 0, Frame.Width, Frame.Height);\n    }\n\n    void SetUpDatePicker()\n    {\n        _picker = new UIDatePicker { Mode = UIDatePickerMode.Date, TimeZone = new Foundation.NSTimeZone(\"UTC\") };\n        if (UIDevice.CurrentDevice.CheckSystemVersion(13, 4))\n        {\n            _picker.PreferredDatePickerStyle = UIDatePickerStyle.Wheels;\n        }\n\n        var width = UIScreen.MainScreen.Bounds.Width;\n        var toolbar = new UIToolbar(new CGRect(0, 0, width, 44)) { BarStyle = UIBarStyle.Default, Translucent = true };\n\n        var cancelButton = new UIBarButtonItem(UIBarButtonSystemItem.Cancel, (o, e) =>\n        {\n            DummyField.ResignFirstResponder();\n            _picker.Date = _preSelectedDate;\n        });\n\n        var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);\n        var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) =>\n        {\n            DummyField.ResignFirstResponder();\n            Done();\n        });\n\n        if (!string.IsNullOrEmpty(_DatePickerCell.TodayText))\n        {\n            var labelButton = new UIBarButtonItem(_DatePickerCell.TodayText, UIBarButtonItemStyle.Plain, (sender, e) =>\n            {\n                SetToday();\n            });\n            var fixspacer = new UIBarButtonItem(UIBarButtonSystemItem.FixedSpace) { Width = 20 };\n            toolbar.SetItems(new[] { cancelButton, spacer, labelButton, fixspacer, doneButton }, false);\n        }\n        else\n        {\n            toolbar.SetItems(new[] { cancelButton, spacer, doneButton }, false);\n        }\n\n        DummyField.InputView = _picker;\n        DummyField.InputAccessoryView = toolbar;\n    }\n\n    void SetToday()\n    {\n        if (_picker.MinimumDate.ToDateTime() <= DateTime.Today && _picker.MaximumDate.ToDateTime() >= DateTime.Today)\n        {\n            _picker.SetDate(DateTime.Today.ToNSDate(), true);\n        }\n    }\n\n    void Done()\n    {\n        _DatePickerCell.Date = _picker.Date.ToDateTime().Date;\n        ValueLabel.Text = _DatePickerCell.Date?.ToString(_DatePickerCell.Format);\n        _preSelectedDate = _picker.Date;\n    }\n\n    internal void UpdateDate()\n    {\n        if (_DatePickerCell.Date.HasValue)\n        {\n            _picker.SetDate(_DatePickerCell.Date.Value.ToNSDate(), false);\n            ValueLabel.Text = _DatePickerCell.Date.Value.ToString(_DatePickerCell.Format);\n            _preSelectedDate = _DatePickerCell.Date.Value.ToNSDate();\n        }\n        else\n        {\n            _picker.SetDate(_DatePickerCell.InitialDate.ToNSDate(), false);\n            ValueLabel.Text = string.Empty;\n            _preSelectedDate = _DatePickerCell.InitialDate.ToNSDate();\n        }\n    }\n\n    internal void UpdateMaximumDate()\n    {\n        _picker.MaximumDate = _DatePickerCell.MaximumDate.ToNSDate();\n        UpdateDate();   //without this code, selected date isn't sometimes correct when it is shown first.\n    }\n\n    internal void UpdateMinimumDate()\n    {\n        _picker.MinimumDate = _DatePickerCell.MinimumDate.ToNSDate();\n        UpdateDate();\n    }\n\n    internal void UpdateTodayText()\n    {\n        SetUpDatePicker();\n        UpdateDate();\n        UpdateMaximumDate();\n        UpdateMinimumDate();\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/EntryCellView.cs",
    "content": "﻿using System;\nusing System.Drawing;\nusing AiForms.Settings.Extensions;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Controls.Platform;\nusing Microsoft.Maui.Platform;\nusing UIKit;\nusing AiEntryCell = AiForms.Settings.EntryCell;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Entry cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class EntryCellView : CellBaseView\n{\n    AiEntryCell _EntryCell => Cell as AiEntryCell;\n    internal UITextField ValueField;\n    UIView _FieldWrapper;\n    bool _hasFocus = false;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.EntryCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public EntryCellView(CellBase virtualCell) : base(virtualCell)\n    {\n        ValueField = new UITextField() { BorderStyle = UITextBorderStyle.None };\n        ValueField.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;\n        ValueField.ReturnKeyType = UIReturnKeyType.Done;\n        ValueField.EditingChanged += _textField_EditingChanged;\n        ValueField.EditingDidBegin += ValueField_EditingDidBegin;\n        ValueField.EditingDidEnd += ValueField_EditingDidEnd;\n        ValueField.ShouldReturn = OnShouldReturn;\n\n        _EntryCell.Focused += EntryCell_Focused;\n\n\n        _FieldWrapper = new UIView();\n        _FieldWrapper.AutosizesSubviews = true;\n        _FieldWrapper.SetContentHuggingPriority(100f, UILayoutConstraintAxis.Horizontal);\n        _FieldWrapper.SetContentCompressionResistancePriority(100f, UILayoutConstraintAxis.Horizontal);\n\n        _FieldWrapper.AddSubview(ValueField);\n        ContentStack.AddArrangedSubview(_FieldWrapper);\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n\n        if (ValueField is null)\n            return; // For HotReload\n\n        //UpdateValueText();\n        //UpdateValueTextColor();\n        //UpdateValueTextFont();\n        //UpdatePlaceholder();\n        //UpdateKeyboard();\n        //UpdateIsPassword();\n        //UpdateTextAlignment();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellValueTextColorProperty.PropertyName)\n        {\n            UpdateValueTextColor();\n            ValueField.SetNeedsLayout();    // immediately reflect\n        }\n        else if (e.PropertyName == SettingsView.CellValueTextFontSizeProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellValueTextFontFamilyProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellValueTextFontAttributesProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateValueTextFont);\n        }\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        ValueField.BecomeFirstResponder();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            ValueField.EditingChanged -= _textField_EditingChanged;\n            ValueField.EditingDidBegin -= ValueField_EditingDidBegin;\n            ValueField.EditingDidEnd -= ValueField_EditingDidEnd;\n            _EntryCell.Focused -= EntryCell_Focused;\n            ValueField.ShouldReturn = null;\n            ValueField.RemoveFromSuperview();\n            ValueField.Dispose();\n            ValueField = null;\n\n            if (!_FieldWrapper.IsDisposed())\n            {\n                ContentStack.RemoveArrangedSubview(_FieldWrapper);\n                _FieldWrapper.Dispose();\n            }\n            _FieldWrapper = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal override void SetEnabledAppearance(bool isEnabled)\n    {\n        if (isEnabled)\n        {\n            ValueField.Alpha = 1.0f;\n        }\n        else\n        {\n            ValueField.Alpha = 0.3f;\n        }\n        base.SetEnabledAppearance(isEnabled);\n    }\n\n    internal void UpdateValueText()\n    {\n        //Without this judging, TextField don't correctly work when inputting Japanese (maybe other 2byte languages either).\n        if (ValueField.Text != _EntryCell.ValueText)\n        {\n            ValueField.Text = _EntryCell.ValueText;\n        }\n    }\n\n    internal void UpdateValueTextFont()\n    {\n        var family = _EntryCell.ValueTextFontFamily ?? CellParent.CellValueTextFontFamily;\n        var attr = _EntryCell.ValueTextFontAttributes ?? CellParent.CellValueTextFontAttributes;\n\n        if (_EntryCell.ValueTextFontSize > 0)\n        {\n            ValueField.Font = family.ToFont(_EntryCell.ValueTextFontSize, attr).ToUIFont(_fontManager.Value);\n        }\n        else if (CellParent != null)\n        {\n            ValueField.Font = family.ToFont(CellParent.CellValueTextFontSize, attr).ToUIFont(_fontManager.Value);\n        }\n        //make the view height fit font size\n        var contentH = ValueField.IntrinsicContentSize.Height;\n        var bounds = ValueField.Bounds;\n        ValueField.Bounds = new CoreGraphics.CGRect(0, 0, bounds.Width, contentH);\n        _FieldWrapper.Bounds = new CoreGraphics.CGRect(0, 0, _FieldWrapper.Bounds.Width, contentH);\n    }\n\n    internal void UpdateValueTextColor()\n    {\n        if (_EntryCell.ValueTextColor.IsNotDefault())\n        {\n            ValueField.TextColor = _EntryCell.ValueTextColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellValueTextColor.IsNotDefault())\n        {\n            ValueField.TextColor = CellParent.CellValueTextColor.ToPlatform();\n        }\n        ValueField.SetNeedsLayout();\n    }\n\n    internal void UpdateKeyboard()\n    {\n        ValueField.ApplyKeyboard(_EntryCell.Keyboard);\n    }\n\n    internal void UpdatePlaceholder()\n    {\n        if (_EntryCell.PlaceholderColor.IsNotDefault())\n        {\n            ValueField.Placeholder = null;\n            ValueField.AttributedPlaceholder = new NSAttributedString(_EntryCell.Placeholder, ValueField.Font, _EntryCell.PlaceholderColor.ToPlatform());\n        }\n        else\n        {\n            ValueField.AttributedPlaceholder = null;\n            ValueField.Placeholder = _EntryCell.Placeholder;\n        }\n    }\n\n    internal void UpdateTextAlignment()\n    {\n        ValueField.TextAlignment = _EntryCell.TextAlignment.ToUITextAlignment();\n        ValueField.SetNeedsLayout();\n    }\n\n    internal void UpdateIsPassword()\n    {\n        ValueField.SecureTextEntry = _EntryCell.IsPassword;\n    }\n\n    internal void UpdateShowDoneButton()\n    {\n        if (_EntryCell.ShowDoneButtonOnIOS)\n        {\n            var toolbar = new UIToolbar(new CGRect(0.0f, 0.0f, 50.0f, 44.0f));\n            toolbar.BackgroundColor = UIColor.LightGray;\n            var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, delegate\n            {\n                ValueField.ResignFirstResponder();\n            });\n\n            toolbar.Items = new UIBarButtonItem[] {\n                new UIBarButtonItem (UIBarButtonSystemItem.FlexibleSpace),\n                doneButton\n            };\n\n            ValueField.InputAccessoryView = toolbar;\n        }\n        else\n        {\n            ValueField.InputAccessoryView = null;\n        }\n    }\n\n    void _textField_EditingChanged(object sender, EventArgs e)\n    {\n        _EntryCell.ValueText = ValueField.Text;\n    }\n\n\n    void ValueField_EditingDidBegin(object sender, EventArgs e)\n    {\n        _hasFocus = true;\n    }\n\n\n    void ValueField_EditingDidEnd(object sender, EventArgs e)\n    {\n        if (!_hasFocus)\n        {\n            return;\n        }\n        ValueField.ResignFirstResponder();\n        _EntryCell.SendCompleted();\n        _hasFocus = false;\n    }\n\n    void EntryCell_Focused(object sender, EventArgs e)\n    {\n        ValueField.BecomeFirstResponder();\n    }\n\n\n    bool OnShouldReturn(UITextField view)\n    {\n        _hasFocus = false;\n        ValueField.ResignFirstResponder();\n        _EntryCell.SendCompleted();\n        return true;\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/LabelCellView.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing AiForms.Settings.Extensions;\nusing Microsoft.Maui.Controls.Platform;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\npublic class LabelCellView: CellBaseView\n{\n    /// <summary>\n    /// Gets or sets the value label.\n    /// </summary>\n    /// <value>The value label.</value>\n    public UILabel ValueLabel { get; set; }\n    LabelCell _LabelCell => Cell as LabelCell;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.LabelCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public LabelCellView(CellBase virtualCell) : base(virtualCell)\n    {\n        ValueLabel = new UILabel();\n        ValueLabel.TextAlignment = UITextAlignment.Right;\n\n        ContentStack.AddArrangedSubview(ValueLabel);\n        ValueLabel.SetContentHuggingPriority(100f, UILayoutConstraintAxis.Horizontal);\n        ValueLabel.SetContentCompressionResistancePriority(100f, UILayoutConstraintAxis.Horizontal);\n    }    \n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n\n        if (e.PropertyName == SettingsView.CellValueTextColorProperty.PropertyName)\n        {\n            UpdateValueTextColor();\n        }\n        else if (e.PropertyName == SettingsView.CellValueTextFontSizeProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellValueTextFontFamilyProperty.PropertyName ||\n                 e.PropertyName == SettingsView.CellValueTextFontAttributesProperty.PropertyName)\n        {\n            UpdateWithForceLayout(UpdateValueTextFont);\n        }\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        //UpdateValueText();\n        //UpdateValueTextColor();\n        //UpdateValueTextFont();\n        base.UpdateCell(tableView);\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal override void SetEnabledAppearance(bool isEnabled)\n    {\n        if (isEnabled)\n        {\n            ValueLabel.Alpha = 1f;\n        }\n        else\n        {\n            ValueLabel.Alpha = 0.3f;\n        }\n        base.SetEnabledAppearance(isEnabled);\n    }\n\n    /// <summary>\n    /// Updates the value text.\n    /// </summary>\n    internal void UpdateValueText()\n    {\n        ValueLabel.Text = _LabelCell.ValueText;\n    }\n\n    internal void UpdateValueTextFont()\n    {\n        if (ValueLabel.Font is null)\n            return; // for HotReload\n\n        var family = _LabelCell.ValueTextFontFamily ?? CellParent.CellValueTextFontFamily;\n        var attr = _LabelCell.ValueTextFontAttributes ?? CellParent.CellValueTextFontAttributes;\n\n        if (_LabelCell.ValueTextFontSize > 0)\n        {\n            ValueLabel.Font = family.ToFont(_LabelCell.ValueTextFontSize, attr).ToUIFont(_fontManager.Value); \n        }\n        else if (CellParent != null)\n        {\n            ValueLabel.Font = family.ToFont(CellParent.CellValueTextFontSize, attr).ToUIFont(_fontManager.Value);\n        }\n    }\n\n    internal void UpdateValueTextColor()\n    {\n        if (_LabelCell.ValueTextColor.IsNotDefault())\n        {\n            ValueLabel.TextColor = _LabelCell.ValueTextColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellValueTextColor.IsNotDefault())\n        {\n            ValueLabel.TextColor = CellParent.CellValueTextColor.ToPlatform();\n        }\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (!ValueLabel.IsDisposed())\n            {\n                ContentStack.RemoveArrangedSubview(ValueLabel);\n                ValueLabel.Dispose();\n            }\n            ValueLabel = null;\n        }\n        base.Dispose(disposing);\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/NumberPickerCellView.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Number picker cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class NumberPickerCellView : LabelCellView\n{\n    /// <summary>\n    /// Gets or sets the dummy field.\n    /// </summary>\n    /// <value>The dummy field.</value>\n    public UITextField DummyField { get; set; }\n    NumberPickerSource _model;\n    UILabel _titleLabel;\n    UIPickerView _picker;\n    ICommand _command;\n\n    NumberPickerCell _NumberPickerCell => Cell as NumberPickerCell;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.NumberPickerCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public NumberPickerCellView(CellBase virtualCell) : base(virtualCell)\n    {\n\n        DummyField = new NoCaretField();\n        DummyField.BorderStyle = UITextBorderStyle.None;\n        DummyField.BackgroundColor = UIColor.Clear;\n        ContentView.AddSubview(DummyField);\n        ContentView.SendSubviewToBack(DummyField);\n\n        SelectionStyle = UITableViewCellSelectionStyle.Default;\n\n        SetUpPicker();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        tableView.DeselectRow(indexPath, true);\n        DummyField.BecomeFirstResponder();\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n        if (DummyField is null)\n            return; // For HotReload\n\n        //UpdateNumberList();\n        //UpdateNumber();\n        //UpdateTitle();\n        //UpdateCommand();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _model.UpdatePickerFromModel -= Model_UpdatePickerFromModel;\n            DummyField.RemoveFromSuperview();\n            DummyField?.Dispose();\n            DummyField = null;\n            _titleLabel?.Dispose();\n            _titleLabel = null;\n            _model?.Dispose();\n            _model = null;\n            _picker?.Dispose();\n            _picker = null;\n            _command = null;\n\n        }\n        base.Dispose(disposing);\n    }\n\n    void SetUpPicker()\n    {\n        _picker = new UIPickerView();\n\n        var width = UIScreen.MainScreen.Bounds.Width;\n\n        _titleLabel = new UILabel();\n        _titleLabel.TextAlignment = UITextAlignment.Center;\n\n        var toolbar = new UIToolbar(new CGRect(0, 0, (float)width, 44)) { BarStyle = UIBarStyle.Default, Translucent = true };\n        var cancelButton = new UIBarButtonItem(UIBarButtonSystemItem.Cancel, (o, e) =>\n        {\n            DummyField.ResignFirstResponder();\n            Select(_model.PreSelectedItem);\n        });\n\n        var labelButton = new UIBarButtonItem(_titleLabel);\n        var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);\n        var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) =>\n        {\n            _model.OnUpdatePickerFormModel();\n            DummyField.ResignFirstResponder();\n            _command?.Execute(_model.SelectedItem);\n        });\n\n        toolbar.SetItems(new[] { cancelButton, spacer, labelButton, spacer, doneButton }, false);\n\n        DummyField.InputView = _picker;\n        DummyField.InputAccessoryView = toolbar;\n\n        _model = new NumberPickerSource(_NumberPickerCell.Unit);\n        _picker.Model = _model;\n\n        _model.UpdatePickerFromModel += Model_UpdatePickerFromModel;\n    }\n\n    internal virtual void UpdateNumber()\n    {\n        Select(_NumberPickerCell.Number);\n        ValueLabel.Text = FormatNumber(_NumberPickerCell.Number);\n    }\n\n    private string FormatNumber(int? number)\n    {\n        return number.HasValue && !String.IsNullOrEmpty(_NumberPickerCell.Unit)\n            ? $\"{number} {_NumberPickerCell.Unit}\"\n            : number?.ToString() ?? \"\";\n    }\n\n    internal void UpdateNumberList()\n    {\n        _model.SetNumbers(_NumberPickerCell.Min, _NumberPickerCell.Max);\n        Select(_NumberPickerCell.Number);\n    }\n\n    internal void UpdateTitle()\n    {\n        _titleLabel.Text = _NumberPickerCell.PickerTitle;\n        _titleLabel.SizeToFit();\n        _titleLabel.Frame = new CGRect(0, 0, 160, 44);\n    }\n\n    internal void UpdateCommand()\n    {\n        _command = _NumberPickerCell.SelectedCommand;\n    }\n\n    void Model_UpdatePickerFromModel(object sender, EventArgs e)\n    {\n        _NumberPickerCell.Number = _model.SelectedItem;\n        ValueLabel.Text = FormatNumber(_model.SelectedItem);\n    }\n\n    /// <summary>\n    /// Layouts the subviews.\n    /// </summary>\n    public override void LayoutSubviews()\n    {\n        base.LayoutSubviews();\n        if (DummyField is null)\n            return; // For HotReload\n\n        DummyField.Frame = new CGRect(0, 0, Frame.Width, Frame.Height);\n    }\n\n    void Select(int? number)\n    {\n        var idx = number.HasValue ? _model.Items.IndexOf(number.Value) : -1;\n        if (idx == -1)\n        {\n            number = _model.Items[0];\n            idx = 0;\n        }\n        _picker.Select(idx, 0, false);\n        _model.SelectedItem = number.Value;\n        _model.SelectedIndex = idx;\n        _model.PreSelectedItem = number.Value;\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/NumberPickerSource.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n[Foundation.Preserve(AllMembers = true)]\ninternal class NumberPickerSource : UIPickerViewModel\n{\n    private readonly string _unit;\n\n    public NumberPickerSource(string unit)\n    {\n        _unit = unit;\n    }\n\n    internal IList<int> Items { get; private set; }\n\n    internal event EventHandler UpdatePickerFromModel;\n\n    internal int SelectedIndex { get; set; }\n\n    internal int SelectedItem { get; set; }\n\n    internal int PreSelectedItem { get; set; }\n\n    /// <summary>\n    /// Gets the component count.\n    /// </summary>\n    /// <returns>The component count.</returns>\n    /// <param name=\"picker\">Picker.</param>\n    public override nint GetComponentCount(UIPickerView picker)\n    {\n        return 1;\n    }\n\n    /// <summary>\n    /// Gets the rows in component.\n    /// </summary>\n    /// <returns>The rows in component.</returns>\n    /// <param name=\"pickerView\">Picker view.</param>\n    /// <param name=\"component\">Component.</param>\n    public override nint GetRowsInComponent(UIPickerView pickerView, nint component)\n    {\n        return Items != null ? Items.Count : 0;\n    }\n\n    /// <summary>\n    /// Gets the title.\n    /// </summary>\n    /// <returns>The title.</returns>\n    /// <param name=\"picker\">Picker.</param>\n    /// <param name=\"row\">Row.</param>\n    /// <param name=\"component\">Component.</param>\n    public override string GetTitle(UIPickerView picker, nint row, nint component)\n    {\n        int number = SelectItem((int)row);\n        return !String.IsNullOrEmpty(_unit)\n            ? $\"{number} {_unit}\"\n            : number.ToString();\n    }\n\n    /// <summary>\n    /// Selected the specified picker, row and component.\n    /// </summary>\n    /// <returns>The selected.</returns>\n    /// <param name=\"picker\">Picker.</param>\n    /// <param name=\"row\">Row.</param>\n    /// <param name=\"component\">Component.</param>\n    public override void Selected(UIPickerView picker, nint row, nint component)\n    {\n\n        if (Items.Count == 0)\n        {\n            SelectedItem = 0;\n            SelectedIndex = -1;\n        }\n        else\n        {\n            SelectedItem = SelectItem((int)row);\n            SelectedIndex = (int)row;\n        }\n\n    }\n\n    /// <summary>\n    /// Sets the numbers.\n    /// </summary>\n    /// <param name=\"min\">Minimum.</param>\n    /// <param name=\"max\">Max.</param>\n    public void SetNumbers(int min, int max)\n    {\n        if (min < 0) min = 0;\n        if (max < 0) max = 0;\n        if (min > max)\n        {\n            //Set min value to zero temporally, because it is sometimes min greater than max depending on the order which min and max value is bound.\n            min = 0;\n        }\n        Items = Enumerable.Range(min, max - min + 1).ToList();\n    }\n\n    /// <summary>\n    /// Ons the update picker form model.\n    /// </summary>\n    public void OnUpdatePickerFormModel()\n    {\n        PreSelectedItem = SelectedItem;\n        UpdatePickerFromModel?.Invoke(this, EventArgs.Empty);\n    }\n    private int SelectItem(int row)\n    {\n        if (row >= Items.Count)\n        {\n            return Items[Items.Count - 1];\n        }\n        if (row < 0)\n        {\n            return Items[0];\n        }\n        return Items[row];\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/RadioCellView.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing Foundation;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Radio cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class RadioCellView : CellBaseView\n{\n    RadioCell _radioCell => Cell as RadioCell;\n\n    private object SelectedValue\n    {\n        get\n        {\n            return RadioCell.GetSelectedValue(_radioCell.Section) ?? RadioCell.GetSelectedValue(CellParent);\n        }\n        set\n        {\n            if (RadioCell.GetSelectedValue(_radioCell.Section) != null)\n            {\n                RadioCell.SetSelectedValue(_radioCell.Section, value);\n            }\n            else\n            {\n                RadioCell.SetSelectedValue(CellParent, value);\n            }\n        }\n    }\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.RadioCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public RadioCellView(CellBase virtualCell) : base(virtualCell)\n    {\n        SelectionStyle = UITableViewCellSelectionStyle.Default;\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        //UpdateAccentColor();\n        UpdateSelectedValue();\n        base.UpdateCell(tableView);\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }\n        else if (e.PropertyName == RadioCell.SelectedValueProperty.PropertyName)\n        {\n            UpdateSelectedValue();\n        }\n    }\n\n    /// <summary>\n    /// Sections the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void SectionPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.SectionPropertyChanged(sender, e);\n        if (e.PropertyName == RadioCell.SelectedValueProperty.PropertyName)\n        {\n            UpdateSelectedValue();\n        }\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        if (Accessory == UITableViewCellAccessory.None)\n        {\n            SelectedValue = _radioCell.Value;\n        }\n        tableView.DeselectRow(indexPath, true);\n    }\n\n    void UpdateSelectedValue()\n    {\n        if (_radioCell.Value is null)\n            return; // for HotReload\n\n        bool result;\n        if (_radioCell.Value.GetType().IsValueType || _radioCell.Value is string)\n        {\n            result = object.Equals(_radioCell.Value, SelectedValue);\n        }\n        else\n        {\n            result = object.ReferenceEquals(_radioCell.Value, SelectedValue);\n        }\n\n        Accessory = result ? UITableViewCellAccessory.Checkmark : UITableViewCellAccessory.None;\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_radioCell.AccentColor.IsNotDefault())\n        {\n            TintColor = _radioCell.AccentColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            TintColor = CellParent.CellAccentColor.ToPlatform();\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/SimpleCheckCellView.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing Foundation;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\n[Foundation.Preserve(AllMembers = true)]\r\npublic class SimpleCheckCellView: CellBaseView\n{\n    SimpleCheckCell _simpleCheckCell => Cell as SimpleCheckCell;\n\n    public SimpleCheckCellView(CellBase virtualCell): base(virtualCell)\n    {\n        SelectionStyle = UITableViewCellSelectionStyle.Default;\n    }\n\n    public override void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }        \n    }\n\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        base.RowSelected(tableView, indexPath);\n\n        tableView.DeselectRow(indexPath, true);\n    }\n\n    internal void UpdateChecked()\n    {\n\n        Accessory = _simpleCheckCell.Checked ? UITableViewCellAccessory.Checkmark : UITableViewCellAccessory.None;\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_simpleCheckCell.AccentColor.IsNotDefault())\n        {\n            TintColor = _simpleCheckCell.AccentColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            TintColor = CellParent.CellAccentColor.ToPlatform();\n        }\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/SwitchCellView.cs",
    "content": "﻿using System;\nusing AiSwitchCell = AiForms.Settings.SwitchCell;\nusing UIKit;\nusing Foundation;\nusing Microsoft.Maui.Platform;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Switch cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class SwitchCellView : CellBaseView\n{\n\n    AiSwitchCell _SwitchCell => Cell as AiSwitchCell;\n    UISwitch _switch;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.SwitchCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public SwitchCellView(CellBase virtualCell) : base(virtualCell)\n    {\n\n        _switch = new UISwitch();\n        _switch.ValueChanged += _switch_ValueChanged;\n\n        this.AccessoryView = _switch;\n        EditingAccessoryView = _switch;\n    }\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        base.RowSelected(tableView, indexPath);\n        _switch.On = !_switch.On;\n        _switch_ValueChanged(_switch, EventArgs.Empty);\n    }\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Parents the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void ParentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.ParentPropertyChanged(sender, e);\n        if (e.PropertyName == SettingsView.CellAccentColorProperty.PropertyName)\n        {\n            UpdateAccentColor();\n        }\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n        if (_switch is null)\n            return; // for HotReload\n\n        //UpdateAccentColor();\n        //UpdateOn();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _switch.ValueChanged -= _switch_ValueChanged;\n            AccessoryView = null;\n            _switch?.Dispose();\n            _switch = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Sets the enabled appearance.\n    /// </summary>\n    /// <param name=\"isEnabled\">If set to <c>true</c> is enabled.</param>\n    internal override void SetEnabledAppearance(bool isEnabled)\n    {\n        if (isEnabled)\n        {\n            _switch.Alpha = 1.0f;\n        }\n        else\n        {\n            _switch.Alpha = 0.3f;\n        }\n        base.SetEnabledAppearance(isEnabled);\n    }\n\n    void _switch_ValueChanged(object sender, EventArgs e)\n    {\n        _SwitchCell.On = _switch.On;\n    }\n\n    internal void UpdateOn()\n    {\n        if (_switch.On != _SwitchCell.On)\n        {\n            _switch.On = _SwitchCell.On;\n        }\n    }\n\n    internal void UpdateAccentColor()\n    {\n        if (_SwitchCell.AccentColor.IsNotDefault())\n        {\n            _switch.OnTintColor = _SwitchCell.AccentColor.ToPlatform();\n        }\n        else if (CellParent != null && CellParent.CellAccentColor.IsNotDefault())\n        {\n            _switch.OnTintColor = CellParent.CellAccentColor.ToPlatform();\n        }\n    }\n\n}"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/TextPickerCellView.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Windows.Input;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Text picker cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class TextPickerCellView : LabelCellView\n{\n    /// <summary>\n    /// Gets or sets the dummy field.\n    /// </summary>\n    /// <value>The dummy field.</value>\n    public UITextField DummyField { get; set; }\n    TextPickerSource _model;\n    UILabel _titleLabel;\n    UIPickerView _picker;\n    ICommand _command;\n\n    TextPickerCell _TextPickerCell => Cell as TextPickerCell;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.TextPickerCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public TextPickerCellView(CellBase virtualCell) : base(virtualCell)\n    {\n\n        DummyField = new NoCaretField();\n        DummyField.BorderStyle = UITextBorderStyle.None;\n        DummyField.BackgroundColor = UIColor.Clear;\n        ContentView.AddSubview(DummyField);\n        ContentView.SendSubviewToBack(DummyField);\n\n        SelectionStyle = UITableViewCellSelectionStyle.Default;\n\n        SetUpPicker();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        tableView.DeselectRow(indexPath, true);\n        DummyField.BecomeFirstResponder();\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n        //UpdateItems();\n        //UpdateSelectedItem();\n        //UpdateTitle();\n        //UpdateCommand();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _model.UpdatePickerFromModel -= Model_UpdatePickerFromModel;\n            DummyField.RemoveFromSuperview();\n            DummyField?.Dispose();\n            DummyField = null;\n            _titleLabel?.Dispose();\n            _titleLabel = null;\n            _model?.Dispose();\n            _model = null;\n            _picker?.Dispose();\n            _picker = null;\n            _command = null;\n\n        }\n        base.Dispose(disposing);\n    }\n\n    void SetUpPicker()\n    {\n        _picker = new UIPickerView();\n\n        var width = UIScreen.MainScreen.Bounds.Width;\n\n        _titleLabel = new UILabel();\n        _titleLabel.TextAlignment = UITextAlignment.Center;\n\n        var toolbar = new UIToolbar(new CGRect(0, 0, (float)width, 44)) { BarStyle = UIBarStyle.Default, Translucent = true };\n        var cancelButton = new UIBarButtonItem(UIBarButtonSystemItem.Cancel, (o, e) =>\n        {\n            DummyField.ResignFirstResponder();\n            Select(_model.PreSelectedItem);\n        });\n\n        var labelButton = new UIBarButtonItem(_titleLabel);\n        var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);\n        var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) =>\n        {\n            _model.OnUpdatePickerFormModel();\n            DummyField.ResignFirstResponder();\n            _command?.Execute(_model.SelectedItem);\n        });\n\n        toolbar.SetItems(new[] { cancelButton, spacer, labelButton, spacer, doneButton }, false);\n\n        DummyField.InputView = _picker;\n        DummyField.InputAccessoryView = toolbar;\n\n        _model = new TextPickerSource();\n        _picker.Model = _model;\n\n        _model.UpdatePickerFromModel += Model_UpdatePickerFromModel;\n    }\n\n    internal void UpdateSelectedItem()\n    {\n        Select(_TextPickerCell.SelectedItem);\n        ValueLabel.Text = _TextPickerCell.SelectedItem?.ToString();\n    }\n\n    internal void UpdateItems()\n    {\n        var items = _TextPickerCell.Items ?? new List<object>();\n        _model.SetItems(items);\n        // Force picker view to reload data from model after change\n        // Otherwise it might access the model based on old view data\n        // causing \"Index was out of range\" errors and the like.\n        _picker.ReloadAllComponents();\n        Select(_TextPickerCell.SelectedItem);\n    }\n\n    internal void UpdateTitle()\n    {\n        _titleLabel.Text = _TextPickerCell.PickerTitle;\n        _titleLabel.SizeToFit();\n        _titleLabel.Frame = new CGRect(0, 0, 160, 44);\n    }\n\n    internal void UpdateCommand()\n    {\n        _command = _TextPickerCell.SelectedCommand;\n    }\n\n    void Model_UpdatePickerFromModel(object sender, EventArgs e)\n    {\n        _TextPickerCell.SelectedItem = _model.SelectedItem;\n        ValueLabel.Text = _model.SelectedItem?.ToString();\n    }\n\n    /// <summary>\n    /// Layouts the subviews.\n    /// </summary>\n    public override void LayoutSubviews()\n    {\n        base.LayoutSubviews();\n\n        DummyField.Frame = new CGRect(0, 0, Frame.Width, Frame.Height);\n    }\n\n    void Select(object item)\n    {\n        var idx = _model.Items.IndexOf(item);\n        if (idx == -1)\n        {\n            item = _model.Items.Count == 0 ? null : _model.Items[0];\n            idx = 0;\n        }\n        _picker.Select(idx, 0, false);\n        _model.SelectedItem = item;\n        _model.SelectedIndex = idx;\n        _model.PreSelectedItem = item;\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/TextPickerSource.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n[Foundation.Preserve(AllMembers = true)]\ninternal class TextPickerSource : UIPickerViewModel\n{\n\n    internal IList Items { get; private set; }\n\n    internal event EventHandler UpdatePickerFromModel;\n\n    internal int SelectedIndex { get; set; }\n\n    internal object SelectedItem { get; set; }\n\n    internal object PreSelectedItem { get; set; }\n\n    /// <summary>\n    /// Gets the component count.\n    /// </summary>\n    /// <returns>The component count.</returns>\n    /// <param name=\"picker\">Picker.</param>\n    public override nint GetComponentCount(UIPickerView picker)\n    {\n        return 1;\n    }\n\n    /// <summary>\n    /// Gets the rows in component.\n    /// </summary>\n    /// <returns>The rows in component.</returns>\n    /// <param name=\"pickerView\">Picker view.</param>\n    /// <param name=\"component\">Component.</param>\n    public override nint GetRowsInComponent(UIPickerView pickerView, nint component)\n    {\n        return Items != null ? Items.Count : 0;\n    }\n\n    /// <summary>\n    /// Gets the title.\n    /// </summary>\n    /// <returns>The title.</returns>\n    /// <param name=\"picker\">Picker.</param>\n    /// <param name=\"row\">Row.</param>\n    /// <param name=\"component\">Component.</param>\n    public override string GetTitle(UIPickerView picker, nint row, nint component)\n    {\n        return Items[(int)row].ToString();\n    }\n\n    /// <summary>\n    /// Selected the specified picker, row and component.\n    /// </summary>\n    /// <returns>The selected.</returns>\n    /// <param name=\"picker\">Picker.</param>\n    /// <param name=\"row\">Row.</param>\n    /// <param name=\"component\">Component.</param>\n    public override void Selected(UIPickerView picker, nint row, nint component)\n    {\n\n        if (Items.Count == 0)\n        {\n            SelectedItem = null;\n            SelectedIndex = -1;\n        }\n        else\n        {\n            SelectedItem = Items[(int)row];\n            SelectedIndex = (int)row;\n        }\n\n    }\n\n    /// <summary>\n    /// Sets the items.\n    /// </summary>\n    /// <param name=\"items\">Items.</param>\n    public void SetItems(IList items)\n    {\n        Items = items;\n    }\n\n    /// <summary>\n    /// Ons the update picker form model.\n    /// </summary>\n    public void OnUpdatePickerFormModel()\n    {\n        PreSelectedItem = SelectedItem;\n        UpdatePickerFromModel?.Invoke(this, EventArgs.Empty);\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Cells/TimePickerCellView.cs",
    "content": "﻿using System;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Platform;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Time picker cell view.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class TimePickerCellView : LabelCellView\n{\n    TimePickerCell _TimePickerCell => Cell as TimePickerCell;\n    UIDatePicker _picker;\n    /// <summary>\n    /// Gets or sets the dummy field.\n    /// </summary>\n    /// <value>The dummy field.</value>\n    public UITextField DummyField { get; set; }\n    UILabel _titleLabel;\n    NSDate _preSelectedDate;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.TimePickerCellView\"/> class.\n    /// </summary>\n    /// <param name=\"virtualCell\">Forms cell.</param>\n    public TimePickerCellView(CellBase virtualCell) : base(virtualCell)\n    {\n        DummyField = new NoCaretField();\n        DummyField.BorderStyle = UITextBorderStyle.None;\n        DummyField.BackgroundColor = UIColor.Clear;\n        ContentView.AddSubview(DummyField);\n        ContentView.SendSubviewToBack(DummyField);\n\n        SelectionStyle = UITableViewCellSelectionStyle.Default;\n\n        SetUpTimePicker();\n    }\n\n    /// <summary>\n    /// Updates the cell.\n    /// </summary>\n    public override void UpdateCell(UITableView tableView)\n    {\n        base.UpdateCell(tableView);\n        //UpdatePickerTitle();\n        //UpdateTime();\n    }\n\n    /// <summary>\n    /// Cells the property changed.\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public override void CellPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        base.CellPropertyChanged(sender, e);\n        if (e.PropertyName == TimePickerCell.TimeProperty.PropertyName ||\n           e.PropertyName == TimePickerCell.FormatProperty.PropertyName)\n        {\n            UpdateTime();\n        }\n        else if (e.PropertyName == TimePickerCell.PickerTitleProperty.PropertyName)\n        {\n            UpdatePickerTitle();\n        }\n    }\n\n    /// <summary>\n    /// Rows the selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        tableView.DeselectRow(indexPath, true);\n        DummyField.BecomeFirstResponder();\n    }\n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            DummyField.RemoveFromSuperview();\n            DummyField?.Dispose();\n            DummyField = null;\n            _picker.Dispose();\n            _picker = null;\n            _titleLabel?.Dispose();\n            _titleLabel = null;\n        }\n        base.Dispose(disposing);\n    }\n\n    /// <summary>\n    /// Layouts the subviews.\n    /// </summary>\n    public override void LayoutSubviews()\n    {\n        base.LayoutSubviews();\n\n        DummyField.Frame = new CGRect(0, 0, Frame.Width, Frame.Height);\n    }\n\n    void SetUpTimePicker()\n    {\n        _picker = new UIDatePicker { Mode = UIDatePickerMode.Time, TimeZone = new NSTimeZone(\"UTC\") };\n        if (UIDevice.CurrentDevice.CheckSystemVersion(13, 4))\n        {\n            _picker.PreferredDatePickerStyle = UIDatePickerStyle.Wheels;\n        }\n\n        _titleLabel = new UILabel();\n        _titleLabel.TextAlignment = UITextAlignment.Center;\n\n        var width = UIScreen.MainScreen.Bounds.Width;\n        var toolbar = new UIToolbar(new CGRect(0, 0, (float)width, 44)) { BarStyle = UIBarStyle.Default, Translucent = true };\n        var cancelButton = new UIBarButtonItem(UIBarButtonSystemItem.Cancel, (o, e) =>\n        {\n            DummyField.ResignFirstResponder();\n            Canceled();\n        });\n\n        var labelButton = new UIBarButtonItem(_titleLabel);\n        var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);\n        var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) =>\n        {\n            DummyField.ResignFirstResponder();\n            Done();\n        });\n\n        toolbar.SetItems(new[] { cancelButton, spacer, labelButton, spacer, doneButton }, false);\n\n        DummyField.InputView = _picker;\n        DummyField.InputAccessoryView = toolbar;\n\n\n    }\n\n    void Canceled()\n    {\n        _picker.Date = _preSelectedDate;\n    }\n\n    void Done()\n    {\n        _TimePickerCell.Time = _picker.Date.ToDateTime() - new DateTime(1, 1, 1);\n        ValueLabel.Text = DateTime.Today.Add(_TimePickerCell.Time).ToString(_TimePickerCell.Format);\n        _preSelectedDate = _picker.Date;\n    }\n\n    internal void UpdateTime()\n    {\n        _picker.Date = new DateTime(1, 1, 1).Add(_TimePickerCell.Time).ToNSDate();\n        ValueLabel.Text = DateTime.Today.Add(_TimePickerCell.Time).ToString(_TimePickerCell.Format);\n        _preSelectedDate = _picker.Date;\n    }\n\n    internal void UpdatePickerTitle()\n    {\n        _titleLabel.Text = _TimePickerCell.PickerTitle;\n        _titleLabel.SizeToFit();\n        _titleLabel.Frame = new CGRect(0, 0, 160, 44);\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/CustomHeaderFooterView.cs",
    "content": "﻿#nullable enable\nusing System;\nusing System.ComponentModel;\nusing AiForms.Settings.Extensions;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Handlers;\nusing Microsoft.Maui.Platform;\nusing ObjCRuntime;\nusing SpriteKit;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\npublic class CustomHeaderView : CustomHeaderFooterView\n{\n    public CustomHeaderView()\n    {\n    }    \n\n    public CustomHeaderView(NSCoder coder) : base(coder)\n    {\n    }\n\n    public CustomHeaderView(CGRect frame) : base(frame)\n    {\n    }\n\n    public CustomHeaderView(NSString reuseIdentifier) : base(reuseIdentifier)\n    {\n    }\n\n    protected CustomHeaderView(NSObjectFlag t) : base(t)\n    {\n    }\n\n    protected internal CustomHeaderView(NativeHandle handle) : base(handle)\n    {\n    }\n}\n\npublic class CustomFooterView : CustomHeaderFooterView\n{\n    public CustomFooterView()\n    {\n    }    \n\n    public CustomFooterView(NSString reuseIdentifier) : base(reuseIdentifier)\n    {\n    }\n\n    public CustomFooterView(NSCoder coder) : base(coder)\n    {\n    }\n\n    public CustomFooterView(CGRect frame) : base(frame)\n    {\n    }\n\n    protected CustomFooterView(NSObjectFlag t) : base(t)\n    {\n    }\n\n    protected internal CustomFooterView(NativeHandle handle) : base(handle)\n    {\n    }\n}\n\npublic class CustomHeaderFooterView:UITableViewHeaderFooterView\n{\n    bool _disposed;\n    NSLayoutConstraint _heightConstraint;\n    View _virtualCell;\n    UITableView _tableView;\n    IMauiContext? _mauiContext => _virtualCell.FindMauiContext();    \n\n    public CustomHeaderFooterView()\n    {\n    }\n\n    public CustomHeaderFooterView(NSCoder coder) : base(coder)\n    {\n    }\n\n    protected CustomHeaderFooterView(NSObjectFlag t) : base(t)\n    {\n    }\n\n    protected internal CustomHeaderFooterView(NativeHandle handle) : base(handle)\n    {\n    }\n\n    public CustomHeaderFooterView(CGRect frame) : base(frame)\n    {\n    }\n\n    public CustomHeaderFooterView(NSString reuseIdentifier) : base(reuseIdentifier)\n    {\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (_disposed)\n        {\n            return;\n        }\n\n        if (disposing)\n        {\n            _cts?.Cancel();\n            _cts?.Dispose();\n            _cts = null;\n            if (_virtualCell != null)\n            {\n                _virtualCell.PropertyChanged -= CellPropertyChanged;\n                _virtualCell.MeasureInvalidated -= OnMeasureInvalidated;\n                foreach (var child in CustomCellContent.ElementDescendants(_virtualCell))\n                {\n                    if (child is Layout layout)\n                    {\n                        layout.SizeChanged -= OnInnerLayoutSizeChanged;\n                    }\n                    child.MeasureInvalidated -= OnMeasureInvalidated;\n                }\n                _virtualCell.DisposeModalAndChildHandlers();\n            }\n\n            _heightConstraint?.Dispose();\n            _heightConstraint = null;\n     \n            _virtualCell = null;\n            _tableView = null;\n        }\n\n        _disposed = true;\n\n        base.Dispose(disposing);\n    }\n\n    public virtual void UpdateNativeCell()\n    {\n        UpdateIsEnabled();\n    }\n\n    public virtual void CellPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)\n        {\n            UpdateIsEnabled();\n        }\n    }\n\n    protected virtual void UpdateIsEnabled()\n    {\n        UserInteractionEnabled = _virtualCell.IsEnabled;\n    }       \n      \n    public virtual void UpdateCell(View newCell,UITableView tableView)\n    {\n        _tableView = tableView; \n        \n        if (_virtualCell == newCell)\n        {\n            return;\n        }\n\n        var oldCell = _virtualCell;\n\n        if(oldCell != null)\n        {\n            // Do not disconnect the Handler here as it may not redraw.\n            //oldCell.Handler?.DisconnectHandler();\n            oldCell.PropertyChanged -= CellPropertyChanged;\n            oldCell.MeasureInvalidated -= OnMeasureInvalidated;\n            // Delete previous child element\n            foreach (var subView in ContentView.Subviews)\n            {\n                subView.RemoveFromSuperview();\n            }\n            \n            foreach (var child in CustomCellContent.ElementDescendants(oldCell))\n            {\n                if (child is Layout layout)\n                {\n                    layout.SizeChanged -= OnInnerLayoutSizeChanged;\n                }\n                child.MeasureInvalidated -= OnMeasureInvalidated;\n            }\n        }\n\n        _virtualCell = newCell;\n        _virtualCell.PropertyChanged += CellPropertyChanged;\n\n        IPlatformViewHandler handler;\n        if (newCell.Handler != null)\n        {\n            // TODO:\n            // Currently, the performance is not good because the number of\n            // NativieView is kept as many as the number of Cells. To improve this,\n            // it is necessary to virtualize the Content part of CustomCell as well.\n            // This can probably be achieved by replacing the Handler and\n            // resetting the VirtualView.\n\n            // If it has already been generated, use it as is.\n            handler = newCell.Handler as IPlatformViewHandler;\n            // If the incoming Cell belongs to another parent, peel it off.\n            handler.PlatformView?.RemoveFromSuperview();\n            ArrangeSubView(handler);            \n        }\n        else\n        {\n            // If Handler is not generated, generate it.            \n            handler = GetNewHandler();\n        }\n\n        if (_mauiContext == null)\n        {\n            return;\n        }\n\n        var viewHandlerType = _mauiContext.Handlers.GetHandlerType(_virtualCell.GetType());\n        var reflectableType = handler as System.Reflection.IReflectableType;\n        var handlerType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : (handler != null ? handler.GetType() : typeof(System.Object));\n\n        if (handlerType == viewHandlerType)\n        {\n            handler.SetVirtualView(_virtualCell);\n            System.Diagnostics.Debug.WriteLine(\"SetVirtualCell\");\n        }\n        else\n        {\n            //when cells are getting reused the element could be already set to another cell\n            //so we should dispose based on the renderer and not the renderer.Element\n            handler.DisposeHandlersAndChildren();\n            handler = GetNewHandler();\n            System.Diagnostics.Debug.WriteLine(\"Already set another cell\");\n        }       \n\n        var height = double.PositiveInfinity;\n        var result = _virtualCell.Measure(tableView.Frame.Width, height);\n        var finalW = result.Width;\n        if(_virtualCell.HorizontalOptions.Alignment == LayoutAlignment.Fill)\n        {\n            finalW = tableView.Frame.Width;\n        }\n        var finalH = (float)result.Height;           \n\n        UpdateNativeCell();\n\n        if (_heightConstraint != null)\n        {\n            _heightConstraint.Active = false;\n            _heightConstraint?.Dispose();\n        }\n\n        _heightConstraint = handler.PlatformView.HeightAnchor.ConstraintEqualTo(finalH);\n        _heightConstraint.Priority = 999f;\n        _heightConstraint.Active = true;\n\n        handler.PlatformView.UpdateConstraintsIfNeeded();\n        \n        _virtualCell.MeasureInvalidated += OnMeasureInvalidated;  \n        foreach (var child in CustomCellContent.ElementDescendants(_virtualCell))\n        {\n            if(child is Layout layout)\n            {\n                // Also detects changes in the size of descendant layout(BindableLayout)\n                layout.SizeChanged += OnInnerLayoutSizeChanged;\n            }\n            // Also detects changes in the size of descendant elements\n            child.MeasureInvalidated += OnMeasureInvalidated;\n        }\n    }\n\n    private void OnInnerLayoutSizeChanged(object sender, EventArgs e)\n    {\n        LayoutDispatcher();\n    }  \n    \n    private void OnMeasureInvalidated(object sender, EventArgs e)\n    {\n        LayoutDispatcher();\n    }\n\n    protected virtual IPlatformViewHandler? GetNewHandler()\n    {\n        if(_virtualCell == null)\n        {\n            throw new InvalidOperationException(\"Header or Footer must have a view\");\n        }\n\n        var findMauiContext = _virtualCell.FindMauiContext();\n\n        if (findMauiContext == null)\n        {\n            return null;\n        }\n\n        var newHandler = _virtualCell.ToHandler(findMauiContext);\n\n        ArrangeSubView(newHandler);\n\n        return newHandler;\n    }\n\n    protected virtual void ArrangeSubView(IPlatformViewHandler handler)\n    {\n        ContentView.AddSubview(handler.PlatformView);\n\n        var native = handler.PlatformView;\n        native.TranslatesAutoresizingMaskIntoConstraints = false;\n\n        native.TopAnchor.ConstraintEqualTo(ContentView.TopAnchor).Active = true;\n        native.LeftAnchor.ConstraintEqualTo(ContentView.LeftAnchor).Active = true;\n        native.BottomAnchor.ConstraintEqualTo(ContentView.BottomAnchor).Active = true;\n        native.RightAnchor.ConstraintEqualTo(ContentView.RightAnchor).Active = true;\n    }\n    \n    async Task ForceLayout(CancellationToken token)\n    {\n        if(_tableView == null || _tableView.IsDisposed())\n        {\n            return;\n        }\n        var tableView = _tableView;\n        if (_virtualCell?.Handler is not IPlatformViewHandler handler)\n        {\n            return;\n        }\n\n        // Wait a little and execute layout processing only on the last event\n        await Task.Delay(100,token);\n        if (token.IsCancellationRequested)\n        {\n            return;\n        }\n        \n        var height = double.PositiveInfinity;\n\n        var result = _virtualCell.Measure(tableView.Frame.Width, height);\n        var finalW = result.Width;\n        if (_virtualCell.HorizontalOptions.Alignment == LayoutAlignment.Fill)\n        {\n            finalW = tableView.Frame.Width;\n        }\n        var finalH = (float)result.Height;\n\n        if (_heightConstraint != null)\n        {\n            _heightConstraint.Active = false;\n            _heightConstraint?.Dispose();\n        }\n        \n        var native = handler.PlatformView;\n        if (native is null)\n        {\n            return;\n        }\n        \n        _heightConstraint = native.HeightAnchor.ConstraintEqualTo(finalH);\n        _heightConstraint.Priority = 999f;\n        _heightConstraint.Active = true;\n\n        _virtualCell.Arrange(new Rect(0, 0, finalW, finalH));\n\n        tableView.BeginUpdates();\n        tableView.EndUpdates();\n    }  \n    \n    CancellationTokenSource _cts = new CancellationTokenSource();\n    void LayoutDispatcher()\n    {\n        _cts?.Cancel();\n        _cts = new CancellationTokenSource();\n        _ = ForceLayout(_cts.Token);\n    }\n    \n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Extensions/DisposeHelpers.cs",
    "content": "﻿using System;\nusing System.Reflection;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\npublic static class DisposeHelpers\n{\n    static Type ModalWrapper = typeof(Element).Assembly.GetType(\"Microsoft.Maui.Controls.Platform.ControlsModalWrapper\");\n    static MethodInfo ModalWrapperDispose = ModalWrapper.GetMethod(\"Dispose\");\n    static MethodInfo ElementDescendants = typeof(Element).GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name == \"Descendants\" && !x.IsGenericMethod);\n\n    public static void DisposeModalAndChildHandlers(this Microsoft.Maui.IElement view)\n    {\n        IPlatformViewHandler renderer;\n        var desendants = ElementDescendants.Invoke((Element)view, new object[] { }) as IEnumerable<Element>;\n        foreach (Element child in desendants)\n        {\n            if (child is VisualElement ve)\n            {\n                ve.Handler?.DisconnectHandler();\n\n                if (ve.Handler is IDisposable disposable)\n                {\n                    disposable.Dispose();\n                }\n            }\n        }\n\n        if (view is VisualElement visualElement)\n        {\n            renderer = (visualElement.Handler as IPlatformViewHandler);\n            if (renderer != null)\n            {\n                if (renderer.ViewController != null)\n                {\n                    if (renderer.ViewController.ParentViewController.GetType() == ModalWrapper)\n                    {\n                        var modalWrapper = Convert.ChangeType(renderer.ViewController.ParentViewController, ModalWrapper);\n                        ModalWrapperDispose.Invoke(modalWrapper, new object[] { });\n                    }\n                }\n\n                renderer.PlatformView?.RemoveFromSuperview();\n\n                if (view.Handler is IDisposable disposable)\n                {\n                    disposable.Dispose();\n                }\n            }\n        }\n    }\n\n    public static void DisposeHandlersAndChildren(this IPlatformViewHandler rendererToRemove)\n    {\n        if (rendererToRemove == null)\n        {\n            return;\n        }\n\n        if (rendererToRemove.VirtualView != null && rendererToRemove.VirtualView.Handler == rendererToRemove)\n        {\n            rendererToRemove.VirtualView.Handler?.DisconnectHandler();\n        }\n\n        if (rendererToRemove.PlatformView != null)\n        {\n            var subviews = rendererToRemove.PlatformView.Subviews;\n            for (var i = 0; i < subviews.Length; i++)\n            {\n                if (subviews[i] is IPlatformViewHandler childRenderer)\n                {\n                    DisposeHandlersAndChildren(childRenderer);\n                }\n            }\n\n            rendererToRemove.PlatformView.RemoveFromSuperview();\n        }\n\n        if (rendererToRemove is IDisposable disposable)\n            disposable.Dispose();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/Extensions/NSObjectExtension.cs",
    "content": "﻿using System;\nusing Foundation;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\npublic static class NSObjectExtension\n{\n    /// <summary>\n    /// https://stackoverflow.com/questions/25532870/xamarin-ios-memory-leaks-everywhere\n    /// </summary>\n    /// <param name=\"target\"></param>\n    public static void DisposeIfDisposable(this NSObject target)\n    {\n        if(target == null)\n        {\n            return;\n        }\n\n        if(!target.IsDisposed())\n        {\n            target.Dispose();\n        }\n    }\n\n    public static bool IsDisposed(this NSObject target)\n    {\n        return target.Handle == IntPtr.Zero;\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Extensions/StackViewAlignmentExtensions.cs",
    "content": "﻿using System;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\n/// <summary>\n/// Stack view alignment extensions.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic static class StackViewAlignmentExtensions\n{\n    /// <summary>\n    /// Tos the native vertical.\n    /// </summary>\n    /// <returns>The native vertical.</returns>\n    /// <param name=\"forms\">Forms.</param>\n    public static UIStackViewAlignment ToNativeVertical(this LayoutAlignment forms)\n    {\n        switch (forms) {\n            case LayoutAlignment.Start:\n                return UIStackViewAlignment.Leading;\n            case LayoutAlignment.Center:\n                return UIStackViewAlignment.Center;\n            case LayoutAlignment.End:\n                return UIStackViewAlignment.Trailing;\n            default:\n                return UIStackViewAlignment.Fill;\n        }\n    }\n\n    /// <summary>\n    /// Tos the native horizontal.\n    /// </summary>\n    /// <returns>The native horizontal.</returns>\n    /// <param name=\"forms\">Forms.</param>\n    public static UIStackViewAlignment ToNativeHorizontal(this LayoutAlignment forms)\n    {\n        switch (forms) {\n            case LayoutAlignment.Start:\n                return UIStackViewAlignment.Top;\n            case LayoutAlignment.Center:\n                return UIStackViewAlignment.Center;\n            case LayoutAlignment.End:\n                return UIStackViewAlignment.Bottom;\n            default:\n                return UIStackViewAlignment.Fill;\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Extensions/TextAlignmentExtensions.cs",
    "content": "﻿using System;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\n/// <summary>\n/// Text alignment extensions.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic static class TextAlignmentExtensions\n{\n    /// <summary>\n    /// To the UITextalignment.\n    /// </summary>\n    /// <returns>The UIT ext alignment.</returns>\n    /// <param name=\"forms\">Forms.</param>\n    public static UITextAlignment ToUITextAlignment(this TextAlignment forms)\n    {\n        switch (forms) {\n            case TextAlignment.Start:\n                return UITextAlignment.Left;\n            case TextAlignment.Center:\n                return UITextAlignment.Center;\n            case TextAlignment.End:\n                return UITextAlignment.Right;\n            default:\n                return UITextAlignment.Right;\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/Extensions/ThicknessExtensions.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\n/// <summary>\n/// Thickness extensions.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic static class ThicknessExtensions\n{\n    /// <summary>\n    /// To the UIEdgeinsets.\n    /// </summary>\n    /// <returns>The UIE dge insets.</returns>\n    /// <param name=\"forms\">Forms.</param>\n    public static UIEdgeInsets ToUIEdgeInsets(this Thickness forms)\n    {\n        return new UIEdgeInsets(\n            (NFloat)forms.Top,\n            (NFloat)forms.Left,\n            (NFloat)forms.Bottom,\n            (NFloat)forms.Right\n        );\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/KeyboardInsetTracker.cs",
    "content": "﻿using System;\nusing Microsoft.Maui.Controls.Handlers.Compatibility;\nusing SpriteKit;\nusing UIKit;\nusing PointF = CoreGraphics.CGPoint;\nusing RectangleF = CoreGraphics.CGRect;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\n/// <summary>\n/// Copy from\n/// https://github.com/dotnet/maui/blob/main/src/Controls/src/Core/Compatibility/Handlers/iOS/KeyboardInsetTracker.cs\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\ninternal class KeyboardInsetTracker : IDisposable\n{\n    readonly Func<UIWindow> _fetchWindow;\n    readonly Action<PointF> _setContentOffset;\n    readonly Action<UIEdgeInsets> _setInsetAction;\n    readonly UIView _targetView;\n    bool _disposed;\n\n    RectangleF _lastKeyboardRect;\n\n    public KeyboardInsetTracker(UIView targetView, Func<UIWindow> fetchWindow, Action<UIEdgeInsets> setInsetAction, Action<PointF> setContentOffset, IPlatformViewHandler renderer)\n    {\n        _setContentOffset = setContentOffset;\n        _targetView = targetView;\n        _fetchWindow = fetchWindow;\n        _setInsetAction = setInsetAction;\n        KeyboardObserver.KeyboardWillShow += OnKeyboardShown;\n        KeyboardObserver.KeyboardWillHide += OnKeyboardHidden;\n    }\n\n    public void Dispose()\n    {\n        if (_disposed)\n            return;\n        _disposed = true;\n\n        KeyboardObserver.KeyboardWillShow -= OnKeyboardShown;\n        KeyboardObserver.KeyboardWillHide -= OnKeyboardHidden;\n    }\n\n    //This method allows us to update the insets if the Frame changes\n    internal void UpdateInsets()\n    {\n        //being called from LayoutSubviews but keyboard wasn't shown yet\n        if (_lastKeyboardRect.IsEmpty)\n            return;\n\n        var window = _fetchWindow();\n        // Code left verbose to make its operation more obvious\n        if (window == null)\n        {\n            // we are not currently displayed and can safely ignore this\n            // most likely this renderer is on a page which is currently not displayed (e.g. in NavController)\n            return;\n        }\n\n        var field = FindFirstResponder(_targetView);\n\n        //the view that is triggering the keyboard is not inside our UITableView?\n        //if (field == null)\n        //  return;\n\n        var boundsSize = _targetView.Frame.Size;\n\n        //since our keyboard frame is RVC CoordinateSpace, lets convert it to our targetView CoordinateSpace\n        var rect = _targetView.Superview.ConvertRectFromView(_lastKeyboardRect, null);\n        //let's see how much does it cover our target view\n        var overlay = RectangleF.Intersect(rect, _targetView.Frame);\n\n        _setInsetAction(new UIEdgeInsets(0, 0, overlay.Height, 0));\n\n        if (field is UITextView && _setContentOffset != null)\n        {\n            var keyboardTop = boundsSize.Height - overlay.Height;\n            var fieldPosition = field.ConvertPointToView(field.Frame.Location, _targetView.Superview);\n            var fieldBottom = fieldPosition.Y + field.Frame.Height;\n            var offset = fieldBottom - keyboardTop;\n            if (offset > 0)\n                _setContentOffset(new PointF(0, offset));\n        }\n    }\n\n    void OnKeyboardHidden(object sender, UIKeyboardEventArgs args)\n    {\n        _setInsetAction(new UIEdgeInsets(0, 0, 0, 0));\n        _lastKeyboardRect = RectangleF.Empty;\n    }\n\n    void OnKeyboardShown(object sender, UIKeyboardEventArgs args)\n    {\n        _lastKeyboardRect = args.FrameEnd;\n        UpdateInsets();\n    }\n\n    //元は拡張メソッドだけど移植がめんどいので個別切り出し\n    UIView FindFirstResponder(UIView view)\n    {\n        if (view.IsFirstResponder)\n            return view;\n\n        foreach (var subView in view.Subviews)\n        {\n            var firstResponder = FindFirstResponder(subView);\n            if (firstResponder != null)\n                return firstResponder;\n        }\n\n        return null;\n    }\n}\n\ninternal static class KeyboardObserver\n{\n    static KeyboardObserver()\n    {\n        UIKeyboard.Notifications.ObserveWillShow(OnKeyboardShown);\n        UIKeyboard.Notifications.ObserveWillHide(OnKeyboardHidden);\n    }\n\n    public static event EventHandler<UIKeyboardEventArgs> KeyboardWillHide;\n\n    public static event EventHandler<UIKeyboardEventArgs> KeyboardWillShow;\n\n    static void OnKeyboardHidden(object sender, UIKeyboardEventArgs args)\n    {\n        var handler = KeyboardWillHide;\n        if (handler != null)\n            handler(sender, args);\n    }\n\n    static void OnKeyboardShown(object sender, UIKeyboardEventArgs args)\n    {\n        var handler = KeyboardWillShow;\n        if (handler != null)\n            handler(sender, args);\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/Native/iOS/PaddingLabel.cs",
    "content": "﻿using System;\nusing CoreGraphics;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\npublic class PaddingLabel : UILabel\n{\n    UIEdgeInsets _padding = new UIEdgeInsets();\n    public UIEdgeInsets Padding {\n        get => _padding;\n        set {\n            _padding = value;\n            SetNeedsLayout();\n            SetNeedsDisplay();\n        }\n    }\n\n    public override void DrawText(CGRect rect)\n    {\n        base.DrawText(Padding.InsetRect(rect));\n    }\n\n    public override CGSize IntrinsicContentSize {\n        get {\n            var contentSize = base.IntrinsicContentSize;\n            contentSize.Height += Padding.Top + Padding.Bottom;\n            contentSize.Width += Padding.Left + Padding.Right;\n            return contentSize;\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/SettingsTableSource.cs",
    "content": "﻿using System;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Threading.Tasks;\nusing AiForms.Settings.Extensions;\nusing AiForms.Settings.Handlers;\nusing CoreGraphics;\nusing Foundation;\nusing Microsoft.Maui.Controls.Platform;\nusing Microsoft.Maui.Platform;\nusing ObjCRuntime;\nusing UIKit;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\n/// <summary>\n/// Settings table source.\n/// </summary>\n[Foundation.Preserve(AllMembers = true)]\npublic class SettingsTableSource : UITableViewSource\n{\n    /// <summary>\n    /// The table view.\n    /// </summary>\n    protected UITableView _tableView;\n    /// <summary>\n    /// The settings view.\n    /// </summary>\n    protected SettingsView _settingsView;\n\n    bool _disposed;\n    HashSet<IElementHandler> _cellHandlers = new HashSet<IElementHandler>();\n\n    Lazy<IFontManager> _fontManager;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.iOS.SettingsTableSource\"/> class.\n    /// </summary>\n    /// <param name=\"settingsView\">Settings view.</param>\n    public SettingsTableSource(SettingsView settingsView)\n    {\n        _settingsView = settingsView;\n        _settingsView.ModelChanged += (sender, e) => {\n            if (_tableView != null) {\n                _tableView.ReloadData();\n                // reflect a dynamic cell height\n                _tableView.PerformBatchUpdates(null, null);\n            }\n        };\n\n        _fontManager = new Lazy<IFontManager>(() =>\n        {\n            return settingsView.FindMauiContext().Services.GetService<IFontManager>();\n        });\n    }\n\n    /// <summary>\n    /// Gets the cell.\n    /// </summary>\n    /// <returns>The cell.</returns>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)\n    {\n        //get Maui cell\n        var cell = _settingsView.Model.GetCell(indexPath.Section, indexPath.Row);\n\n        var id = cell.GetType().FullName;\n        //get native recycle cell\n        var reusableCell = tableView.DequeueReusableCell(id);\n\n        if(cell.Handler != null)\n        {\n            _cellHandlers.Remove(cell.Handler);\n            // disconnect old nativeview;\n            cell.Handler.DisconnectHandler();\n            cell.Handler = null;\n        }\n        \n        cell.ReusableCell = reusableCell;\n        cell.TableView = tableView;\n\n        // connect the next cell to the reusableNativeView or a new nativeView\n        var handler = cell.ToHandler(cell.FindMauiContext());\n\n        _cellHandlers.Add(handler);\n\n        var platformCell = handler.PlatformView as CellBaseView;\n\n        var cellWithContent = platformCell;\n\n        // Sometimes iOS for returns a dequeued cell whose Layer is hidden. \n        // This prevents it from showing up, so lets turn it back on!\n        if (cellWithContent.Layer.Hidden)\n        {\n            cellWithContent.Layer.Hidden = false;\n        }\n\n        // Because the layer was hidden we need to layout the cell by hand\n        if (cellWithContent != null)\n        {\n            //cellWithContent.LayoutSubviews();\n        }\n\n        return platformCell;           \n    }    \n\n    /// <summary>\n    /// Gets the height for row.\n    /// </summary>\n    /// <returns>The height for row.</returns>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override NFloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)\n    {\n        var cell = _settingsView.Model.GetCell(indexPath.Section, indexPath.Row);\n        if (!cell.IsVisible)\n        {\n            return NFloat.Epsilon;\n        }\n        \n        if (!_settingsView.HasUnevenRows) {\n            return tableView.EstimatedRowHeight;\n        }\n        \n        var h = cell.Height;\n\n        if (h == -1) {\n            //automatic height\n            return tableView.RowHeight;\n        }\n\n        //individual height\n        return (NFloat)h;\n    }\n\n    /// <summary>\n    /// section header height\n    /// </summary>\n    /// <returns>The height for header.</returns>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"section\">Section.</param>\n    public override NFloat GetHeightForHeader(UITableView tableView, nint section)\n    {\n        var sec = _settingsView.Model.GetSection((int)section);\n\n        if (!sec.IsVisible)\n        {\n            return NFloat.Epsilon;\n        }\n\n        if(sec.HeaderView != null)\n        {\n            return UITableView.AutomaticDimension; // automatic height\n        }\n\n        var individualHeight = sec.HeaderHeight;\n\n        if(individualHeight > 0d){\n            return (NFloat)individualHeight;\n        }\n        if (_settingsView.HeaderHeight == -1d) {\n            return UITableView.AutomaticDimension;\n        }\n\n        return (NFloat)_settingsView.HeaderHeight;\n    }\n\n    /// <summary>\n    /// Gets the view for header.\n    /// </summary>\n    /// <returns>The view for header.</returns>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"section\">Section.</param>\n    public override UIView GetViewForHeader(UITableView tableView, nint section)\n    {\n        var formsView = _settingsView.Model.GetSectionHeaderView((int)section);\n        if (formsView != null)\n        {\n            return GetNativeSectionHeaderFooterView(formsView, tableView, true);\n        }\n\n\n        var headerView = _tableView.DequeueReusableHeaderFooterView(SettingsViewHandler.TextHeaderId) as TextHeaderView;\n        if(headerView is null)\n        {\n            // for HotReload\n            return new UIView();\n        }\n\n        headerView.Label.Text = _settingsView.Model.GetSectionTitle((int)section);\n        headerView.Label.TextColor = _settingsView.HeaderTextColor.IsDefault() ?\n            UIColor.Gray : _settingsView.HeaderTextColor.ToPlatform();\n\n        headerView.Label.Font = _settingsView.HeaderFontFamily\n            .ToFont(_settingsView.HeaderFontSize, _settingsView.HeaderFontAttributes)\n            .ToUIFont(_fontManager.Value);\n\n        headerView.BackgroundView.BackgroundColor = _settingsView.HeaderBackgroundColor.ToPlatform();\n        headerView.Label.Padding = _settingsView.HeaderPadding.ToUIEdgeInsets();\n\n        var sec = _settingsView.Model.GetSection((int)section);\n        if(sec.HeaderHeight != -1 || _settingsView.HeaderHeight != -1)\n        {\n            headerView.SetVerticalAlignment(_settingsView.HeaderTextVerticalAlign);\n        }\n\n        return headerView;\n    }\n\n    /// <summary>\n    /// section footer height\n    /// </summary>\n    /// <returns>The height for footer.</returns>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"section\">Section.</param>\n    public override NFloat GetHeightForFooter(UITableView tableView, nint section)\n    {\n        var sec = _settingsView.Model.GetSection((int)section);\n\n        if (!sec.IsVisible)\n        {\n            return NFloat.Epsilon;\n        }\n\n        if(!sec.FooterVisible)\n        {\n            return NFloat.Epsilon;\n        }\n\n        if (sec.FooterView != null)\n        {\n            return UITableView.AutomaticDimension; // automatic height\n        }\n\n        var footerText = sec.FooterText;\n\n        if (string.IsNullOrEmpty(footerText)) {\n            //hide footer\n            return NFloat.Epsilon; // must not zero\n        }\n\n        return UITableView.AutomaticDimension;\n    }\n\n    /// <summary>\n    /// Gets the view for footer.\n    /// </summary>\n    /// <returns>The view for footer.</returns>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"section\">Section.</param>\n    public override UIView GetViewForFooter(UITableView tableView, nint section)\n    {\n        var formsView = _settingsView.Model.GetSectionFooterView((int)section);\n        if (formsView != null)\n        {\n            return GetNativeSectionHeaderFooterView(formsView, tableView, false);\n        }\n\n        var text = _settingsView.Model.GetFooterText((int)section);\n\n        if (string.IsNullOrEmpty(text)) {\n            return new UIView(CGRect.Empty);\n        }\n\n        var footerView = _tableView.DequeueReusableHeaderFooterView(SettingsViewHandler.TextFooterId) as TextFooterView;\n\n        if (footerView is null)\n        {\n            // for HotReload\n            return new UIView();\n        }            \n\n        footerView.Label.Text = text;\n        footerView.Label.TextColor = _settingsView.FooterTextColor.IsDefault() ?\n            UIColor.Gray : _settingsView.FooterTextColor.ToPlatform();\n\n        footerView.Label.Font = _settingsView.FooterFontFamily\n            .ToFont(_settingsView.FooterFontSize, _settingsView.FooterFontAttributes)\n            .ToUIFont(_fontManager.Value); \n\n        footerView.BackgroundView.BackgroundColor = _settingsView.FooterBackgroundColor.ToPlatform();\n        footerView.Label.Padding = _settingsView.FooterPadding.ToUIEdgeInsets();\n\n        return footerView;\n    }\n\n    UIView GetNativeSectionHeaderFooterView(View formsView, UITableView tableView, bool isHeader)\n    {\n        var idString = isHeader ? SettingsViewHandler.CustomHeaderId : SettingsViewHandler.CustomFooterId;\n        var nativeView = tableView.DequeueReusableHeaderFooterView(idString) as CustomHeaderFooterView;\n        nativeView.UpdateCell(formsView,tableView);\n\n        return nativeView;\n    }\n\n    /// <summary>\n    /// Numbers the of sections.\n    /// </summary>\n    /// <returns>The of sections.</returns>\n    /// <param name=\"tableView\">Table view.</param>\n    public override nint NumberOfSections(UITableView tableView)\n    {\n        _tableView = tableView;\n        return _settingsView.Model.GetSectionCount();\n    }\n\n    /// <summary>\n    /// Rowses the in section.\n    /// </summary>\n    /// <returns>The in section.</returns>\n    /// <param name=\"tableview\">Tableview.</param>\n    /// <param name=\"section\">Section.</param>\n    public override nint RowsInSection(UITableView tableview, nint section)\n    {\n        var sec = _settingsView.Model.GetSection((int)section);\n        return sec.IsVisible ? sec.Count : 0;\n    }\n\n\n    public override bool ShouldShowMenu(UITableView tableView, NSIndexPath rowAtindexPath)\n    {\n        if(_settingsView.Model.GetSection(rowAtindexPath.Section).UseDragSort)\n        {\n            return false;\n        }\n\n        var ret = false;\n        if(tableView.CellAt(rowAtindexPath) is CellBaseView cell)\n        {\n            System.Diagnostics.Debug.WriteLine(\"LongTap\");\n            ret = cell.RowLongPressed(tableView, rowAtindexPath);\n        }\n\n        if(ret)\n        {\n            BeginInvokeOnMainThread(async () => {\n                await Task.Delay(250);\n                tableView.CellAt(rowAtindexPath).SetSelected(false, true);\n            });\n        }\n\n        return ret;\n    }\n\n    public override bool CanPerformAction(UITableView tableView, Selector action, NSIndexPath indexPath, NSObject sender)\n    {\n        return false;\n    }\n\n    public override void PerformAction(UITableView tableView, Selector action, NSIndexPath indexPath, NSObject sender)\n    {\n    }\n\n    /// <summary>\n    /// Title text string array (unknown what to do ) \n    /// </summary>\n    /// <returns>The index titles.</returns>\n    /// <param name=\"tableView\">Table view.</param>\n    public override string[] SectionIndexTitles(UITableView tableView)\n    {\n        return _settingsView.Model.GetSectionIndexTitles();\n    }\n\n    /// <summary>\n    /// processing when row is selected.\n    /// </summary>\n    /// <param name=\"tableView\">Table view.</param>\n    /// <param name=\"indexPath\">Index path.</param>\n    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)\n    {\n        _settingsView.Model.OnRowSelected(indexPath.Section, indexPath.Row);\n\n        if (tableView.CellAt(indexPath) is CellBaseView cell)\n        {\n            cell.RowSelected(tableView, indexPath);\n        }\n    }       \n\n    /// <summary>\n    /// Dispose the specified disposing.\n    /// </summary>\n    /// <returns>The dispose.</returns>\n    /// <param name=\"disposing\">If set to <c>true</c> disposing.</param>\n    protected override void Dispose(bool disposing)\n    {\n        if (!_disposed){\n\n            foreach(var section in _settingsView.Root)\n            {\n                foreach(var cell in section)\n                {\n                    cell.ReusableCell = null;\n                    cell.TableView = null;\n                }\n            }\n\n            foreach(var handler in _cellHandlers)\n            {\n                handler.DisconnectHandler();\n            }\n            _cellHandlers.Clear();\n            _cellHandlers = null;\n\n            _fontManager = null;\n            _settingsView = null;\n            _tableView = null;               \n        }\n\n        _disposed = true;\n\n        base.Dispose(disposing);\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/TextFooterView.cs",
    "content": "﻿using System;\nusing UIKit;\nusing System.Collections.Generic;\nusing Foundation;\nusing ObjCRuntime;\nusing CoreGraphics;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\npublic class TextFooterView : UITableViewHeaderFooterView\n{\n    public PaddingLabel Label { get; set; }\n    List<NSLayoutConstraint> _constraints = new List<NSLayoutConstraint>();\n\n    public TextFooterView()\n    {\n    }\n\n    public TextFooterView(NSCoder coder) : base(coder)\n    {\n    }\n\n    protected TextFooterView(NSObjectFlag t) : base(t)\n    {\n    }\n\n    protected internal TextFooterView(NativeHandle handle) : base(handle)\n    {\n        Label = new PaddingLabel();\n        Label.Lines = 0;\n        Label.LineBreakMode = UILineBreakMode.CharacterWrap;\n        Label.TranslatesAutoresizingMaskIntoConstraints = false;\n\n        ContentView.AddSubview(Label);\n\n        _constraints.Add(Label.TopAnchor.ConstraintEqualTo(ContentView.TopAnchor, 0));\n        _constraints.Add(Label.BottomAnchor.ConstraintEqualTo(ContentView.BottomAnchor, 0));\n        _constraints.Add(Label.LeftAnchor.ConstraintEqualTo(ContentView.LeftAnchor, 0));\n        _constraints.Add(Label.RightAnchor.ConstraintEqualTo(ContentView.RightAnchor, 0));\n\n        _constraints.ForEach(c => {\n            c.Priority = 999f; // fix warning-log:Unable to simultaneously satisfy constraints.\n            c.Active = true;\n        });\n\n        this.BackgroundView = new UIView();\n    }\n\n    public TextFooterView(CGRect frame) : base(frame)\n    {\n    }\n\n    public TextFooterView(NSString reuseIdentifier) : base(reuseIdentifier)\n    {\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        base.Dispose(disposing);\n        if (disposing)\n        {\n            _constraints.ForEach(c => c.Dispose());\n            Label?.Dispose();\n            Label = null;\n            BackgroundView?.Dispose();\n            BackgroundView = null;\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/Native/iOS/TextHeaderView.cs",
    "content": "﻿using System;\nusing UIKit;\nusing System.Collections.Generic;\nusing CoreGraphics;\nusing Foundation;\nusing ObjCRuntime;\n\nnamespace AiForms.Settings.Platforms.iOS;\n\r\npublic class TextHeaderView : UITableViewHeaderFooterView\n{\n    public PaddingLabel Label { get; set; }\n    List<NSLayoutConstraint> _constraints = new List<NSLayoutConstraint>();\n    LayoutAlignment _curAlignment;\n    bool _isInitialized;    \n\n    public TextHeaderView()\n    {\n    }\n\n    public TextHeaderView(NSCoder coder) : base(coder)\n    {\n    }\n\n    protected TextHeaderView(NSObjectFlag t) : base(t)\n    {\n    }\n\n    protected internal TextHeaderView(NativeHandle handle) : base(handle)\n    {\n        Label = new PaddingLabel();\n        Label.Lines = 0;\n        Label.LineBreakMode = UILineBreakMode.CharacterWrap;\n        Label.TranslatesAutoresizingMaskIntoConstraints = false;\n\n        ContentView.AddSubview(Label);\n\n        _constraints.Add(Label.TopAnchor.ConstraintEqualTo(ContentView.TopAnchor, 0));\n        _constraints.Add(Label.BottomAnchor.ConstraintEqualTo(ContentView.BottomAnchor, 0));\n        _constraints.Add(Label.LeftAnchor.ConstraintEqualTo(ContentView.LeftAnchor, 0));\n        _constraints.Add(Label.RightAnchor.ConstraintEqualTo(ContentView.RightAnchor, 0));\n\n        _constraints.ForEach(c => {\n            c.Priority = 999f; // fix warning-log:Unable to simultaneously satisfy constraints.\n            c.Active = true;\n        });\n\n\n        this.BackgroundView = new UIView();\n    }\n\n    public TextHeaderView(CGRect frame) : base(frame)\n    {\n    }\n\n    public TextHeaderView(NSString reuseIdentifier) : base(reuseIdentifier)\n    {\n    }\n\n    public void SetVerticalAlignment(LayoutAlignment align)\n    {\n        if(_isInitialized && align == _curAlignment)\n        {\n            return;\n        }\n\n        foreach (var c in _constraints)\n        {\n            c.Active = false;\n            c.Dispose();\n        }\n        _constraints.Clear();\n\n        _constraints.Add(Label.LeftAnchor.ConstraintEqualTo(ContentView.LeftAnchor, 0));\n        _constraints.Add(Label.RightAnchor.ConstraintEqualTo(ContentView.RightAnchor, 0));\n\n        if (align == LayoutAlignment.Start)\n        {\n            _constraints.Add(Label.TopAnchor.ConstraintEqualTo(ContentView.TopAnchor, 0));\n        }\n        else if (align == LayoutAlignment.End)\n        {\n            _constraints.Add(Label.BottomAnchor.ConstraintEqualTo(ContentView.BottomAnchor, 0));\n        }\n        else\n        {\n            _constraints.Add(Label.CenterYAnchor.ConstraintEqualTo(ContentView.CenterYAnchor, 0));\n        }\n\n        _constraints.ForEach(c => {\n            c.Priority = 999f; // fix warning-log:Unable to simultaneously satisfy constraints.\n            c.Active = true;\n        });\n\n        _curAlignment = align;\n        _isInitialized = true;\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        base.Dispose(disposing);\n        if(disposing)\n        {\n            _constraints.ForEach(c => c.Dispose());\n            Label?.Dispose();\n            Label = null;\n            BackgroundView?.Dispose();\n            BackgroundView = null;\n        }\n    }\n}\n"
  },
  {
    "path": "SettingsView/NaturalComparer.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Text;\n\n// Copy from https://github.com/tomochan154/toy-box/edit/master/NaturalComparer.cs\n\nnamespace AiForms.Settings;\n\r\n/// <summary>ソートの方向。</summary>\npublic enum NaturalSortOrder : int\n{\n    #region Enum\n\n    /// <summary>なし。</summary>\n    None = 0,\n    /// <summary>昇順。</summary>\n    Ascending = 1,\n    /// <summary>降順。</summary>\n    Descending = 2,\n\n    #endregion\n}\n\n/// <summary>自然順の比較オプション。</summary>\n[Flags()]\npublic enum NaturalComparerOptions\n{\n    #region Enum\n\n    /// <summary>アラビア数字。</summary>\n    Number = 0x1,\n    /// <summary>ASCIIローマ数字。</summary>\n    RomanNumber = 0x2,\n    /// <summary>日本語ローマ数字。</summary>\n    JpRomanNumber = 0x4,\n    /// <summary>日本語丸数字。</summary>\n    CircleNumber = 0x8,\n    /// <summary>日本語漢数字。</summary>\n    KanjiNumber = 0x10,\n    /// <summary>すべての数字。</summary>\n    NumberAll = Number | RomanNumber | JpRomanNumber | CircleNumber | KanjiNumber,\n\n    /// <summary>空白文字の存在を無視。</summary>\n    IgnoreSpace = 0x10000,\n    /// <summary>数字表現の違いを無視。</summary>\n    IgnoreNumber = 0x20000,\n    /// <summary>全角半角の違いを無視。</summary>\n    IgnoreWide = 0x40000,\n    /// <summary>大文字小文字の違いを無視。</summary>\n    IgnoreCase = 0x80000,\n    /// <summary>カタカナひらがなの違いを無視。</summary>\n    IgnoreKana = 0x100000,\n    /// <summary>すべての無視条件。</summary>\n    IgnoreAll = IgnoreSpace | IgnoreNumber | IgnoreWide | IgnoreCase | IgnoreKana,\n\n    /// <summary>既定の比較オプション。</summary>\n    Default = NumberAll | IgnoreSpace | IgnoreNumber | IgnoreWide | IgnoreCase,\n\n    #endregion\n}\n\n/// <summary>自然順の比較機能を提供します。</summary>\npublic class NaturalComparer : IComparer<string>, IComparer\n{\n    #region Enum\n\n    /// <summary>数字表現文字の種類。</summary>\n    private enum CharTypes : uint\n    {\n        /// <summary>なし。</summary>\n        None = 0x0,\n        /// <summary>アラビア数字。</summary>\n        Number = 0x1,\n        /// <summary>ASCIIローマ数字。</summary>\n        RomanNumber = 0x2,\n        /// <summary>日本語ローマ数字。</summary>\n        JpRomanNumber = 0x4,\n        /// <summary>日本語丸数字。</summary>\n        CircleNumber = 0x8,\n        /// <summary>日本語漢数字。</summary>\n        KanjiNumber = 0x10,\n    }\n\n    #endregion\n\n    #region Field\n\n    /// <summary>ソートの方向を表す int。</summary>\n    private int _order;\n    /// <summary>自然順の比較オプションを表す <see cref=\"NaturalComparerOptions\"/>。</summary>\n    private NaturalComparerOptions _options;\n    /// <summary>除外文字を表す char[]。</summary>\n    private char[] _ignoreCharacter;\n    /// <summary>比較オプションを組み合わせた除外文字を表す char[]。</summary>\n    private char[] _ignoreTable;\n\n    #endregion\n\n    #region Constructor\n\n    /// <summary>インスタンスを初期化します。</summary>\n    public NaturalComparer()\n        : this(NaturalSortOrder.Ascending, NaturalComparerOptions.Default, new char[0])\n    {\n    }\n\n    /// <summary>インスタンスを初期化します。</summary>\n    /// <param name=\"order\">ソート方向を表す <see cref=\"NaturalSortOrder\"/>。</param>\n    public NaturalComparer(NaturalSortOrder order)\n        : this(order, NaturalComparerOptions.Default, new char[0])\n    {\n    }\n\n    /// <summary>インスタンスを初期化します。</summary>\n    /// <param name=\"order\">ソート方向を表す <see cref=\"NaturalSortOrder\"/>。</param>\n    /// <param name=\"options\">比較方法を表す <see cref=\"NaturalComparerOptions\"/>。</param>\n    public NaturalComparer(NaturalSortOrder order, NaturalComparerOptions options)\n        : this(order, NaturalComparerOptions.Default, new char[0])\n    {\n    }\n\n    /// <summary>インスタンスを初期化します。</summary>\n    /// <param name=\"order\">ソート方向を表す <see cref=\"NaturalSortOrder\"/>。</param>\n    /// <param name=\"options\">比較方法を表す <see cref=\"NaturalComparerOptions\"/>。</param>\n    /// <param name=\"ignoreCharacter\">無視する文字を表す char[]。</param>\n    public NaturalComparer(NaturalSortOrder order, NaturalComparerOptions options, char[] ignoreCharacter)\n    {\n        this.SortOrder = order;\n        _ignoreCharacter = ignoreCharacter;\n        this.Options = options; // 最後に実行する必要がある\n    }\n\n    #endregion\n\n    #region Property\n\n    /// <summary>ソート方向を取得または設定します。</summary>\n    public virtual NaturalSortOrder SortOrder\n    {\n        get\n        {\n            switch (_order)\n            {\n                case 1:\n                    return NaturalSortOrder.Ascending;\n                case -1:\n                    return NaturalSortOrder.Descending;\n                default:\n                    return NaturalSortOrder.Ascending;\n            }\n        }\n        set\n        {\n            switch (value)\n            {\n                case NaturalSortOrder.Ascending:\n                    _order = 1;\n                    break;\n                case NaturalSortOrder.Descending:\n                    _order = -1;\n                    break;\n                default:\n                    _order = 0;\n                    break;\n            }\n        }\n    }\n\n    /// <summary>自然順の比較オプションを取得または設定します。</summary>\n    public virtual NaturalComparerOptions Options\n    {\n        get { return _options; }\n        set\n        {\n            _options = value;\n            if (this.IgnoreSpace)\n            {\n                _ignoreTable = new char[_ignoreCharacter.Length + 3];\n                _ignoreCharacter.CopyTo(_ignoreTable, 0);\n                _ignoreTable[_ignoreTable.Length - 3] = ' ';\n                _ignoreTable[_ignoreTable.Length - 2] = '　';\n                _ignoreTable[_ignoreTable.Length - 1] = '\\t';\n            }\n            else\n            {\n                _ignoreTable = _ignoreCharacter;\n            }\n        }\n    }\n\n    /// <summary>空白文字の存在を無視するかどうかを取得します。</summary>\n    protected virtual bool IgnoreSpace\n    {\n        get { return ((_options & NaturalComparerOptions.IgnoreSpace) == NaturalComparerOptions.IgnoreSpace); }\n    }\n\n    /// <summary>数字表現の違いを無視するかどうかを取得します。</summary>\n    protected virtual bool IgnoreNumber\n    {\n        get { return ((_options & NaturalComparerOptions.IgnoreNumber) == NaturalComparerOptions.IgnoreNumber); }\n    }\n\n    /// <summary>全角半角の違いを無視するかどうかを取得します。</summary>\n    protected virtual bool IgnoreWide\n    {\n        get { return ((_options & NaturalComparerOptions.IgnoreWide) == NaturalComparerOptions.IgnoreWide); }\n    }\n\n    /// <summary>大文字小文字の違いを無視するかどうかを取得します。</summary>\n    protected virtual bool IgnoreCase\n    {\n        get { return ((_options & NaturalComparerOptions.IgnoreCase) == NaturalComparerOptions.IgnoreCase); }\n    }\n\n    /// <summary>カタカナひらがなの違いを無視するかどうかを取得します。</summary>\n    protected virtual bool IgnoreKana\n    {\n        get { return ((_options & NaturalComparerOptions.IgnoreKana) == NaturalComparerOptions.IgnoreKana); }\n    }\n\n    #endregion\n\n    #region Method\n\n    /// <summary>オブジェクトの大小関係を比較します。</summary>\n    /// <param name=\"s1\">比較対象のオブジェクトを表す string。</param>\n    /// <param name=\"s2\">比較対象のオブジェクトを表す string。</param>\n    /// <returns>\n    /// <list type=\"table\">\n    ///   <item><term>0 より小さい</term><description><paramref name=\"s1\"/> が <paramref name=\"s2\"/> より小さい。</description></item>\n    ///   <item><term>0</term><description><paramref name=\"s1\"/> と <paramref name=\"s2\"/> は等しい。</description></item>\n    ///   <item><term>0 より大きい</term><description><paramref name=\"s1\"/> が <paramref name=\"s2\"/> より大きい。</description></item>\n    /// </list>\n    /// </returns>\n    public int Compare(string s1, string s2)\n    {\n        return LocalCompare(s1, s2) * _order;\n    }\n\n    /// <summary>オブジェクトの大小関係を比較します。</summary>\n    /// <param name=\"s1\">比較対象のオブジェクトを表す object。</param>\n    /// <param name=\"s2\">比較対象のオブジェクトを表す object。</param>\n    /// <returns>\n    /// <list type=\"table\">\n    ///   <item><term>0 より小さい</term><description><paramref name=\"s1\"/> が <paramref name=\"s2\"/> より小さい。</description></item>\n    ///   <item><term>0</term><description><paramref name=\"s1\"/> と <paramref name=\"s2\"/> は等しい。</description></item>\n    ///   <item><term>0 より大きい</term><description><paramref name=\"s1\"/> が <paramref name=\"s2\"/> より大きい。</description></item>\n    /// </list>\n    /// </returns>\n    int IComparer.Compare(object s1, object s2)\n    {\n        return LocalCompare(s1 as string, s2 as string) * _order;\n    }\n\n    /// <summary>オブジェクトの大小関係を比較します。</summary>\n    /// <param name=\"s1\">比較対象のオブジェクトを表す string。</param>\n    /// <param name=\"s2\">比較対象のオブジェクトを表す string。</param>\n    /// <returns>\n    /// <list type=\"table\">\n    ///   <item><term>0 より小さい</term><description><paramref name=\"s1\"/> が <paramref name=\"s2\"/> より小さい。</description></item>\n    ///   <item><term>0</term><description><paramref name=\"s1\"/> と <paramref name=\"s2\"/> は等しい。</description></item>\n    ///   <item><term>0 より大きい</term><description><paramref name=\"s1\"/> が <paramref name=\"s2\"/> より大きい。</description></item>\n    /// </list>\n    /// </returns>\n    protected virtual int LocalCompare(string s1, string s2)\n    {\n        // いずれかが null もしくは空文字であれば比較終了\n        if (string.IsNullOrEmpty(s1))\n        {\n            return string.IsNullOrEmpty(s2) ? 0 : -1;\n        }\n        else if (string.IsNullOrEmpty(s2))\n        {\n            return 1;\n        }\n\n        CharTypes filter = (CharTypes)(_options & NaturalComparerOptions.NumberAll);\n        CharTypes t1 = CharTypes.None;\n        CharTypes t2 = CharTypes.None;\n        int p1 = 0;\n        int p2 = 0;\n        char c1 = char.MinValue;\n        char c2 = char.MinValue;\n\n        s1 = ConvertChar(s1);\n        s2 = ConvertChar(s2);\n\n        // 除外文字を読み飛ばす\n        if (_ignoreTable.Length > 0)\n        {\n            SkipIgnoreCharacter(s1, ref p1);\n            SkipIgnoreCharacter(s2, ref p2);\n        }\n\n        while (p1 < s1.Length && p2 < s2.Length)\n        {\n            t1 = GetCharType(s1[p1], c1, t1) & filter;\n            t2 = GetCharType(s2[p2], c2, t2) & filter;\n            c1 = s1[p1];\n            c2 = s2[p2];\n\n            // 両方とも何らかの数字の場合\n            if ((this.IgnoreNumber || (this.IgnoreNumber == false && t1 == t2)) && t1 != CharTypes.None && t2 != CharTypes.None)\n            {\n                int i1 = p1;\n                int i2 = p2;\n                long v1 = 0;\n                long v2 = 0;\n\n                bool success = GetNumber(s1, t1, ref i1, out v1) && GetNumber(s2, t2, ref i2, out v2);\n                if (success)\n                {\n                    if (v1 < v2)\n                    {\n                        return -1;\n                    }\n                    else if (v1 > v2)\n                    {\n                        return 1;\n                    }\n                    p1 = i1;\n                    p2 = i2;\n                }\n                else\n                {\n                    int diff = CompareChar(s1[p1], s2[p2]);\n                    if (diff != 0)\n                    {\n                        return diff;\n                    }\n                    p1++;\n                    p2++;\n                }\n            }\n            // いずれかが数字の場合\n            else if ((t1 != CharTypes.None || t2 != CharTypes.None) && t1 != CharTypes.RomanNumber && t2 != CharTypes.RomanNumber)\n            {\n                return (t1 != CharTypes.None) ? -1 : 1;\n            }\n            // 数字でない場合は文字コードを比較する\n            else\n            {\n                int diff = CompareChar(s1[p1], s2[p2]);\n                if (diff != 0)\n                {\n                    return diff;\n                }\n                p1++;\n                p2++;\n            }\n\n            // 除外文字を読み飛ばす\n            if (_ignoreTable.Length > 0)\n            {\n                SkipIgnoreCharacter(s1, ref p1);\n                SkipIgnoreCharacter(s2, ref p2);\n            }\n        }\n\n        // 共通部分が一致している場合は、残りの文字列長で大小関係を決める\n        if (p1 >= s1.Length)\n        {\n            return (p2 >= s2.Length) ? 0 : -1;\n        }\n        else\n        {\n            return 1;\n        }\n    }\n\n    /// <summary>除外文字を読み飛ばします。</summary>\n    /// <param name=\"source\">対象の文字列を表す string。</param>\n    /// <param name=\"pos\">開始位置を表す int。</param>\n    private void SkipIgnoreCharacter(string source, ref int pos)\n    {\n        for (; pos < source.Length; pos++)\n        {\n            if (Array.IndexOf<char>(_ignoreTable, source[pos]) == -1)\n            {\n                break;\n            }\n        }\n    }\n\n    /// <summary>文字の種類を取得します。</summary>\n    /// <param name=\"c\">取得対象の文字を表す char。</param>\n    /// <param name=\"back\">直前の文字を表す char。</param>\n    /// <param name=\"state\">直前の文字の種類を表す <see cref=\"CharTypes\"/>。</param>\n    /// <returns>取得した文字の種類を表す <see cref=\"CharTypes\"/>。</returns>\n    private CharTypes GetCharType(char c, char back, CharTypes state)\n    {\n        // ASCIIアラビア数字 (0～9)\n        if (c >= '0' && c <= '9')\n        {\n            return CharTypes.Number;\n        }\n        // 日本語アラビア数字 (０～９)\n        else if (c >= '０' && c <= '９')\n        {\n            return CharTypes.Number;\n        }\n        // 日本語丸数字 (①～⑳)\n        else if (c >= '①' && c <= '⑳')\n        {\n            return CharTypes.CircleNumber;\n        }\n        // ASCII英大文字 (A～Z)\n        else if (c >= 'A' && c <= 'Z')\n        {\n            // ASCIIローマ数字 (I,V,X,L,C,D,M)\n            if (back < 'A' || back > 'Z')\n            {\n                switch (c)\n                {\n                    case 'I':\n                    case 'V':\n                    case 'X':\n                    case 'L':\n                    case 'C':\n                    case 'D':\n                    case 'M':\n                        return CharTypes.RomanNumber;\n                }\n            }\n        }\n        // ASCII英小文字 (a～z)\n        else if (c >= 'a' && c <= 'z')\n        {\n            // ASCIIローマ数字 (i,v,x,l,c,d,m)\n            if ((back < 'A' || back > 'Z') && (back < 'a' || back > 'z'))\n            {\n                switch (c)\n                {\n                    case 'i':\n                    case 'v':\n                    case 'x':\n                    case 'l':\n                    case 'c':\n                    case 'd':\n                    case 'm':\n                        return CharTypes.RomanNumber;\n                }\n            }\n        }\n        // 日本語英大文字 (Ａ～Ｚ)\n        else if (c >= 'Ａ' && c <= 'Ｚ')\n        {\n            // 日本語ローマ数字 (Ｉ,Ｖ,Ｘ,Ｌ,Ｃ,Ｄ,Ｍ)\n            if (back < 'Ａ' || back > 'Ｚ')\n            {\n                switch (c)\n                {\n                    case 'Ｉ':\n                    case 'Ｖ':\n                    case 'Ｘ':\n                    case 'Ｌ':\n                    case 'Ｃ':\n                    case 'Ｄ':\n                    case 'Ｍ':\n                        return CharTypes.RomanNumber;\n                }\n            }\n        }\n        // 日本語英小文字 (ａ～ｚ)\n        else if (c >= 'ａ' && c <= 'ｚ')\n        {\n            // 日本語ローマ数字 (ⅰ,ⅴ,ⅹ,ｌ,ｃ,ｄ,ｍ)\n            if ((back < 'Ａ' || back > 'Ｚ') && (back < 'ａ' || back > 'ｚ'))\n            {\n                switch (c)\n                {\n                    case 'ⅰ':\n                    case 'ⅴ':\n                    case 'ⅹ':\n                    case 'ｌ':\n                    case 'ｃ':\n                    case 'ｄ':\n                    case 'ｍ':\n                        return CharTypes.RomanNumber;\n                }\n            }\n        }\n        // ローマ数字\n        else if (c >= 0x2160 && c <= 0x217F)\n        {\n            return CharTypes.JpRomanNumber;\n        }\n        else\n        {\n            // 日本語漢数字\n            if (state == CharTypes.KanjiNumber)\n            {\n                switch (c)\n                {\n                    case '〇':\n                    case '一':\n                    case '二':\n                    case '三':\n                    case '四':\n                    case '五':\n                    case '六':\n                    case '七':\n                    case '八':\n                    case '九':\n                    case '十':\n                    case '百':\n                    case '千':\n                    case '万':\n                    case '億':\n                    case '兆':\n                    case '京':\n                    case '壱':\n                    case '弐':\n                    case '参':\n                    case '拾':\n                        return CharTypes.KanjiNumber;\n                }\n            }\n            else\n            {\n                switch (c)\n                {\n                    case '〇':\n                    case '一':\n                    case '二':\n                    case '三':\n                    case '四':\n                    case '五':\n                    case '六':\n                    case '七':\n                    case '八':\n                    case '九':\n                    case '十':\n                    case '百':\n                    case '千':\n                    case '壱':\n                    case '弐':\n                    case '参':\n                        return CharTypes.KanjiNumber;\n                }\n            }\n        }\n\n        return CharTypes.None;\n    }\n\n    /// <summary>比較オプションに合わせて文字を変換します。</summary>\n    /// <param name=\"source\">変換する文字を表す string。</param>\n    /// <returns>変換結果の文字を表す string。</returns>\n    private string ConvertChar(string source)\n    {\n        StringBuilder buffer = new StringBuilder(source);\n\n        // 全角半角の違いを無視する\n        if (this.IgnoreWide)\n        {\n            ConvertHalf(buffer);\n        }\n\n        // 大文字小文字の違いを無視する\n        if (this.IgnoreCase)\n        {\n            ConvertUpperCase(buffer);\n        }\n\n        // カタカナひらがなの違いを無視する\n        if (this.IgnoreKana)\n        {\n            ConvertKatakana(buffer);\n        }\n\n        return buffer.ToString();\n    }\n\n    /// <summary>全角を半角へ変換します。</summary>\n    /// <param name=\"source\">変換元の文字列を表す <see cref=\"StringBuilder\"/>。</param>\n    private void ConvertHalf(StringBuilder source)\n    {\n        for (int i = 0; i < source.Length; i++)\n        {\n            if (source[i] >= '！' && source[i] <= '～')\n            {\n                source[i] = (char)(source[i] - '！' + '!');\n            }\n            else\n            {\n                switch (source[i])\n                {\n                    case '、': source[i] = '､'; break;\n                    case '。': source[i] = '｡'; break;\n                    case '〈': source[i] = '<'; break;\n                    case '〉': source[i] = '>'; break;\n                    case '《': source[i] = '<'; break;\n                    case '》': source[i] = '>'; break;\n                    case '「': source[i] = '｢'; break;\n                    case '」': source[i] = '｣'; break;\n                    case '『': source[i] = '｢'; break;\n                    case '』': source[i] = '｣'; break;\n                    case '【': source[i] = '['; break;\n                    case '】': source[i] = ']'; break;\n                    case '〔': source[i] = '['; break;\n                    case '〕': source[i] = ']'; break;\n                }\n            }\n        }\n    }\n\n    /// <summary>小文字を大文字へ変換します。</summary>\n    /// <param name=\"source\">変換元の文字列を表す <see cref=\"StringBuilder\"/>。</param>\n    private void ConvertUpperCase(StringBuilder source)\n    {\n        for (int i = 0; i < source.Length; i++)\n        {\n            if ((source[i] >= 'a' && source[i] <= 'z') && (source[i] >= 'ａ' && source[i] <= 'ｚ'))\n            {\n                source[i] = char.ToUpperInvariant(source[i]);\n            }\n        }\n    }\n\n    /// <summary>ひらがなをカタカナへ変換します。</summary>\n    /// <param name=\"source\">変換元の文字列を表す <see cref=\"StringBuilder\"/>。</param>\n    private void ConvertKatakana(StringBuilder source)\n    {\n        for (int i = 0; i < source.Length; i++)\n        {\n            if (source[i] >= 'ぁ' && source[i] <= 'ゞ')\n            {\n                source[i] = (char)(source[i] + 'ァ' - 'ぁ');\n            }\n            else if (source[i] >= 'ｦ' && source[i] <= 'ﾟ')\n            {\n                bool replaced = false;\n\n                if (i + 1 < source.Length)\n                {\n                    replaced = true;\n\n                    switch (source[i + 1])\n                    {\n                        case 'ﾞ':\n                            switch (source[i])\n                            {\n                                case 'ｶ': source[i] = 'ガ'; break;\n                                case 'ｷ': source[i] = 'ギ'; break;\n                                case 'ｸ': source[i] = 'グ'; break;\n                                case 'ｹ': source[i] = 'ゲ'; break;\n                                case 'ｺ': source[i] = 'ゴ'; break;\n                                case 'ｻ': source[i] = 'ザ'; break;\n                                case 'ｼ': source[i] = 'ジ'; break;\n                                case 'ｽ': source[i] = 'ズ'; break;\n                                case 'ｾ': source[i] = 'ゼ'; break;\n                                case 'ｿ': source[i] = 'ゾ'; break;\n                                case 'ﾀ': source[i] = 'ダ'; break;\n                                case 'ﾁ': source[i] = 'ヂ'; break;\n                                case 'ﾂ': source[i] = 'ヅ'; break;\n                                case 'ﾃ': source[i] = 'デ'; break;\n                                case 'ﾄ': source[i] = 'ド'; break;\n                                case 'ﾊ': source[i] = 'バ'; break;\n                                case 'ﾋ': source[i] = 'ビ'; break;\n                                case 'ﾌ': source[i] = 'ブ'; break;\n                                case 'ﾍ': source[i] = 'ベ'; break;\n                                case 'ﾎ': source[i] = 'ボ'; break;\n                                case 'ｳ': source[i] = 'ヴ'; break;\n                                default: replaced = false; break;\n                            }\n                            break;\n                        case 'ﾟ':\n                            switch (source[i])\n                            {\n                                case 'ﾊ': source[i] = 'パ'; break;\n                                case 'ﾋ': source[i] = 'ピ'; break;\n                                case 'ﾌ': source[i] = 'プ'; break;\n                                case 'ﾍ': source[i] = 'ペ'; break;\n                                case 'ﾎ': source[i] = 'ポ'; break;\n                                default: replaced = false; break;\n                            }\n                            break;\n                        default:\n                            replaced = false;\n                            break;\n                    }\n\n                    if (replaced)\n                    {\n                        source.Remove(i + 1, 1);\n                    }\n                }\n\n                if (replaced == false)\n                {\n                    switch (source[i])\n                    {\n                        case 'ｦ': source[i] = 'ヲ'; break;\n                        case 'ｧ': source[i] = 'ァ'; break;\n                        case 'ｨ': source[i] = 'ィ'; break;\n                        case 'ｩ': source[i] = 'ゥ'; break;\n                        case 'ｪ': source[i] = 'ェ'; break;\n                        case 'ｫ': source[i] = 'ォ'; break;\n                        case 'ｬ': source[i] = 'ャ'; break;\n                        case 'ｭ': source[i] = 'ュ'; break;\n                        case 'ｮ': source[i] = 'ョ'; break;\n                        case 'ｯ': source[i] = 'ッ'; break;\n                        case 'ｰ': source[i] = 'ー'; break;\n                        case 'ｱ': source[i] = 'ア'; break;\n                        case 'ｲ': source[i] = 'イ'; break;\n                        case 'ｳ': source[i] = 'ウ'; break;\n                        case 'ｴ': source[i] = 'エ'; break;\n                        case 'ｵ': source[i] = 'オ'; break;\n                        case 'ｶ': source[i] = 'カ'; break;\n                        case 'ｷ': source[i] = 'キ'; break;\n                        case 'ｸ': source[i] = 'ク'; break;\n                        case 'ｹ': source[i] = 'ケ'; break;\n                        case 'ｺ': source[i] = 'コ'; break;\n                        case 'ｻ': source[i] = 'サ'; break;\n                        case 'ｼ': source[i] = 'シ'; break;\n                        case 'ｽ': source[i] = 'ス'; break;\n                        case 'ｾ': source[i] = 'セ'; break;\n                        case 'ｿ': source[i] = 'ソ'; break;\n                        case 'ﾀ': source[i] = 'タ'; break;\n                        case 'ﾁ': source[i] = 'チ'; break;\n                        case 'ﾂ': source[i] = 'ツ'; break;\n                        case 'ﾃ': source[i] = 'テ'; break;\n                        case 'ﾄ': source[i] = 'ト'; break;\n                        case 'ﾅ': source[i] = 'ナ'; break;\n                        case 'ﾆ': source[i] = 'ニ'; break;\n                        case 'ﾇ': source[i] = 'ヌ'; break;\n                        case 'ﾈ': source[i] = 'ネ'; break;\n                        case 'ﾉ': source[i] = 'ノ'; break;\n                        case 'ﾊ': source[i] = 'ハ'; break;\n                        case 'ﾋ': source[i] = 'ヒ'; break;\n                        case 'ﾌ': source[i] = 'フ'; break;\n                        case 'ﾍ': source[i] = 'ヘ'; break;\n                        case 'ﾎ': source[i] = 'ホ'; break;\n                        case 'ﾏ': source[i] = 'マ'; break;\n                        case 'ﾐ': source[i] = 'ミ'; break;\n                        case 'ﾑ': source[i] = 'ム'; break;\n                        case 'ﾒ': source[i] = 'メ'; break;\n                        case 'ﾓ': source[i] = 'モ'; break;\n                        case 'ﾔ': source[i] = 'ヤ'; break;\n                        case 'ﾕ': source[i] = 'ユ'; break;\n                        case 'ﾖ': source[i] = 'ヨ'; break;\n                        case 'ﾗ': source[i] = 'ラ'; break;\n                        case 'ﾘ': source[i] = 'リ'; break;\n                        case 'ﾙ': source[i] = 'ル'; break;\n                        case 'ﾚ': source[i] = 'レ'; break;\n                        case 'ﾛ': source[i] = 'ロ'; break;\n                        case 'ﾜ': source[i] = 'ワ'; break;\n                        case 'ﾝ': source[i] = 'ン'; break;\n                        case 'ﾞ': source[i] = '゛'; break;\n                        case 'ﾟ': source[i] = '゜'; break;\n                    }\n                }\n            }\n        }\n    }\n\n    /// <summary>文字列内の数値を取得します。</summary>\n    /// <param name=\"source\">対象の文字列を表す string。</param>\n    /// <param name=\"type\">開始文字の種類を表す <see cref=\"CharTypes\"/>。</param>\n    /// <param name=\"pos\">開始位置を表す int。</param>\n    /// <param name=\"value\">取得した数値を表す long。</param>\n    /// <returns>数値を取得出来た場合は <see langword=\"true\"/>、それ以外の場合は <see langword=\"false\"/>。</returns>\n    private bool GetNumber(string source, CharTypes type, ref int pos, out long value)\n    {\n        INumberComverter number = null;\n\n        switch (type)\n        {\n            case CharTypes.Number: number = new NumberConverter(source[pos]); break;\n            case CharTypes.RomanNumber: number = new RomanNumberConverter(source[pos]); break;\n            case CharTypes.JpRomanNumber: number = new JpRomanNumberConverter(source[pos]); break;\n            case CharTypes.CircleNumber: number = new CircleNumberConverter(source[pos]); break;\n            case CharTypes.KanjiNumber: number = new KanjiNumberConverter(source[pos]); break;\n        }\n\n        for (int i = pos + 1; i < source.Length; i++)\n        {\n            if (number.AddChar(source[i]) == false)\n            {\n                break;\n            }\n        }\n\n        if (number.IsError == false)\n        {\n            value = number.Value;\n            pos += number.Length;\n        }\n        else\n        {\n            value = 0;\n        }\n\n        return (number.IsError == false);\n    }\n\n    /// <summary>2つの文字コードを比較します。</summary>\n    /// <param name=\"c1\">比較する文字を表す char。</param>\n    /// <param name=\"c2\">比較する文字を表す char。</param>\n    /// <returns>2つの文字コードの大小関係を表す int。</returns>\n    private int CompareChar(char c1, char c2)\n    {\n        // 前中後、上中下の整列を考慮する\n        string list = \"上前中下後\";\n        int p1 = list.IndexOf(c1);\n        int p2 = list.IndexOf(c2);\n\n        if (p1 >= 0 && p2 >= 0)\n        {\n            return p1 - p2;\n        }\n\n        return StringComparer.CurrentCulture.Compare(c1.ToString(), c2.ToString());\n    }\n\n    #endregion\n\n    #region INumberComverter\n\n    /// <summary>数字を数値へ変換する機能を提供します。</summary>\n    private interface INumberComverter\n    {\n        #region Property\n\n        /// <summary>エラーが発生したかどうかを取得します。</summary>\n        bool IsError { get; }\n\n        /// <summary>数字から変換した数値を取得します。</summary>\n        long Value { get; }\n\n        /// <summary>数値全体の文字数を取得します。</summary>\n        int Length { get; }\n\n        #endregion\n\n        #region Method\n\n        /// <summary>数字を追加します。</summary>\n        /// <param name=\"number\">数字を表す char。</param>\n        /// <returns>数字として成立する場合は <see langword=\"true\"/>、それ以外の場合は <see langword=\"false\"/>。</returns>\n        bool AddChar(char number);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region NumberConverter\n\n    /// <summary>アラビア数字を数値へ変換する機能を提供します。</summary>\n    /// <remarks>ASCIIと日本語の混在は許しません。</remarks>\n    private class NumberConverter : INumberComverter\n    {\n        #region Field\n\n        /// <summary>数値全体の長さを表す int。</summary>\n        private int _length;\n        /// <summary>アラビア数字の 0 を表す char。</summary>\n        private char _numberZero;\n        /// <summary>アラビア数字の 9 を表す char。</summary>\n        private char _numberNine;\n        /// <summary>変換結果の数値を表す long。</summary>\n        private long _value;\n        /// <summary>カンマ区切りの数値かどうかを表す bool。</summary>\n        private bool _isComma;\n        /// <summary>先頭から連続したアラビア数字の文字数を表す int。</summary>\n        private int _numberCount;\n        /// <summary>カンマ区切り以降のアラビア数字の文字数を表す int。</summary>\n        private int _commaLength;\n\n        #endregion\n\n        #region Constructor\n\n        /// <summary>インスタンスを初期化します。</summary>\n        /// <param name=\"number\">１文字目の数字を表す char。</param>\n        public NumberConverter(char number)\n        {\n            if (number >= '0' && number <= '9')\n            {\n                _numberZero = '0';\n                _numberNine = '9';\n            }\n            else\n            {\n                _numberZero = '０';\n                _numberNine = '９';\n            }\n\n            _length = 1;\n            _value = number - _numberZero;\n            _isComma = false;\n        }\n\n        #endregion\n\n        #region Property\n\n        /// <summary>エラーが発生したかどうかを取得します。</summary>\n        public bool IsError\n        {\n            get { return false; }\n        }\n\n        /// <summary>数字から変換した数値を取得します。</summary>\n        public long Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>数値全体の文字数を取得します。</summary>\n        public int Length\n        {\n            get { return _length; }\n        }\n\n        #endregion\n\n        #region Method\n\n        /// <summary>数字を追加します。</summary>\n        /// <param name=\"number\">数字を表す char。</param>\n        /// <returns>数字として成立する場合は <see langword=\"true\"/>、それ以外の場合は <see langword=\"false\"/>。</returns>\n        public bool AddChar(char number)\n        {\n            // 1文字目の数字と同種のアラビア数字かどうか\n            if (number >= _numberZero && number <= _numberNine)\n            {\n                if (_isComma)\n                {\n                    _commaLength++;\n                    if (_commaLength > 3)\n                    {\n                        _length = _numberCount;\n                        return false;\n                    }\n                }\n                else\n                {\n                    _numberCount++;\n                }\n\n                _value = _value * 10 + (number - _numberZero);\n            }\n            // 3桁区切りのカンマかどうか\n            else if (_numberZero - number == 4)\n            {\n                if (_isComma == false && _numberCount > 3)\n                {\n                    return false;\n                }\n                _commaLength = 0;\n            }\n            // アラビア数字以外の文字が見つかったら終了\n            else\n            {\n                return false;\n            }\n\n            _length++;\n            return true;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region RomanNumberConverter\n\n    /// <summary>英字表現のローマ数字を数値へ変換する機能を提供します。</summary>\n    /// <remarks>大文字と小文字、ASCIIと日本語の混在は許しません。</remarks>\n    private class RomanNumberConverter : INumberComverter\n    {\n        #region Field\n\n        /// <summary>数値全体の長さを表す int。</summary>\n        private int _length;\n        /// <summary>アルファベットの A を表す char。</summary>\n        private char _alphaA;\n        /// <summary>未確定の数字を表す long。</summary>\n        private long _number;\n        /// <summary>変換結果の数値を表す long。</summary>\n        private long _value;\n        /// <summary>現在単位を表す long。</summary>\n        private long _max;\n        /// <summary>エラーが発生したかどうかを表す bool。</summary>\n        private bool _isError;\n\n        #endregion\n\n        #region Constructor\n\n        /// <summary>インスタンスを初期化します。</summary>\n        /// <param name=\"alpha\">１文字目の英字を表す char。</param>\n        public RomanNumberConverter(char alpha)\n        {\n            if (alpha >= 'A' && alpha <= 'Z')\n            {\n                _alphaA = 'A';\n            }\n            else if (alpha >= 'a' && alpha <= 'z')\n            {\n                _alphaA = 'a';\n            }\n            else if (alpha >= 'Ａ' && alpha <= 'Ｚ')\n            {\n                _alphaA = 'Ａ';\n            }\n            else if (alpha >= 'ａ' && alpha <= 'ｚ')\n            {\n                _alphaA = 'ａ';\n            }\n\n            _length = 1;\n            _number = Parse(alpha);\n            _max = _number;\n        }\n\n        #endregion\n\n        #region Property\n\n        /// <summary>エラーが発生したかどうかを取得します。</summary>\n        public bool IsError\n        {\n            get { return _isError; }\n        }\n\n        /// <summary>数字から変換した数値を取得します。</summary>\n        public long Value\n        {\n            get { return _value + _number; }\n        }\n\n        /// <summary>数値全体の文字数を取得します。</summary>\n        public int Length\n        {\n            get { return _length; }\n        }\n\n        #endregion\n\n        #region Method\n\n        /// <summary>ローマ数字を追加します。</summary>\n        /// <param name=\"roman\">ローマ数字を表す char。</param>\n        /// <returns>数字として成立する場合は <see langword=\"true\"/>、それ以外の場合は <see langword=\"false\"/>。</returns>\n        public bool AddChar(char roman)\n        {\n            long value = Parse(roman);\n\n            // ローマ数字以外の文字が見つかったら終了\n            if (value == 0)\n            {\n                _isError = IsAlpha(roman);\n                return false;\n            }\n            // IV IX などの減算則表記\n            else if (value > _max)\n            {\n                long mag = value / _max;\n                if (mag == 5 || mag == 10)\n                {\n                    _value += value - _number;\n                    _number = 0;\n                    _max = _max / 2;\n                }\n                else\n                {\n                    _isError = IsAlpha(roman);\n                    return false;\n                }\n            }\n            // VI XI など加算則表記\n            else if (value < _max)\n            {\n                _value += _number;\n                _number = value;\n                _max = value;\n            }\n            // II XX など同じ数字の繰り返し\n            else\n            {\n                _number += value;\n            }\n\n            _length++;\n            return true;\n        }\n\n        /// <summary>ローマ数字を数値へ変換します。</summary>\n        /// <param name=\"alpha\">1 文字のローマ数字を表す char。</param>\n        /// <returns>変換後の数値を表す long。</returns>\n        protected long Parse(char alpha)\n        {\n            switch (alpha - _alphaA)\n            {\n                case 08: return 1;      // I\n                case 21: return 5;      // V\n                case 23: return 10;     // X\n                case 11: return 50;     // L\n                case 02: return 100;    // C\n                case 03: return 500;    // D\n                case 12: return 1000;   // M\n            }\n\n            return 0;\n        }\n\n        /// <summary>指定の文字が英字かどうかを判定します。</summary>\n        /// <param name=\"alpha\">検査対象の文字を表す char。</param>\n        /// <returns>指定の文字が英字だった場合は <see langword=\"true\"/>、それ以外の場合は <see langword=\"false\"/>。</returns>\n        protected bool IsAlpha(char alpha)\n        {\n            return ((alpha >= 'A' && alpha <= 'Z') || (alpha >= 'a' && alpha <= 'z') || (alpha >= 'Ａ' && alpha <= 'Ｚ') || (alpha >= 'ａ' && alpha <= 'ｚ'));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region JpRomanNumberConverter\n\n    /// <summary>全角ローマ数字を数値へ変換する機能を提供します。</summary>\n    private class JpRomanNumberConverter : INumberComverter\n    {\n        #region Field\n\n        /// <summary>数値全体の長さを表す int。</summary>\n        private int _length;\n        /// <summary>2文字以上の組み合わせが可能かどうかを表す bool。</summary>\n        private bool _isMultiChar;\n        /// <summary>ローマ数字の 1 を表す char。</summary>\n        private char _romanOne;\n        /// <summary>未確定の数字を表す long。</summary>\n        private long _number;\n        /// <summary>変換結果の数値を表す long。</summary>\n        private long _value;\n        /// <summary>現在単位を表す long。</summary>\n        private long _max;\n\n        #endregion\n\n        #region Constructor\n\n        /// <summary>インスタンスを初期化します。</summary>\n        /// <param name=\"roman\">１文字目のローマ数字を表す char。</param>\n        public JpRomanNumberConverter(char roman)\n        {\n            _length = 1;\n\n            // 全角ローマ数字(Ⅰ～XII,L,C,D,M)\n            if (roman >= 0x2160 && roman <= 0x216F)\n            {\n                _romanOne = (char)0x2160;\n            }\n            // 全角ローマ数字(ⅰ～xii,l,c,d,m)\n            else if (roman >= 0x2170 && roman <= 0x217F)\n            {\n                _romanOne = (char)0x2170;\n            }\n\n            long value = Parse(roman);\n            if (value == 0)\n            {\n                _value = roman - _romanOne + 1;\n                _isMultiChar = false;\n            }\n            else\n            {\n                _number = value;\n                _max = _number;\n                _isMultiChar = true;\n            }\n        }\n\n        #endregion\n\n        #region Property\n\n        /// <summary>エラーが発生したかどうかを取得します。</summary>\n        public bool IsError\n        {\n            get { return false; }\n        }\n\n        /// <summary>数字から変換した数値を取得します。</summary>\n        public long Value\n        {\n            get { return _value + _number; }\n        }\n\n        /// <summary>数値全体の文字数を取得します。</summary>\n        public int Length\n        {\n            get { return _length; }\n        }\n\n        #endregion\n\n        #region Method\n\n        /// <summary>数字を追加します。</summary>\n        /// <param name=\"roman\">数字を表す char。</param>\n        /// <returns>数字として成立する場合は <see langword=\"true\"/>、それ以外の場合は <see langword=\"false\"/>。</returns>\n        public bool AddChar(char roman)\n        {\n            if (_isMultiChar == false)\n            {\n                return false;\n            }\n\n            long value = Parse(roman);\n\n            // ローマ数字以外の文字が見つかったら終了\n            if (value == 0)\n            {\n                return false;\n            }\n            // IV IX などの減算則表記\n            else if (value > _max)\n            {\n                long mag = value / _max;\n                if (mag == 5 || mag == 10)\n                {\n                    _value += value - _number;\n                    _number = 0;\n                    _max = _max / 2;\n                }\n                else\n                {\n                    return false;\n                }\n            }\n            // VI XI など加算則表記\n            else if (value < _max)\n            {\n                _value += _number;\n                _number = value;\n                _max = value;\n            }\n            // II XX など同じ数字の繰り返し\n            else\n            {\n                _number += value;\n            }\n\n            _length++;\n            return true;\n        }\n\n        /// <summary>ローマ数字を数値へ変換します。</summary>\n        /// <param name=\"roman\">1 文字のローマ数字を表す char。</param>\n        /// <returns>変換後の数値を表す long。</returns>\n        protected long Parse(char roman)\n        {\n            switch (roman - _romanOne)\n            {\n                case 0x0: return 1;     // I\n                case 0x4: return 5;     // V\n                case 0x9: return 10;    // X\n                case 0xC: return 50;    // L\n                case 0xD: return 100;   // C\n                case 0xE: return 500;   // D\n                case 0xF: return 1000;  // M\n            }\n\n            return 0;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region CircleNumberConverter\n\n    /// <summary>丸数字を数値へ変換する機能を提供します。</summary>\n    private class CircleNumberConverter : INumberComverter\n    {\n        #region Field\n\n        /// <summary>現在の数字を表す long。</summary>\n        private long _number;\n\n        #endregion\n\n        #region Constructor\n\n        /// <summary>インスタンスを初期化します。</summary>\n        /// <param name=\"number\">１文字目の数字を表す char。</param>\n        public CircleNumberConverter(char number)\n        {\n            // ①～⑳\n            if (number >= 0x2460 && number <= 0x2473)\n            {\n                _number = number - 0x2460 + 1;\n            }\n            // (1)～(12)\n            else if (number >= 0x2474 && number <= 0x2487)\n            {\n                _number = number - 0x2474 + 1;\n            }\n            // 1.～20.\n            else if (number >= 0x2488 && number <= 0x249B)\n            {\n                _number = number - 0x2488 + 1;\n            }\n            // 丸付き21～35\n            else if (number >= 0x3251 && number <= 0x325F)\n            {\n                _number = number - 0x3251 + 21;\n            }\n            // {一}～{十}\n            else if (number >= 0x3220 && number <= 0x3229)\n            {\n                _number = number - 0x3220 + 1;\n            }\n            // 丸付き一～十\n            else if (number >= 0x3280 && number <= 0x3289)\n            {\n                _number = number - 0x3280 + 1;\n            }\n        }\n\n        #endregion\n\n        #region Property\n\n        /// <summary>エラーが発生したかどうかを取得します。</summary>\n        public bool IsError\n        {\n            get { return false; }\n        }\n\n        /// <summary>数字から変換した数値を取得します。</summary>\n        public long Value\n        {\n            get { return _number; }\n        }\n\n        /// <summary>数値全体の文字数を取得します。</summary>\n        public int Length\n        {\n            get { return 1; }\n        }\n\n        #endregion\n\n        #region Method\n\n        /// <summary>数字を追加します。</summary>\n        /// <param name=\"number\">数字を表す char。</param>\n        /// <returns>数字として成立する場合は <see langword=\"true\"/>、それ以外の場合は <see langword=\"false\"/>。</returns>\n        public bool AddChar(char number)\n        {\n            return false;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region KanjiNumberConverter\n\n    /// <summary>漢数字を数値へ変換する機能を提供します。</summary>\n    private class KanjiNumberConverter : INumberComverter\n    {\n        #region Field\n\n        /// <summary>数値全体の長さを表す int。</summary>\n        private int _length;\n        /// <summary>位取り記数法かどうかを表す bool。</summary>\n        private bool _isNumeral;\n        /// <summary>直前の数字を表す long。</summary>\n        private long _number;\n        /// <summary>1万未満の数値を表す long。</summary>\n        private long _value1;\n        /// <summary>変換結果の数値を表す long。</summary>\n        private long _value2;\n        /// <summary>1万未満の現在単位を表す long。</summary>\n        private long _unit1;\n        /// <summary>数値全体の現在単位を表す long。</summary>\n        private long _unit2;\n\n        #endregion\n\n        #region Constructor\n\n        /// <summary>インスタンスを初期化します。</summary>\n        /// <param name=\"number\">１文字目の数字を表す char。</param>\n        public KanjiNumberConverter(char number)\n        {\n            _length = 1;\n            long temp = Parse(number);\n            if (temp < 10)\n            {\n                _number = temp;\n                _unit1 = 9999;\n                _unit2 = 99999999999999999;\n            }\n            else\n            {\n                _value1 = _unit1 = temp;\n            }\n        }\n\n        #endregion\n\n        #region Property\n\n        /// <summary>エラーが発生したかどうかを取得します。</summary>\n        public bool IsError\n        {\n            get { return false; }\n        }\n\n        /// <summary>数字から変換した数値を取得します。</summary>\n        public long Value\n        {\n            get { return _value2 + _value1 + _number; }\n        }\n\n        /// <summary>数値全体の文字数を取得します。</summary>\n        public int Length\n        {\n            get { return _length; }\n        }\n\n        #endregion\n\n        #region Method\n\n        /// <summary>数字を追加します。</summary>\n        /// <param name=\"kanji\">数字を表す char。</param>\n        /// <returns>数字として成立する場合は <see langword=\"true\"/>、それ以外の場合は <see langword=\"false\"/>。</returns>\n        public bool AddChar(char kanji)\n        {\n            long value = Parse(kanji);\n\n            // 2文字目の内容で位取り記数法かどうかを決定する\n            if (_length == 1)\n            {\n                _isNumeral = (_number + _value1 < 10 && value < 10);\n                if (_isNumeral)\n                {\n                    _value2 = _number;\n                    _number = 0;\n                }\n            }\n\n            if (value < 0)\n            {\n                return false;\n            }\n\n            if (_isNumeral)\n            {\n                if (value > 10)\n                {\n                    return false;\n                }\n\n                _value2 = _value2 * 10 + value;\n                _length++;\n                return true;\n            }\n            else\n            {\n                if (value < 10)\n                {\n                    // 9以下の漢数字が連続したらエラー\n                    if (_number > 0)\n                    {\n                        return false;\n                    }\n\n                    _number = value;\n                }\n                else if (value <= 1000)\n                {\n                    // 前方より大きな単位が出現したらエラー\n                    if (_unit1 <= value)\n                    {\n                        return false;\n                    }\n\n                    _value1 += _number * value;\n                    _number = 0;\n                    _unit1 = value;\n                }\n                else\n                {\n                    // 前方より大きな単位が出現したらエラー\n                    if (_unit2 <= value)\n                    {\n                        return false;\n                    }\n\n                    _value2 += (_value1 + _number) * value;\n                    _value1 = _number = 0;\n                    _unit1 = 9999;\n                    _unit2 = value;\n                }\n\n                _length++;\n                return true;\n            }\n        }\n\n        /// <summary>漢数字を数値へ変換します。</summary>\n        /// <param name=\"kanji\">漢数字を表す char。</param>\n        /// <returns>変換後の数値を表す long。</returns>\n        protected long Parse(char kanji)\n        {\n            switch (kanji)\n            {\n                case '〇': return 0;\n                case '一': return 1;\n                case '二': return 2;\n                case '三': return 3;\n                case '四': return 4;\n                case '五': return 5;\n                case '六': return 6;\n                case '七': return 7;\n                case '八': return 8;\n                case '九': return 9;\n                case '十': return 10;\n                case '百': return 100;\n                case '千': return 1000;\n                case '万': return 10000;\n                case '億': return 100000000;\n                case '兆': return 1000000000000;\n                case '京': return 10000000000000000;\n                case '零': return 0;\n                case '壱': return 1;\n                case '弐': return 2;\n                case '参': return 3;\n                case '拾': return 10;\n            }\n\n            return -1;\n        }\n\n        #endregion\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "SettingsView/Pages/PickerPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:sv=\"clr-namespace:AiForms.Settings\"\n    xmlns:model=\"clr-namespace:AiForms.Settings.Pages\"\n    x:Class=\"AiForms.Settings.Pages.PickerPage\"\n    NavigationPage.BackButtonTitle=\"\">\n\n    <sv:SettingsView x:Name=\"settingsView\">\n\n        <sv:Section ItemsSource=\"{Binding ItemsSource}\">\n            <sv:Section.ItemTemplate>\n                <DataTemplate x:DataType=\"model:DisplayValue\">\n                    <sv:SimpleCheckCell\n                        Title=\"{Binding Display}\"\n                        Description=\"{Binding SubDisplay}\"\n                        Checked=\"{Binding IsSelected}\" />\n                </DataTemplate>\n            </sv:Section.ItemTemplate>\n        </sv:Section>\n\n    </sv:SettingsView>\n\n</ContentPage>\n\n"
  },
  {
    "path": "SettingsView/Pages/PickerPage.xaml.cs",
    "content": "﻿using Microsoft.Maui;\nusing System.Collections;\nusing System.Runtime.InteropServices;\n\nnamespace AiForms.Settings.Pages;\n\npublic partial class PickerPage : ContentPage\n{\n    public List<DisplayValue> ItemsSource { get; } = new List<DisplayValue>();\n\n    PickerCell _pickerCell;\n    SettingsView _parent;\n    HashSet<DisplayValue> _selectedCache = new HashSet<DisplayValue>();\n\n    public PickerPage(PickerCell cell)\n    {\n        InitializeComponent();\n\n        settingsView.Model.RowSelected += Model_RowSelected;    \n\n        _pickerCell = cell;\n        _parent = _pickerCell.Parent as SettingsView;\n\n        SetUpProperties();\n\n        foreach (var item in _pickerCell.ItemsSource)\n        {\n            var isSelected = _pickerCell.SelectedItems.IndexOf(item) >= 0;           \n            var displayValue = new DisplayValue($\"{_pickerCell.DisplayValue(item)}\", $\"{_pickerCell.SubDisplayValue(item)}\", isSelected, item);\n            ItemsSource.Add(displayValue);\n\n            if (isSelected)\n            {\n                _selectedCache.Add(displayValue);\n            }\n        }\n\n        BindingContext = this;\n    }\n\n    private void Model_RowSelected(CellBase cell)\n    {\n        UpdateSelected(cell.BindingContext as DisplayValue);\n    }\n\n    void SetUpProperties()\n    {\n        Title = _pickerCell.Title;\n        settingsView.SeparatorColor = _parent.SeparatorColor;\n        settingsView.BackgroundColor = _parent.BackgroundColor;\n        settingsView.SelectedColor = _parent.SelectedColor;\n\n        if (_pickerCell.AccentColor.IsNotDefault())\n        {\n            settingsView.CellAccentColor = _pickerCell.AccentColor;\n        }\n        else if (_parent.CellAccentColor.IsNotDefault())\n        {\n            settingsView.CellAccentColor = _parent.CellAccentColor;\n        }\n\n        if (_pickerCell.TitleColor.IsNotDefault())\n        {\n            settingsView.CellTitleColor = _pickerCell.TitleColor;\n        }\n        else if (_parent != null && _parent.CellTitleColor.IsNotDefault())\n        {\n            settingsView.CellTitleColor = _parent.CellTitleColor;\n        }\n\n        if (_pickerCell.TitleFontSize > 0)\n        {\n            settingsView.CellTitleFontSize = _pickerCell.TitleFontSize;\n        }\n        else if (_parent != null)\n        {\n            settingsView.CellTitleFontSize = _parent.CellTitleFontSize;\n        }\n\n        if (_pickerCell.DescriptionColor.IsNotDefault())\n        {\n            settingsView.CellDescriptionColor = _pickerCell.DescriptionColor;\n        }\n        else if (_parent != null && _parent.CellDescriptionColor.IsNotDefault())\n        {\n            settingsView.CellDescriptionColor = _parent.CellDescriptionColor;\n        }\n\n        if (_pickerCell.DescriptionFontSize > 0)\n        {\n            settingsView.CellDescriptionFontSize = _pickerCell.DescriptionFontSize;\n        }\n        else if (_parent != null)\n        {\n            settingsView.CellDescriptionFontSize = _parent.CellDescriptionFontSize;\n        }\n\n        if (_pickerCell.BackgroundColor.IsNotDefault())\n        {\n            settingsView.CellBackgroundColor = _pickerCell.BackgroundColor;\n        }\n        else if (_parent != null && _parent.CellBackgroundColor.IsNotDefault())\n        {\n            settingsView.CellBackgroundColor = _parent.CellBackgroundColor;\n        }\n\n        if(_pickerCell.SelectedItems == null)\n        {\n            _pickerCell.SelectedItems = new ArrayList();\n            if (_pickerCell.SelectedItem != null)\n            {\n                _pickerCell.SelectedItems.Add(_pickerCell.SelectedItem);\n            }\n        }\n    }\n\n    protected override void OnDisappearing()\n    {\n        base.OnDisappearing();\n\n        if (settingsView?.Model != null)\n        {\n            settingsView.Model.RowSelected -= Model_RowSelected;\n        }\n\n        if (_pickerCell == null || _selectedCache == null || _pickerCell.SelectedItems == null)\n        {\n            return;\n        }\n\n        _pickerCell.SelectedItems.Clear();\n\n        foreach(var item in _selectedCache)\n        {\n            _pickerCell.SelectedItems.Add(item.Value);\n        }\n\n        _pickerCell.SelectedItem = _selectedCache.FirstOrDefault()?.Value;\n\n        _pickerCell.InvokeCommand();\n\n        _parent = null;\n        _pickerCell = null;\n        _selectedCache = null;\n    } \n\n    void UpdateSelected(DisplayValue item)\n    {\n        if(_pickerCell.MaxSelectedNumber == 1)\n        {\n            SelectedSingle(item);\n            DoPickToClose();\n        }\n        else\n        {\n            SelectedMulti(item);\n        }\n    }\n\n    void SelectedSingle(DisplayValue item)\n    {\n        if (_selectedCache.Contains(item))\n        {\n            return;\n        }\n\n        foreach(var dv in ItemsSource)\n        {\n            dv.IsSelected = false;\n        }\n\n        item.IsSelected = true;\n\n        _selectedCache.Clear();\n        _selectedCache.Add(item);\n    }\n\n    void SelectedMulti(DisplayValue item)\n    {\n        if (_selectedCache.Contains(item))\n        {\n            item.IsSelected = false;\n            _selectedCache.Remove(item);\n            return;\n        }\n\n        if(_pickerCell.MaxSelectedNumber != 0 && _selectedCache.Count() >= _pickerCell.MaxSelectedNumber)\n        {\n            return;\n        }\n\n        item.IsSelected = true;\n        _selectedCache.Add(item);\n\n        DoPickToClose();\n    }\n\n    void DoPickToClose()\n    {\n        if(_pickerCell.UsePickToClose && _selectedCache.Count == _pickerCell.MaxSelectedNumber)\n        {\n            Navigation.PopAsync(true);\n        }\n    }\n}\n\npublic class DisplayValue : BindableBase\n{\n    \n    public object Value { get; set; }\n\n    private string _Display;\n    public string Display\n    {\n        get => _Display;\n        set => SetProperty(ref _Display, value);\n    }\n\n    private string _SubDisplay;\n    public string SubDisplay\n    {\n        get => _SubDisplay;\n        set => SetProperty(ref _SubDisplay, value);\n    }\n\n\n    private bool _IsSelected;\n    public bool IsSelected\n    {\n        get => _IsSelected;\n        set => SetProperty(ref _IsSelected, value);\n    }\n\n    public DisplayValue(string display, string subDisplay, bool selected, object value)\n    {\n        Display = display;\n        SubDisplay = subDisplay;\n        IsSelected = selected;\n        Value = value;\n    }\n}\n"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/drawable/divider.xml",
    "content": "﻿<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <size android:height=\"1px\" />\n    <solid android:color=\"@color/material_grey_50\" />\n</shape>"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/drawable/ic_navigate_next.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"18dp\"\n    android:height=\"26dp\"\n    android:viewportWidth=\"18\"\n    android:viewportHeight=\"26\">\n  <path\n      android:fillColor=\"#FFCACACA\"\n      android:pathData=\"M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z\"/>\n</vector>\n"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/layout/cellbaseview.axml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/CellLayout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:minHeight=\"44dp\"\n    android:paddingLeft=\"10dp\"\n    android:paddingRight=\"10dp\"\n    android:paddingTop=\"4dp\"\n    android:paddingBottom=\"4dp\">\n    <ImageView\n        android:id=\"@+id/CellIcon\"\n        android:scaleType=\"fitXY\"\n        android:layout_centerVertical=\"true\"\n        android:layout_alignParentLeft=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginLeft=\"2dp\"\n        android:layout_marginRight=\"12dp\" />\n    <LinearLayout\n        android:id=\"@+id/CellBody\"\n        android:orientation=\"vertical\"\n        android:layout_toRightOf=\"@+id/CellIcon\"\n        android:layout_toLeftOf=\"@+id/CellAccessoryView\"\n        android:layout_centerVertical=\"true\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:paddingLeft=\"4dp\">\n        <LinearLayout\n            android:id=\"@+id/CellContentStack\"\n            android:orientation=\"horizontal\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:gravity=\"center_vertical\"\n            android:weightSum=\"1\">\n            <TextView\n                android:id=\"@+id/CellTitle\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:singleLine=\"true\"\n                android:ellipsize=\"end\"\n                android:gravity=\"left\"\n                android:paddingRight=\"6dp\"\n                android:layout_gravity=\"left|center_vertical\" />\n        </LinearLayout>\n        <TextView\n            android:id=\"@+id/CellDescription\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:gravity=\"left\"\n            android:layout_gravity=\"left\"\n            android:layout_marginTop=\"2dp\" />\n    </LinearLayout>\n    <LinearLayout\n        android:id=\"@+id/CellAccessoryView\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_centerVertical=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center_vertical\" />\n    <TextView\n        android:id=\"@+id/CellHintText\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_alignParentTop=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"right\"\n        android:textSize=\"10sp\"\n        android:textColor=\"#FF0000\"\n        android:visibility=\"gone\" />\n</RelativeLayout>"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/layout/contentcell.axml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:minHeight=\"44dp\">\n    <LinearLayout\n        android:id=\"@+id/ContentCellBody\"\n        android:layout_alignParentTop=\"true\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_alignParentLeft=\"true\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n</RelativeLayout>"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/layout/footercell.axml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:minHeight=\"0dp\">\n    <TextView\n        android:id=\"@+id/FooterCellText\"\n        android:layout_alignParentTop=\"true\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_alignParentLeft=\"true\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:gravity=\"top|left\" />\n</RelativeLayout>"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/layout/headercell.axml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:minHeight=\"0dp\">\n    <TextView\n        android:id=\"@+id/HeaderCellText\"\n        android:layout_alignParentTop=\"true\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_alignParentLeft=\"true\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:gravity=\"left\" />\n</RelativeLayout>"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/values/Strings.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<string name=\"library_name\">SettingsView.Droid</string>\n</resources>\n"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/values/attrs.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<resources xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n  <!-- \n    This defines the collectionViewStyle attribute so that we can use it \n    to add the scrollbars style to the CollectionView/CarouselView renderers.\n  -->\n  <declare-styleable name=\"SettingsViewRendererTheme\">\n    <attr name=\"settingsViewStyle\" format=\"reference\"/>\n  </declare-styleable>\n\n</resources>"
  },
  {
    "path": "SettingsView/Platforms/Android/Resources/values/styles.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<resources xmlns:android=\"http://schemas.android.com/apk/res/android\" \n  xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n  \n  <style name=\"settingsViewScrollBars\">\n    <item name=\"android:scrollbars\">vertical|horizontal</item>\n  </style>\n  \n  <style name=\"settingsViewTheme\">\n    <item name=\"settingsViewStyle\">@style/settingsViewScrollBars</item>\n  </style>\n  \n  <style name=\"datePickerDialogSpinnerTheme\">\n    <item name=\"android:datePickerStyle\">@style/datePickerSpinnerStyle</item>\n    <item name=\"android:windowIsFloating\">true</item>\n  </style>\n\n   <style name=\"datePickerSpinnerStyle\" parent=\"android:Widget.Material.DatePicker\" >\n        <item name=\"android:datePickerMode\">spinner</item>\n        <item name=\"android:calendarViewShown\">false</item>\n    </style>\n\n</resources>"
  },
  {
    "path": "SettingsView/Section.cs",
    "content": "﻿using System;\nusing System.Collections.Specialized;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Collections;\n\nnamespace AiForms.Settings;\n\r\npublic class Section: SectionBase\n{\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Section\"/> class.\n    /// </summary>\n    public Section()\n    {\n        CollectionChanged += OnCollectionChanged;\n        PropertyChanged += OnPropertyChanged;\n    }\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.Section\"/> class.\n    /// </summary>\n    /// <param name=\"title\">Title.</param>\n    public Section(string title) : this()\n    {\n        Title = title;\n    }\n\n    /// <summary>\n    /// Ons the binding context changed.\n    /// </summary>\n    protected override void OnBindingContextChanged()\n    {\n        base.OnBindingContextChanged();\n        if (HeaderView != null)\n        {\n            HeaderView.BindingContext = BindingContext;\n        }\n        if (FooterView != null)\n        {\n            FooterView.BindingContext = BindingContext;\n        }\n    }\n\n    /// <summary>\n    /// Moves the source item without notify.\n    /// </summary>\n    /// <param name=\"from\">From.</param>\n    /// <param name=\"to\">To.</param>\n    public void MoveSourceItemWithoutNotify(int from, int to)\n    {\n        CollectionChanged -= OnCollectionChanged;\n        var notifyCollection = ItemsSource as INotifyCollectionChanged;\n        if (notifyCollection != null)\n        {\n            notifyCollection.CollectionChanged -= OnItemsSourceCollectionChanged;\n        }\n\n        var tmp = ItemsSource[from];\n        ItemsSource.RemoveAt(from);\n        ItemsSource.Insert(to, tmp);\n\n        var tmpCell = this[from];\n        this.RemoveAt(from);\n        this.Insert(to, tmpCell);\n\n        if (notifyCollection != null)\n        {\n            notifyCollection.CollectionChanged += OnItemsSourceCollectionChanged;\n        }\n\n        CollectionChanged += OnCollectionChanged;\n    }\n\n    /// <summary>\n    /// Moves the cell without notify.\n    /// </summary>\n    /// <param name=\"from\">From.</param>\n    /// <param name=\"to\">To.</param>\n    public void MoveCellWithoutNotify(int from, int to)\n    {\n        CollectionChanged -= OnCollectionChanged;\n        var tmp = this[from];\n        this.RemoveAt(from);\n        this.Insert(to, tmp);\n        CollectionChanged += OnCollectionChanged;\n    }\n\n    public (CellBase Cell, Object Item) DeleteSourceItemWithoutNotify(int from)\n    {\n        CollectionChanged -= OnCollectionChanged;\n        var notifyCollection = ItemsSource as INotifyCollectionChanged;\n        if (notifyCollection != null)\n        {\n            notifyCollection.CollectionChanged -= OnItemsSourceCollectionChanged;\n        }\n\n        var deletedItem = ItemsSource[from];\n        ItemsSource.RemoveAt(from);\n\n        var deletedCell = this[from];\n        this.RemoveAt(from);\n\n        if (notifyCollection != null)\n        {\n            notifyCollection.CollectionChanged += OnItemsSourceCollectionChanged;\n        }\n\n        CollectionChanged += OnCollectionChanged;\n\n        return (deletedCell, deletedItem);\n    }\n\n    public void InsertSourceItemWithoutNotify(CellBase cell, Object item, int to)\n    {\n        CollectionChanged -= OnCollectionChanged;\n        var notifyCollection = ItemsSource as INotifyCollectionChanged;\n        if (notifyCollection != null)\n        {\n            notifyCollection.CollectionChanged -= OnItemsSourceCollectionChanged;\n        }\n\n        ItemsSource.Insert(to, item);\n        Insert(to, cell);\n\n        if (notifyCollection != null)\n        {\n            notifyCollection.CollectionChanged += OnItemsSourceCollectionChanged;\n        }\n\n        CollectionChanged += OnCollectionChanged;\n    }\n\n    public CellBase DeleteCellWithoutNotify(int from)\n    {\n        var deletedCell = this[from];\n        CollectionChanged -= OnCollectionChanged;\n        RemoveAt(from);\n        CollectionChanged += OnCollectionChanged;\n        return deletedCell;\n    }\n\n    public void InsertCellWithoutNotify(CellBase cell, int to)\n    {\n        CollectionChanged -= OnCollectionChanged;\n        Insert(to, cell);\n        CollectionChanged += OnCollectionChanged;\n    }\n\n    void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        var oldCells = e.OldItems?.OfType<CellBase>() ?? Enumerable.Empty<CellBase>();\n        foreach (var oldCell in oldCells)\n            oldCell.PropertyChanged -= OnItemPropertyChanged;\n\n        var newCells = e.NewItems?.OfType<CellBase>() ?? Enumerable.Empty<CellBase>();\n        foreach (var newCell in newCells)\n            newCell.PropertyChanged += OnItemPropertyChanged;\n\n        SectionCollectionChanged?.Invoke(this, e);\n    }\n\n    void OnPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        SectionPropertyChanged?.Invoke(this, e);\n    }\n\n    void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        CellPropertyChanged?.Invoke(sender, new CellPropertyChangedEventArgs(e.PropertyName, this));\n    }\n\n    /// <summary>\n    /// Occurs when section collection changed.\n    /// </summary>\n    public event NotifyCollectionChangedEventHandler SectionCollectionChanged;\n\n    /// <summary>\n    /// Occurs when section property changed.\n    /// </summary>\n    public event PropertyChangedEventHandler SectionPropertyChanged;\n\n    /// <summary>\n    /// Occurs when cell property changed.\n    /// </summary>\n    public event EventHandler<CellPropertyChangedEventArgs> CellPropertyChanged;\n\n    //public SettingsView Parent { get; set; }\n\n    /// <summary>\n    /// The is visible property.\n    /// </summary>\n    public static BindableProperty IsVisibleProperty =\n        BindableProperty.Create(\n            nameof(IsVisible),\n            typeof(bool),\n            typeof(Section),\n            true,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.Section\"/> is visible.\n    /// </summary>\n    /// <value><c>true</c> if is visible; otherwise, <c>false</c>.</value>\n    public bool IsVisible\n    {\n        get { return (bool)GetValue(IsVisibleProperty); }\n        set { SetValue(IsVisibleProperty, value); }\n    }\n\n    /// <summary>\n    /// The footer text property.\n    /// </summary>\n    public static BindableProperty FooterTextProperty =\n        BindableProperty.Create(\n            nameof(FooterText),\n            typeof(string),\n            typeof(Section),\n            default(string),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the footer text.\n    /// </summary>\n    /// <value>The footer text.</value>\n    public string FooterText\n    {\n        get { return (string)GetValue(FooterTextProperty); }\n        set { SetValue(FooterTextProperty, value); }\n    }\n\n    /// <summary>\n    /// The item template property.\n    /// </summary>\n    public static BindableProperty ItemTemplateProperty =\n        BindableProperty.Create(\n            nameof(ItemTemplate),\n            typeof(DataTemplate),\n            typeof(Section),\n            default(DataTemplate),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the item template.\n    /// </summary>\n    /// <value>The item template.</value>\n    public DataTemplate ItemTemplate\n    {\n        get { return (DataTemplate)GetValue(ItemTemplateProperty); }\n        set { SetValue(ItemTemplateProperty, value); }\n    }\n\n    /// <summary>\n    /// The items source property.\n    /// </summary>\n    public static BindableProperty ItemsSourceProperty =\n        BindableProperty.Create(\n            nameof(ItemsSource),\n            typeof(IList),\n            typeof(Section),\n            default(IList),\n            defaultBindingMode: BindingMode.OneWay,\n            propertyChanged: ItemsChanged\n        );\n\n    /// <summary>\n    /// Gets or sets the items source.\n    /// </summary>\n    /// <value>The items source.</value>\n    public IList ItemsSource\n    {\n        get { return (IList)GetValue(ItemsSourceProperty); }\n        set { SetValue(ItemsSourceProperty, value); }\n    }\n\n    /// <summary>\n    /// The header height property.\n    /// </summary>\n    public static BindableProperty HeaderHeightProperty =\n        BindableProperty.Create(\n            nameof(HeaderHeight),\n            typeof(double),\n            typeof(Section),\n            -1d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the height of the header.\n    /// </summary>\n    /// <value>The height of the header.</value>\n    public double HeaderHeight\n    {\n        get { return (double)GetValue(HeaderHeightProperty); }\n        set { SetValue(HeaderHeightProperty, value); }\n    }\n\n    /// <summary>\n    /// The header view property.\n    /// </summary>\n    public static BindableProperty HeaderViewProperty =\n        BindableProperty.Create(\n            nameof(HeaderView),\n            typeof(View),\n            typeof(Section),\n            default(View),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the header view.\n    /// </summary>\n    /// <value>The header view.</value>\n    public View HeaderView\n    {\n        get { return (View)GetValue(HeaderViewProperty); }\n        set { SetValue(HeaderViewProperty, value); }\n    }\n\n    /// <summary>\n    /// The footer view property.\n    /// </summary>\n    public static BindableProperty FooterViewProperty =\n        BindableProperty.Create(\n            nameof(FooterView),\n            typeof(View),\n            typeof(Section),\n            default(View),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the footer view.\n    /// </summary>\n    /// <value>The footer view.</value>\n    public View FooterView\n    {\n        get { return (View)GetValue(FooterViewProperty); }\n        set { SetValue(FooterViewProperty, value); }\n    }\n\n    public static BindableProperty FooterVisibleProperty = BindableProperty.Create(\n        nameof(FooterVisible),\n        typeof(bool),\n        typeof(Section),\n        true,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public bool FooterVisible\n    {\n        get { return (bool)GetValue(FooterVisibleProperty); }\n        set { SetValue(FooterVisibleProperty, value); }\n    }\n\n    /// <summary>\n    /// The use drag sort property.\n    /// </summary>\n    public static BindableProperty UseDragSortProperty =\n        BindableProperty.Create(\n            nameof(UseDragSort),\n            typeof(bool),\n            typeof(Section),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.Section\"/> use drag sort.\n    /// </summary>\n    /// <value><c>true</c> if use drag sort; otherwise, <c>false</c>.</value>\n    public bool UseDragSort\n    {\n        get { return (bool)GetValue(UseDragSortProperty); }\n        set { SetValue(UseDragSortProperty, value); }\n    }\n\n    public static BindableProperty TemplateStartIndexProperty =\n        BindableProperty.Create(\n            nameof(TemplateStartIndex),\n            typeof(int),\n            typeof(Section),\n            default(int),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    public int TemplateStartIndex\n    {\n        get { return (int)GetValue(TemplateStartIndexProperty); }\n        set { SetValue(TemplateStartIndexProperty, value); }\n    }\n\n    int templatedItemsCount;\n\n    static void ItemsChanged(BindableObject bindable, object oldValue, object newValue)\n    {\n        var section = (Section)bindable;\n\n        if (section.ItemTemplate == null)\n        {\n            return;\n        }\n\n        IList oldValueAsEnumerable;\n        IList newValueAsEnumerable;\n        try\n        {\n            oldValueAsEnumerable = oldValue as IList;\n            newValueAsEnumerable = newValue as IList;\n        }\n        catch (Exception e)\n        {\n            throw;\n        }\n\n        var oldObservableCollection = oldValue as INotifyCollectionChanged;\n\n        if (oldObservableCollection != null)\n        {\n            oldObservableCollection.CollectionChanged -= section.OnItemsSourceCollectionChanged;\n        }\n\n        // keep the platform from notifying itemchanged event.\n        section.CollectionChanged -= section.OnCollectionChanged;\n\n        if (oldValueAsEnumerable != null)\n        {\n            for (var i = oldValueAsEnumerable.Count - 1; i >= 0; i--)\n            {\n                section.RemoveAt(section.TemplateStartIndex + i);\n            }\n        }\n\n        if (newValueAsEnumerable != null)\n        {\n            for (var i = 0; i < newValueAsEnumerable.Count; i++)\n            {\n                var view = CreateChildViewFor(section.ItemTemplate, newValueAsEnumerable[i], section);\n                view.Parent = section.Parent;\n                section.Insert(section.TemplateStartIndex + i, view);\n            }\n            section.templatedItemsCount = newValueAsEnumerable.Count;\n        }\n\n        section.CollectionChanged += section.OnCollectionChanged;\n\n        var newObservableCollection = newValue as INotifyCollectionChanged;\n\n        if (newObservableCollection != null)\n        {\n            newObservableCollection.CollectionChanged += section.OnItemsSourceCollectionChanged;\n        }\n\n        // Notify manually Collection Reset.\n        section.SectionCollectionChanged?.Invoke(section, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));\n    }\n\n    void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        if (e.Action == NotifyCollectionChangedAction.Replace)\n        {\n\n            //RemoveAt(e.OldStartingIndex + TemplateStartIndex);\n\n            var item = e.NewItems[0];\n            var view = CreateChildViewFor(ItemTemplate, item, this);\n\n            //Insert(e.NewStartingIndex + TemplateStartIndex, view);\n            this[e.NewStartingIndex + TemplateStartIndex] = view;\n        }\n\n        else if (e.Action == NotifyCollectionChangedAction.Add)\n        {\n            if (e.NewItems != null)\n            {\n                for (var i = 0; i < e.NewItems.Count; i++)\n                {\n                    var item = e.NewItems[i];\n                    var view = CreateChildViewFor(ItemTemplate, item, this);\n\n                    Insert(i + e.NewStartingIndex + TemplateStartIndex, view);\n                    templatedItemsCount++;\n                }\n            }\n        }\n\n        else if (e.Action == NotifyCollectionChangedAction.Remove)\n        {\n            if (e.OldItems != null)\n            {\n                RemoveAt(e.OldStartingIndex + TemplateStartIndex);\n                templatedItemsCount--;\n            }\n        }\n\n        else if (e.Action == NotifyCollectionChangedAction.Reset)\n        {\n            //this.Clear();\n            IList source = ItemsSource as IList;\n            for (var i = templatedItemsCount - 1; i >= 0; i--)\n            {\n                RemoveAt(TemplateStartIndex + i);\n            }\n            templatedItemsCount = 0;\n        }\n\n        else\n        {\n            return;\n        }\n\n    }\n\n\n    static CellBase CreateChildViewFor(DataTemplate template, object item, BindableObject container)\n    {\n        var selector = template as DataTemplateSelector;\n\n        if (selector != null)\n        {\n            template = selector.SelectTemplate(item, container);\n        }\n\n        //Binding context\n        template.SetValue(BindableObject.BindingContextProperty, item);\n\n        return (CellBase)template.CreateContent();\n    }\n}\n\n"
  },
  {
    "path": "SettingsView/SectionBase.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing System.Collections.ObjectModel;\nusing System.Collections.Specialized;\n\nnamespace AiForms.Settings;\n\r\npublic class SectionBase: Element, IList<CellBase>, IVisualTreeElement, INotifyCollectionChanged\n{\n    public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(TableSectionBase), null);\n    public static readonly BindableProperty TextColorProperty = BindableProperty.Create(nameof(TextColor), typeof(Color), typeof(TableSectionBase), Colors.Black);\n\n\n    readonly ObservableCollection<CellBase> _children = new ObservableCollection<CellBase>();\n\n    /// <summary>\n    ///     Constructs a Section without an empty header.\n    /// </summary>\n    protected SectionBase()\n    {\n        _children.CollectionChanged += OnChildrenChanged;\n    }\n\n    /// <summary>\n    ///     Constructs a Section with the specified header.\n    /// </summary>\n    protected SectionBase(string title)\n    {\n        if (title == null)\n            throw new ArgumentNullException(\"title\");\n\n        Title = title;\n        _children.CollectionChanged += OnChildrenChanged;\n    }\n\n    public string Title\n    {\n        get { return (string)GetValue(TitleProperty); }\n        set { SetValue(TitleProperty, value); }\n    }\n\n    public Color TextColor\n    {\n        get { return (Color)GetValue(TextColorProperty); }\n        set { SetValue(TextColorProperty, value); }\n    }\n\n    public void Add(CellBase item)\n    {\n        _children.Add(item);\n        if(item is IVisualTreeElement element)\n        {\n            VisualDiagnostics.OnChildAdded(this, element);\n        }\n    }\n\n    public void Clear()\n    {\n        foreach (var item in _children)\n        {\n            if (item is IVisualTreeElement element)\n            {\n                VisualDiagnostics.OnChildRemoved(this, element, _children.IndexOf(item));\n            }\n        }\n        _children.Clear();\n    }\n\n    public bool Contains(CellBase item)\n    {\n        return _children.Contains(item);\n    }\n\n    public void CopyTo(CellBase[] array, int arrayIndex)\n    {\n        _children.CopyTo(array, arrayIndex);\n    }\n\n    public int Count\n    {\n        get { return _children.Count; }\n    }\n\n    bool ICollection<CellBase>.IsReadOnly\n    {\n        get { return false; }\n    }\n\n    public bool Remove(CellBase item)\n    {\n        if (item is IVisualTreeElement element)\n        {\n            VisualDiagnostics.OnChildRemoved(this, element, _children.IndexOf(item));\n        }\n        return _children.Remove(item);\n    }\n\n    IEnumerator IEnumerable.GetEnumerator()\n    {\n        return GetEnumerator();\n    }\n\n    public IEnumerator<CellBase> GetEnumerator()\n    {\n        return _children.GetEnumerator();\n    }\n\n    public int IndexOf(CellBase item)\n    {\n        return _children.IndexOf(item);\n    }\n\n    public void Insert(int index, CellBase item)\n    {\n        if (item is IVisualTreeElement element)\n        {\n            VisualDiagnostics.OnChildAdded(this, element, index);\n        }\n        _children.Insert(index, item);\n    }\n\n    public CellBase this[int index]\n    {\n        get { return _children[index]; }\n        set { _children[index] = value; }\n    }\n\n    public void RemoveAt(int index)\n    {\n        var item = _children[index];\n        if (item is IVisualTreeElement element)\n        {\n            VisualDiagnostics.OnChildRemoved(this, element, index);\n        }\n\n        _children.RemoveAt(index);\n    }\n\n    public event NotifyCollectionChangedEventHandler CollectionChanged\n    {\n        add { _children.CollectionChanged += value; }\n        remove { _children.CollectionChanged -= value; }\n    }\n\n    public void Add(IEnumerable<CellBase> items)\n    {\n        foreach(var item in items)\n        {\n            _children.Add(item);\n        }\n    }\n\n    protected override void OnBindingContextChanged()\n    {\n        base.OnBindingContextChanged();\n\n        object bc = BindingContext;\n        foreach (CellBase child in _children)\n        {\n            SetInheritedBindingContext(child, bc);\n        }\n    }\n\n    void OnChildrenChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)\n    {\n        // We need to hook up the binding context for new items.\n        if (notifyCollectionChangedEventArgs.NewItems == null)\n        {\n            return;\n        }\n        object bc = BindingContext;\n        foreach (BindableObject item in notifyCollectionChangedEventArgs.NewItems)\n        {\n            SetInheritedBindingContext(item, bc);\n        }\n    }\n\n    IReadOnlyList<IVisualTreeElement> IVisualTreeElement.GetVisualChildren() => this._children.Cast<IVisualTreeElement>().ToList().AsReadOnly();\n    IVisualTreeElement IVisualTreeElement.GetVisualParent() => null;\n}\n\n"
  },
  {
    "path": "SettingsView/SettingsModel.cs",
    "content": "﻿using System;\nusing System.Linq;\nusing System.Collections.Generic;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Settings model.\n/// </summary>\npublic class SettingsModel\n{\n    static readonly BindableProperty PathProperty = BindableProperty.Create(\"Path\", typeof(Tuple<int, int>), typeof(CellBase), null);\n\n    public event Action<CellBase> RowSelected;\n\n    SettingsRoot _root;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.SettingsModel\"/> class.\n    /// </summary>\n    /// <param name=\"settingsRoot\">Settings root.</param>\n    public SettingsModel(SettingsRoot settingsRoot)\n    {\n        _root = settingsRoot;\n    }\n\n    /// <summary>\n    /// Gets the cell.\n    /// </summary>\n    /// <returns>The cell.</returns>\n    /// <param name=\"section\">Section.</param>\n    /// <param name=\"row\">Row.</param>\n    public virtual CellBase GetCell(int section, int row)\n    {\n        var cell = _root.ElementAt(section)[row];\n        SetPath(cell, new Tuple<int, int>(section, row));\n        return cell;\n    }   \n\n    /// <summary>\n    /// Gets the row count.\n    /// </summary>\n    /// <returns>The row count.</returns>\n    /// <param name=\"section\">Section.</param>\n    public virtual int GetRowCount(int section)\n    {\n        return _root.ElementAt(section).Count;\n    }\n\n    /// <summary>\n    /// Gets the section count.\n    /// </summary>\n    /// <returns>The section count.</returns>\n    public virtual int GetSectionCount()\n    {\n        return _root.Count();\n    }\n\n    /// <summary>\n    /// Gets the section.\n    /// </summary>\n    /// <returns>The section.</returns>\n    /// <param name=\"section\">Section.</param>\n    public virtual Section GetSection(int section)\n    {\n        return _root.ElementAtOrDefault(section);\n    }\n\n    /// <summary>\n    /// Gets the section from cell.\n    /// </summary>\n    /// <returns>The section from cell.</returns>\n    /// <param name=\"cell\">Cell.</param>\n    public virtual Section GetSectionFromCell(CellBase cell)\n    {\n        return _root.FirstOrDefault(x => x.Contains(cell));\n    }\n\n    /// <summary>\n    /// Gets the index of the section.\n    /// </summary>\n    /// <returns>The section index.</returns>\n    /// <param name=\"section\">Section.</param>\n    public virtual int GetSectionIndex(Section section)\n    {\n        return _root.IndexOf(section);\n    }\n\n    /// <summary>\n    /// Gets the section title.\n    /// </summary>\n    /// <returns>The section title.</returns>\n    /// <param name=\"section\">Section.</param>\n    public virtual string GetSectionTitle(int section)\n    {\n        return _root.ElementAt(section).Title;\n    }\n\n    public virtual string[] GetSectionIndexTitles()\n    {\n        return null;\n    }\n\n\n    /// <summary>\n    /// Gets the section header view.\n    /// </summary>\n    /// <returns>The section header view.</returns>\n    /// <param name=\"section\">Section.</param>\n    public virtual View GetSectionHeaderView(int section)\n    {\n        return _root.ElementAt(section).HeaderView;\n    }\n\n    /// <summary>\n    /// Gets the footer text.\n    /// </summary>\n    /// <returns>The footer text.</returns>\n    /// <param name=\"section\">Section.</param>\n    public virtual string GetFooterText(int section)\n    {\n        return _root.ElementAt(section).FooterText;\n    }\n\n    /// <summary>\n    /// Gets the section footer view.\n    /// </summary>\n    /// <returns>The section footer view.</returns>\n    /// <param name=\"section\">Section.</param>\n    public virtual View GetSectionFooterView(int section)\n    {\n        return _root.ElementAt(section).FooterView;\n    }\n\n    /// <summary>\n    /// Ons the row selected.\n    /// </summary>\n    /// <param name=\"item\">Item.</param>\n    protected virtual void OnRowSelected(object item)\n    {       \n        (item as CellBase)?.OnTapped();\n    }\n\n    /// <summary>\n    /// Gets the height of the header.\n    /// </summary>\n    /// <returns>The header height.</returns>\n    /// <param name=\"section\">Section.</param>\n    public virtual double GetHeaderHeight(int section)\n    {\n        return _root.ElementAt(section).HeaderHeight;\n    }\n\n    public void OnRowSelected(int section, int row)\n    {\n        var cell = GetCell(section, row);\n        cell?.OnTapped();\n        RowSelected?.Invoke(cell);\n    }\n\n    public void OnRowSelected(CellBase cell)\n    {\n        cell.OnTapped();\n        RowSelected?.Invoke(cell);\n    }\n\n    // this method no longer uses except for iOS.CellBaseRenderer.\n    internal static Tuple<int, int> GetPath(CellBase item)\n    {\n        if (item == null)\n            throw new ArgumentNullException(\"item\");\n\n        return (Tuple<int, int>)item.GetValue(PathProperty);\n    }\n\n\n    internal static void SetPath(CellBase item, Tuple<int, int> index)\n    {\n        if (item == null)\n            return;\n\n        item.SetValue(PathProperty, index);\n    }\n}\n"
  },
  {
    "path": "SettingsView/SettingsRoot.cs",
    "content": "﻿using System;\nusing System.Collections.Specialized;\nusing System.ComponentModel;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Settings root.\n/// </summary>\npublic class SettingsRoot : TableSectionBase<Section>\n{\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.SettingsRoot\"/> class.\n    /// </summary>\n    public SettingsRoot()\n    {\n        SetupEvents();\n    }\n\n    /// <summary>\n    /// Occurs when section collection changed.\n    /// </summary>\n    public event EventHandler<NotifyCollectionChangedEventArgs> SectionCollectionChanged;\n    /// <summary>\n    /// Occurs when section property changed.\n    /// </summary>\n    public event PropertyChangedEventHandler SectionPropertyChanged;\n    /// <summary>\n    /// Occurs when cell property changed.\n    /// </summary>\n    public event EventHandler<CellPropertyChangedEventArgs> CellPropertyChanged;\n   \n    void ChildCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)\n    {           \n        SectionCollectionChanged?.Invoke(sender, notifyCollectionChangedEventArgs);\n    }\n\n    void ChildPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        SectionPropertyChanged?.Invoke(sender, e);\n    }\n\n    void OnCellPropertyChanged(object sender, CellPropertyChangedEventArgs e)\n    {\n        CellPropertyChanged?.Invoke(sender, e);\n    }\n\n    void SetupEvents()\n    {\n        CollectionChanged += (sender, args) =>\n        {\n            if (args.NewItems != null) {\n                foreach (Section section in args.NewItems) {\n                    section.SectionCollectionChanged += ChildCollectionChanged;\n                    section.SectionPropertyChanged += ChildPropertyChanged;\n                    section.CellPropertyChanged += OnCellPropertyChanged;\n                }\n            }\n\n            if (args.OldItems != null) {\n                foreach (Section section in args.OldItems) {\n                    section.SectionCollectionChanged -= ChildCollectionChanged;\n                    section.SectionPropertyChanged -= ChildPropertyChanged;\n                    section.CellPropertyChanged -= OnCellPropertyChanged;\n                }\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "SettingsView/SettingsView.DefineProperites.cs",
    "content": "﻿using AiForms.Settings.Extensions;\nusing Microsoft.Maui.Controls.Internals;\nusing System;\nusing System.Collections;\nusing System.Collections.Specialized;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Windows.Input;\n\nnamespace AiForms.Settings;\n\r\npublic partial class SettingsView\n{\n    public event EventHandler<DropEventArgs> ItemDropped;\n\n    public static BindableProperty ItemDroppedCommandProperty = BindableProperty.Create(\n        nameof(ItemDroppedCommand),\n        typeof(ICommand),\n        typeof(SettingsView),\n        default(ICommand),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public ICommand ItemDroppedCommand\n    {\n        get { return (ICommand)GetValue(ItemDroppedCommandProperty); }\n        set { SetValue(ItemDroppedCommandProperty, value); }\n    }\n\n    /// <summary>\n    /// The background color property.\n    /// </summary>\n    public static new BindableProperty BackgroundColorProperty =\n        BindableProperty.Create(\n            nameof(BackgroundColor),\n            typeof(Color),\n            typeof(SettingsView),\n            Colors.Transparent,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// A color of out of region and entire region. They contains header, footer and cell (in case android).\n    /// </summary>\n    /// <value>The color of the background.</value>\n    public new Color BackgroundColor\n    {\n        get { return (Color)GetValue(BackgroundColorProperty); }\n        set { SetValue(BackgroundColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The separator color property.\n    /// </summary>\n    public static BindableProperty SeparatorColorProperty =\n        BindableProperty.Create(\n            nameof(SeparatorColor),\n            typeof(Color),\n            typeof(SettingsView),\n            Color.FromRgb(199, 199, 204),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Row separator color.\n    /// </summary>\n    /// <value>The color of the separator.</value>\n    public Color SeparatorColor\n    {\n        get { return (Color)GetValue(SeparatorColorProperty); }\n        set { SetValue(SeparatorColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The selected color property.\n    /// </summary>\n    public static BindableProperty SelectedColorProperty =\n        BindableProperty.Create(\n            nameof(SelectedColor),\n            typeof(Color),\n            typeof(SettingsView),\n            Colors.Transparent,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Cell backgraound color when row is selected.\n    /// </summary>\n    /// <value>The color of the selected.</value>\n    public Color SelectedColor\n    {\n        get { return (Color)GetValue(SelectedColorProperty); }\n        set { SetValue(SelectedColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The header padding property.\n    /// </summary>\n    public static BindableProperty HeaderPaddingProperty =\n        BindableProperty.Create(\n            nameof(HeaderPadding),\n            typeof(Thickness),\n            typeof(SettingsView),\n            new Thickness(14, 8, 8, 8),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Section header padding\n    /// </summary>\n    /// <value>The header padding.</value>\n    public Thickness HeaderPadding\n    {\n        get { return (Thickness)GetValue(HeaderPaddingProperty); }\n        set { SetValue(HeaderPaddingProperty, value); }\n    }\n\n    /// <summary>\n    /// The header text color property.\n    /// </summary>\n    public static BindableProperty HeaderTextColorProperty =\n        BindableProperty.Create(\n            nameof(HeaderTextColor),\n            typeof(Color),\n            typeof(SettingsView),\n            new Color(),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Section header text color\n    /// </summary>\n    /// <value>The color of the header text.</value>\n    public Color HeaderTextColor\n    {\n        get { return (Color)GetValue(HeaderTextColorProperty); }\n        set { SetValue(HeaderTextColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The header font size property.\n    /// </summary>\n    public static BindableProperty HeaderFontSizeProperty =\n        BindableProperty.Create(\n            nameof(HeaderFontSize),\n            typeof(double),\n            typeof(SettingsView),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay,\n            defaultValueCreator: bindable => DeviceInfo.Platform == DevicePlatform.iOS ? 14d : 18d\n        );\n\n    /// <summary>\n    /// Section header text font size\n    /// </summary>\n    /// <value>The size of the header font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double HeaderFontSize\n    {\n        get { return (double)GetValue(HeaderFontSizeProperty); }\n        set { SetValue(HeaderFontSizeProperty, value); }\n    }\n\n    public static BindableProperty HeaderFontFamilyProperty = BindableProperty.Create(\n        nameof(HeaderFontFamily),\n        typeof(string),\n        typeof(SettingsView),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string HeaderFontFamily {\n        get { return (string)GetValue(HeaderFontFamilyProperty); }\n        set { SetValue(HeaderFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty HeaderFontAttributesProperty = BindableProperty.Create(\n        nameof(HeaderFontAttributes),\n        typeof(FontAttributes),\n        typeof(SettingsView),\n        FontAttributes.None,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes HeaderFontAttributes {\n        get { return (FontAttributes)GetValue(HeaderFontAttributesProperty); }\n        set { SetValue(HeaderFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The header text vertical align property.\n    /// </summary>\n    public static BindableProperty HeaderTextVerticalAlignProperty =\n        BindableProperty.Create(\n            nameof(HeaderTextVerticalAlign),\n            typeof(LayoutAlignment),\n            typeof(SettingsView),\n            LayoutAlignment.End,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Section header text vertical alignment.\n    /// </summary>\n    /// <value>The header text vertical align.</value>\n    public LayoutAlignment HeaderTextVerticalAlign\n    {\n        get { return (LayoutAlignment)GetValue(HeaderTextVerticalAlignProperty); }\n        set { SetValue(HeaderTextVerticalAlignProperty, value); }\n    }\n\n    /// <summary>\n    /// The header background color property.\n    /// </summary>\n    public static BindableProperty HeaderBackgroundColorProperty =\n        BindableProperty.Create(\n            nameof(HeaderBackgroundColor),\n            typeof(Color),\n            typeof(SettingsView),\n            Colors.Transparent,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Section header background color.\n    /// </summary>\n    /// <value>The color of the header background.</value>\n    public Color HeaderBackgroundColor\n    {\n        get { return (Color)GetValue(HeaderBackgroundColorProperty); }\n        set { SetValue(HeaderBackgroundColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The row height property.\n    /// </summary>\n    public static BindableProperty RowHeightProperty =\n        BindableProperty.Create(\n            nameof(RowHeight),\n            typeof(int),\n            typeof(SettingsView),\n            -1,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// The row height property.\n    /// </summary>\n    /// <value>Height of the table rows.</value>\n    public int RowHeight\r\n    {\r\n        get { return (int)GetValue(RowHeightProperty); }\r\n        set { SetValue(RowHeightProperty, value); }\r\n    }\n\n    /// <summary>\n    /// The has uneven rows property.\n    /// </summary>\n    public static BindableProperty HasUnevenRowsProperty =\n        BindableProperty.Create(\n            nameof(HasUnevenRows),\n            typeof(bool),\n            typeof(SettingsView),\n            false,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// The has uneven rows property.\n    /// </summary>\n    /// <value>If rows are uneven height.</value>\n    public bool HasUnevenRows\r\n    {\r\n        get { return (bool)GetValue(HasUnevenRowsProperty); }\r\n        set { SetValue(HasUnevenRowsProperty, value); }\r\n    }\n\n    /// <summary>\n    /// The header height property.\n    /// </summary>\n    public static BindableProperty HeaderHeightProperty =\n        BindableProperty.Create(\n            nameof(HeaderHeight),\n            typeof(double),\n            typeof(SettingsView),\n            -1d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Section header height.\n    /// </summary>\n    /// <value>The height of the header.</value>\n    public double HeaderHeight\n    {\n        get { return (double)GetValue(HeaderHeightProperty); }\n        set { SetValue(HeaderHeightProperty, value); }\n    }\n\n    /// <summary>\n    /// The footer text color property.\n    /// </summary>\n    public static BindableProperty FooterTextColorProperty =\n        BindableProperty.Create(\n            nameof(FooterTextColor),\n            typeof(Color),\n            typeof(SettingsView),\n            new Color(),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Section footer text.\n    /// </summary>\n    /// <value>The color of the footer text.</value>\n    public Color FooterTextColor\n    {\n        get { return (Color)GetValue(FooterTextColorProperty); }\n        set { SetValue(FooterTextColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The footer font size property.\n    /// </summary>\n    public static BindableProperty FooterFontSizeProperty =\n        BindableProperty.Create(\n            nameof(FooterFontSize),\n            typeof(double),\n            typeof(SettingsView),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay,\n            defaultValueCreator: bindable => DeviceInfo.Platform == DevicePlatform.iOS ? 14d : 18d\n        );\n\n    /// <summary>\n    /// Section footer text font size.\n    /// </summary>\n    /// <value>The size of the footer font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double FooterFontSize\n    {\n        get { return (double)GetValue(FooterFontSizeProperty); }\n        set { SetValue(FooterFontSizeProperty, value); }\n    }\n\n    public static BindableProperty FooterFontFamilyProperty = BindableProperty.Create(\n        nameof(FooterFontFamily),\n        typeof(string),\n        typeof(SettingsView),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string FooterFontFamily {\n        get { return (string)GetValue(FooterFontFamilyProperty); }\n        set { SetValue(FooterFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty FooterFontAttributesProperty = BindableProperty.Create(\n        nameof(FooterFontAttributes),\n        typeof(FontAttributes),\n        typeof(SettingsView),\n        FontAttributes.None,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes FooterFontAttributes {\n        get { return (FontAttributes)GetValue(FooterFontAttributesProperty); }\n        set { SetValue(FooterFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The footer background color property.\n    /// </summary>\n    public static BindableProperty FooterBackgroundColorProperty =\n        BindableProperty.Create(\n            nameof(FooterBackgroundColor),\n            typeof(Color),\n            typeof(SettingsView),\n            Colors.Transparent,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Section footer background color.\n    /// </summary>\n    /// <value>The color of the footer background.</value>\n    public Color FooterBackgroundColor\n    {\n        get { return (Color)GetValue(FooterBackgroundColorProperty); }\n        set { SetValue(FooterBackgroundColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The footer padding property.\n    /// </summary>\n    public static BindableProperty FooterPaddingProperty =\n        BindableProperty.Create(\n            nameof(FooterPadding),\n            typeof(Thickness),\n            typeof(SettingsView),\n            new Thickness(14, 8, 14, 8),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Section footer padding.\n    /// </summary>\n    /// <value>The footer padding.</value>\n    public Thickness FooterPadding\n    {\n        get { return (Thickness)GetValue(FooterPaddingProperty); }\n        set { SetValue(FooterPaddingProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell title color property.\n    /// </summary>\n    public static BindableProperty CellTitleColorProperty =\n        BindableProperty.Create(\n            nameof(CellTitleColor),\n            typeof(Color),\n            typeof(SettingsView),\n            new Color(),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// The color of the cell title.\n    /// </summary>\n    /// <value>The color of the cell title.</value>\n    public Color CellTitleColor\n    {\n        get { return (Color)GetValue(CellTitleColorProperty); }\n        set { SetValue(CellTitleColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell title font size property.\n    /// </summary>\n    public static BindableProperty CellTitleFontSizeProperty =\n        BindableProperty.Create(\n            nameof(CellTitleFontSize),\n            typeof(double),\n            typeof(SettingsView),\n            -1.0,\n            defaultBindingMode: BindingMode.OneWay,\n            defaultValueCreator: bindable => (bindable as Element)?.FindMauiContext()?.Services?.GetService<IFontManager>()?.DefaultFontSize ?? 0d\n        );\n\n    /// <summary>\n    /// The font size of the cell title.\n    /// </summary>\n    /// <value>The size of the cell title font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double CellTitleFontSize\n    {\n        get { return (double)GetValue(CellTitleFontSizeProperty); }\n        set { SetValue(CellTitleFontSizeProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell title font family.\n    /// </summary>\n    public static BindableProperty CellTitleFontFamilyProperty = BindableProperty.Create(\n        nameof(CellTitleFontFamily),\n        typeof(string),\n        typeof(SettingsView),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n    /// <summary>\n    /// The cell title font family.\n    /// </summary>\n    public string CellTitleFontFamily {\n        get { return (string)GetValue(CellTitleFontFamilyProperty); }\n        set { SetValue(CellTitleFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty CellTitleFontAttributesProperty = BindableProperty.Create(\n        nameof(CellTitleFontAttributes),\n        typeof(FontAttributes),\n        typeof(SettingsView),\n        FontAttributes.None,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes CellTitleFontAttributes {\n        get { return (FontAttributes)GetValue(CellTitleFontAttributesProperty); }\n        set { SetValue(CellTitleFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell value text color property.\n    /// </summary>\n    public static BindableProperty CellValueTextColorProperty =\n        BindableProperty.Create(\n            nameof(CellValueTextColor),\n            typeof(Color),\n            typeof(SettingsView),\n            new Color(),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// The color of the cell value text.\n    /// </summary>\n    /// <value>The color of the cell value text.</value>\n    public Color CellValueTextColor\n    {\n        get { return (Color)GetValue(CellValueTextColorProperty); }\n        set { SetValue(CellValueTextColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell value text font size property.\n    /// </summary>\n    public static BindableProperty CellValueTextFontSizeProperty =\n        BindableProperty.Create(\n            nameof(CellValueTextFontSize),\n            typeof(double),\n            typeof(SettingsView),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// The font size of the cell value text.\n    /// </summary>\n    /// <value>The size of the cell value text font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double CellValueTextFontSize\n    {\n        get { return (double)GetValue(CellValueTextFontSizeProperty); }\n        set { SetValue(CellValueTextFontSizeProperty, value); }\n    }\n\n    public static BindableProperty CellValueTextFontFamilyProperty = BindableProperty.Create(\n        nameof(CellValueTextFontFamily),\n        typeof(string),\n        typeof(SettingsView),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string CellValueTextFontFamily {\n        get { return (string)GetValue(CellValueTextFontFamilyProperty); }\n        set { SetValue(CellValueTextFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty CellValueTextFontAttributesProperty = BindableProperty.Create(\n        nameof(CellValueTextFontAttributes),\n        typeof(FontAttributes),\n        typeof(SettingsView),\n        FontAttributes.None,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes CellValueTextFontAttributes {\n        get { return (FontAttributes)GetValue(CellValueTextFontAttributesProperty); }\n        set { SetValue(CellValueTextFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell description color property.\n    /// </summary>\n    public static BindableProperty CellDescriptionColorProperty =\n        BindableProperty.Create(\n            nameof(CellDescriptionColor),\n            typeof(Color),\n            typeof(SettingsView),\n            new Color(),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// The color of the cell description text.\n    /// </summary>\n    /// <value>The color of the cell description.</value>\n    public Color CellDescriptionColor\n    {\n        get { return (Color)GetValue(CellDescriptionColorProperty); }\n        set { SetValue(CellDescriptionColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell description font size property.\n    /// </summary>\n    public static BindableProperty CellDescriptionFontSizeProperty =\n        BindableProperty.Create(\n            nameof(CellDescriptionFontSize),\n            typeof(double),\n            typeof(SettingsView),\n            -1.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// The font size of the cell description text.\n    /// </summary>\n    /// <value>The size of the cell description font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double CellDescriptionFontSize\n    {\n        get { return (double)GetValue(CellDescriptionFontSizeProperty); }\n        set { SetValue(CellDescriptionFontSizeProperty, value); }\n    }\n\n    public static BindableProperty CellDescriptionFontFamilyProperty = BindableProperty.Create(\n        nameof(CellDescriptionFontFamily),\n        typeof(string),\n        typeof(SettingsView),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string CellDescriptionFontFamily {\n        get { return (string)GetValue(CellDescriptionFontFamilyProperty); }\n        set { SetValue(CellDescriptionFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty CellDescriptionFontAttributesProperty = BindableProperty.Create(\n        nameof(CellDescriptionFontAttributes),\n        typeof(FontAttributes),\n        typeof(SettingsView),\n        FontAttributes.None,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes CellDescriptionFontAttributes {\n        get { return (FontAttributes)GetValue(CellDescriptionFontAttributesProperty); }\n        set { SetValue(CellDescriptionFontAttributesProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell background color property.\n    /// </summary>\n    public static BindableProperty CellBackgroundColorProperty =\n        BindableProperty.Create(\n            nameof(CellBackgroundColor),\n            typeof(Color),\n            typeof(SettingsView),\n            Colors.White,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the cell background.\n    /// </summary>\n    /// <value>The color of the cell background.</value>\n    public Color CellBackgroundColor\n    {\n        get { return (Color)GetValue(CellBackgroundColorProperty); }\n        set { SetValue(CellBackgroundColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell icon size property.\n    /// </summary>\n    public static BindableProperty CellIconSizeProperty =\n        BindableProperty.Create(\n            nameof(CellIconSize),\n            typeof(Size),\n            typeof(SettingsView),\n            default(Size),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the size of the cell icon.\n    /// </summary>\n    /// <value>The size of the cell icon.</value>\n    [TypeConverter(typeof(SizeConverter))]\n    public Size CellIconSize\n    {\n        get { return (Size)GetValue(CellIconSizeProperty); }\n        set { SetValue(CellIconSizeProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell icon radius property.\n    /// </summary>\n    public static BindableProperty CellIconRadiusProperty =\n        BindableProperty.Create(\n            nameof(CellIconRadius),\n            typeof(double),\n            typeof(SettingsView),\n            6.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the cell icon radius.\n    /// </summary>\n    /// <value>The cell icon radius.</value>\n    public double CellIconRadius\n    {\n        get { return (double)GetValue(CellIconRadiusProperty); }\n        set { SetValue(CellIconRadiusProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell accent color property.\n    /// </summary>\n    public static BindableProperty CellAccentColorProperty =\n        BindableProperty.Create(\n            nameof(CellAccentColor),\n            typeof(Color),\n            typeof(SettingsView),\n            KnownColor.Accent,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the cell accent.\n    /// </summary>\n    /// <value>The color of the cell accent.</value>\n    public Color CellAccentColor\n    {\n        get { return (Color)GetValue(CellAccentColorProperty); }\n        set { SetValue(CellAccentColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell hint text color property.\n    /// </summary>\n    public static BindableProperty CellHintTextColorProperty =\n        BindableProperty.Create(\n            nameof(CellHintTextColor),\n            typeof(Color),\n            typeof(SettingsView),\n            Colors.Red,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the color of the cell hint text.\n    /// </summary>\n    /// <value>The color of the cell hint text.</value>\n    public Color CellHintTextColor\n    {\n        get { return (Color)GetValue(CellHintTextColorProperty); }\n        set { SetValue(CellHintTextColorProperty, value); }\n    }\n\n    /// <summary>\n    /// The cell hint font size property.\n    /// </summary>\n    public static BindableProperty CellHintFontSizeProperty =\n        BindableProperty.Create(\n            nameof(CellHintFontSize),\n            typeof(double),\n            typeof(SettingsView),\n            10.0d,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the font size of the cell hint text.\n    /// </summary>\n    /// <value>The size of the cell hint font.</value>\n    [TypeConverter(typeof(FontSizeConverter))]\n    public double CellHintFontSize\n    {\n        get { return (double)GetValue(CellHintFontSizeProperty); }\n        set { SetValue(CellHintFontSizeProperty, value); }\n    }\n\n    public static BindableProperty CellHintFontFamilyProperty = BindableProperty.Create(\n        nameof(CellHintFontFamily),\n        typeof(string),\n        typeof(SettingsView),\n        default(string),\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public string CellHintFontFamily {\n        get { return (string)GetValue(CellHintFontFamilyProperty); }\n        set { SetValue(CellHintFontFamilyProperty, value); }\n    }\n\n    public static BindableProperty CellHintFontAttributesProperty = BindableProperty.Create(\n        nameof(CellHintFontAttributes),\n        typeof(FontAttributes),\n        typeof(SettingsView),\n        FontAttributes.None,\n        defaultBindingMode: BindingMode.OneWay\n    );\n\n    public FontAttributes CellHintFontAttributes {\n        get { return (FontAttributes)GetValue(CellHintFontAttributesProperty); }\n        set { SetValue(CellHintFontAttributesProperty, value); }\n    }\n\n    //Only Android\n    /// <summary>\n    /// The use description as value property.\n    /// </summary>\n    public static BindableProperty UseDescriptionAsValueProperty =\n        BindableProperty.Create(\n            nameof(UseDescriptionAsValue),\n            typeof(bool),\n            typeof(SettingsView),\n            false,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.SettingsView\"/> use description\n    /// as value. (Only Android)\n    /// </summary>\n    /// <value><c>true</c> if use description as value; otherwise, <c>false</c>.</value>\n    public bool UseDescriptionAsValue\n    {\n        get { return (bool)GetValue(UseDescriptionAsValueProperty); }\n        set { SetValue(UseDescriptionAsValueProperty, value); }\n    }\n\n    //Only Android\n    /// <summary>\n    /// The show section top bottom border property.\n    /// </summary>\n    public static BindableProperty ShowSectionTopBottomBorderProperty =\n        BindableProperty.Create(\n            nameof(ShowSectionTopBottomBorder),\n            typeof(bool),\n            typeof(SettingsView),\n            true,\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.SettingsView\"/> show section top\n    /// and bottom border. (Only Android)\n    /// </summary>\n    /// <value><c>true</c> if show section top bottom border; otherwise, <c>false</c>.</value>\n    public bool ShowSectionTopBottomBorder\n    {\n        get { return (bool)GetValue(ShowSectionTopBottomBorderProperty); }\n        set { SetValue(ShowSectionTopBottomBorderProperty, value); }\n    }\n\n    /// <summary>\n    /// The scroll to bottom property.\n    /// </summary>\n    public static BindableProperty ScrollToBottomProperty =\n        BindableProperty.Create(\n            nameof(ScrollToBottom),\n            typeof(bool),\n            typeof(SettingsView),\n            default(bool),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.SettingsView\"/> scroll to bottom.\n    /// </summary>\n    /// <value><c>true</c> if scroll to bottom; otherwise, <c>false</c>.</value>\n    public bool ScrollToBottom\n    {\n        get { return (bool)GetValue(ScrollToBottomProperty); }\n        set { SetValue(ScrollToBottomProperty, value); }\n    }\n\n    /// <summary>\n    /// The scroll to top property.\n    /// </summary>\n    public static BindableProperty ScrollToTopProperty =\n        BindableProperty.Create(\n            nameof(ScrollToTop),\n            typeof(bool),\n            typeof(SettingsView),\n            default(bool),\n            defaultBindingMode: BindingMode.TwoWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.SettingsView\"/> scroll to top.\n    /// </summary>\n    /// <value><c>true</c> if scroll to top; otherwise, <c>false</c>.</value>\n    public bool ScrollToTop\n    {\n        get { return (bool)GetValue(ScrollToTopProperty); }\n        set { SetValue(ScrollToTopProperty, value); }\n    }\n\n    /// <summary>\n    /// The computed content height property.\n    /// </summary>\n    public static BindableProperty VisibleContentHeightProperty =\n        BindableProperty.Create(\n            nameof(VisibleContentHeight),\n            typeof(double),\n            typeof(SettingsView),\n            -1d,\n            defaultBindingMode: BindingMode.OneWayToSource\n        );\n\n    /// <summary>\n    /// Gets or sets the height of the computed content.\n    /// </summary>\n    /// <value>The height of the computed content.</value>\n    public double VisibleContentHeight {\n        get { return (double)GetValue(VisibleContentHeightProperty); }\n        set { SetValue(VisibleContentHeightProperty, value); }\n    }\n\n    /// <summary>\n    /// The items source property.\n    /// </summary>\n    public static BindableProperty ItemsSourceProperty =\n        BindableProperty.Create(\n            nameof(ItemsSource),\n            typeof(IEnumerable),\n            typeof(SettingsView),\n            default(IEnumerable),\n            defaultBindingMode: BindingMode.OneWay,\n            propertyChanged: ItemsChanged\n        );\n\n    /// <summary>\n    /// Gets or sets the items source.\n    /// </summary>\n    /// <value>The items source.</value>\n    public IEnumerable ItemsSource {\n        get { return (IEnumerable)GetValue(ItemsSourceProperty); }\n        set { SetValue(ItemsSourceProperty, value); }\n    }\n\n    /// <summary>\n    /// The item template property.\n    /// </summary>\n    public static BindableProperty ItemTemplateProperty =\n        BindableProperty.Create(\n            nameof(ItemTemplate),\n            typeof(DataTemplate),\n            typeof(SettingsView),\n            default(DataTemplate),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the item template.\n    /// </summary>\n    /// <value>The item template.</value>\n    public DataTemplate ItemTemplate {\n        get { return (DataTemplate)GetValue(ItemTemplateProperty); }\n        set { SetValue(ItemTemplateProperty, value); }\n    }\n\n    /// <summary>\n    /// The template start index property.\n    /// </summary>\n    public static BindableProperty TemplateStartIndexProperty =\n        BindableProperty.Create(\n            nameof(TemplateStartIndex),\n            typeof(int),\n            typeof(SettingsView),\n            default(int),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets the index of the template start.\n    /// </summary>\n    /// <value>The index of the template start.</value>\n    public int TemplateStartIndex\n    {\n        get { return (int)GetValue(TemplateStartIndexProperty); }\n        set { SetValue(TemplateStartIndexProperty, value); }\n    }\n\n    /// <summary>\n    /// The show arrow indicator for android property.\n    /// </summary>\n    public static BindableProperty ShowArrowIndicatorForAndroidProperty =\n        BindableProperty.Create(\n            nameof(ShowArrowIndicatorForAndroid),\n            typeof(bool),\n            typeof(SettingsView),\n            default(bool),\n            defaultBindingMode: BindingMode.OneWay\n        );\n\n    /// <summary>\n    /// Gets or sets a value indicating whether this <see cref=\"T:AiForms.Renderers.SettingsView\"/> show arrow\n    /// indicator for android.\n    /// </summary>\n    /// <value><c>true</c> if show arrow indicator for android; otherwise, <c>false</c>.</value>\n    public bool ShowArrowIndicatorForAndroid {\n        get { return (bool)GetValue(ShowArrowIndicatorForAndroidProperty); }\n        set { SetValue(ShowArrowIndicatorForAndroidProperty, value); }\n    }\n\n    int templatedItemsCount;\n\n    static void ItemsChanged(BindableObject bindable, object oldValue, object newValue)\n    {\n        var settingsView = (SettingsView)bindable;\n\n        if (settingsView.ItemTemplate == null) {\n            return;\n        }\n\n        IList oldValueAsEnumerable;\n        IList newValueAsEnumerable;\n        try\n        {\n            oldValueAsEnumerable = oldValue as IList;\n            newValueAsEnumerable = newValue as IList;\n        }\n        catch (Exception e)\n        {\n            throw;\n        }\n\n\n        var oldObservableCollection = oldValue as INotifyCollectionChanged;\n\n        if (oldObservableCollection != null) {\n            oldObservableCollection.CollectionChanged -= settingsView.OnItemsSourceCollectionChanged;\n        }\n\n        // keep the platform from notifying itemchanged event.\n        settingsView.Root.CollectionChanged -= settingsView.OnCollectionChanged;\n\n        if (oldValueAsEnumerable != null)\n        {\n            for (var i = oldValueAsEnumerable.Count - 1; i >= 0; i--)\n            {\n                settingsView.Root.RemoveAt(settingsView.TemplateStartIndex + i);\n            }\n        }\n\n        if (newValueAsEnumerable != null)\n        {\n            for (var i = 0; i < newValueAsEnumerable.Count; i++)\n            {\n                var view = CreateChildViewFor(settingsView.ItemTemplate, newValueAsEnumerable[i], settingsView);\n                settingsView.Root.Insert(settingsView.TemplateStartIndex + i, view);\n            }\n            settingsView.templatedItemsCount = newValueAsEnumerable.Count;\n        }\n\n        settingsView.Root.CollectionChanged += settingsView.OnCollectionChanged;\n\n        var newObservableCollection = newValue as INotifyCollectionChanged;\n\n        if (newObservableCollection != null) {\n            newObservableCollection.CollectionChanged += settingsView.OnItemsSourceCollectionChanged;\n        }\n\n\n        // Notify manually ModelChanged.\n        settingsView.OnModelChanged();\n    }\n\n    void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        if (e.Action == NotifyCollectionChangedAction.Replace) {\n\n            //Root.RemoveAt(e.OldStartingIndex + TemplateStartIndex);\n\n            var item = e.NewItems[0];\n            var view = CreateChildViewFor(this.ItemTemplate, item, this);\n\n            //Root.Insert(e.NewStartingIndex + TemplateStartIndex, view);\n            Root[e.NewStartingIndex + TemplateStartIndex] = view;\n        }\n\n        else if (e.Action == NotifyCollectionChangedAction.Add) {\n            if (e.NewItems != null) {\n                for (var i = 0; i < e.NewItems.Count; ++i) {\n                    var item = e.NewItems[i];\n                    var view = CreateChildViewFor(this.ItemTemplate, item, this);\n\n                    Root.Insert(i + e.NewStartingIndex + TemplateStartIndex, view);\n                    templatedItemsCount++;\n                }\n            }\n        }\n\n        else if (e.Action == NotifyCollectionChangedAction.Remove) {\n            if (e.OldItems != null) {\n                Root.RemoveAt(e.OldStartingIndex + TemplateStartIndex);\n                templatedItemsCount--;\n            }\n        }\n\n        else if (e.Action == NotifyCollectionChangedAction.Reset) {\n\n            Root.CollectionChanged -= OnCollectionChanged;\n            IList source = ItemsSource as IList;\n            for (var i = templatedItemsCount - 1; i >= 0; i--)\n            {\n                Root.RemoveAt(TemplateStartIndex + i);\n            }\n            Root.CollectionChanged += OnCollectionChanged;\n            templatedItemsCount = 0;\n            OnModelChanged();\n        }\n\n        else {\n            return;\n        }\n\n    }\n\n    internal void SendItemDropped(Section section,CellBase cell)\n    {\n        var eventArgs = new DropEventArgs(section, cell);\n        ItemDropped?.Invoke(this, eventArgs);\n        ItemDroppedCommand?.Execute(eventArgs);\n    }\n\n    static Section CreateChildViewFor(DataTemplate template, object item, BindableObject container)\n    {\n        var selector = template as DataTemplateSelector;\n\n        if (selector != null) {\n            template = selector.SelectTemplate(item, container);\n        }\n\n        //Binding context\n        template.SetValue(BindableObject.BindingContextProperty, item);\n\n        return (Section)template.CreateContent();\n    }\n}\n"
  },
  {
    "path": "SettingsView/SettingsView.cs",
    "content": "﻿using System.Collections.Specialized;\nusing System.ComponentModel;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Settings view.\n/// </summary>\n[ContentProperty(\"Root\")]\npublic partial class SettingsView : View\n{\n    internal static Action _clearCache;\n    /// <summary>\n    /// Clears the cache.\n    /// </summary>\n    public static void ClearCache()\n    {\n        _clearCache?.Invoke();\n    }\n\n    /// <summary>\n    /// Gets or sets the model.\n    /// </summary>\n    /// <value>The model.</value>\n    public SettingsModel Model { get; set; }\n    /// <summary>\n    /// Occurs when model changed.\n    /// </summary>\n    public event EventHandler ModelChanged;\n    /// <summary>\n    /// Occurs when collection changed.\n    /// </summary>\n    public event NotifyCollectionChangedEventHandler CollectionChanged;\n    /// <summary>\n    /// Occurs when section collection changed.\n    /// </summary>\n    public event NotifyCollectionChangedEventHandler SectionCollectionChanged;\n    /// <summary>\n    /// Occurs when section property changed.\n    /// </summary>\n    public event PropertyChangedEventHandler SectionPropertyChanged;\n    /// <summary>\n    /// Occurs when cell property changed.\n    /// </summary>\n    public event EventHandler<CellPropertyChangedEventArgs> CellPropertyChanged;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"T:AiForms.Renderers.SettingsView\"/> class.\n    /// </summary>\n    public SettingsView()\n    {\n        VerticalOptions = HorizontalOptions = LayoutOptions.Fill;\n        Root = new SettingsRoot();\n        Model = new SettingsModel(Root);\n    }\n\n    SettingsRoot _root;\n    /// <summary>\n    /// Gets or sets the root.\n    /// </summary>\n    /// <value>The root.</value>\n    public SettingsRoot Root\n    {\n        get { return _root; }\n        set {\n            if (_root != null) {\n                _root.SectionPropertyChanged -= OnSectionPropertyChanged;\n                _root.CollectionChanged -= OnCollectionChanged;\n                _root.SectionCollectionChanged -= OnSectionCollectionChanged;\n                _root.CellPropertyChanged -= OnCellPropertyChanged;\n            }\n\n            _root = value;\n\n            //transfer binding context to the children (maybe...)\n            SetInheritedBindingContext(_root, BindingContext);\n\n            _root.SectionPropertyChanged += OnSectionPropertyChanged;\n            _root.CollectionChanged += OnCollectionChanged;\n            _root.SectionCollectionChanged += OnSectionCollectionChanged;\n            _root.CellPropertyChanged += OnCellPropertyChanged;\n            OnModelChanged();\n        }\n    }\n\n    /// <summary>\n    /// Ons the binding context changed.\n    /// </summary>\n    protected override void OnBindingContextChanged()\n    {\n        base.OnBindingContextChanged();\n        if (Root != null)\n            SetInheritedBindingContext(Root, BindingContext);\n    }\n\n    void OnSectionPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)\n    {\n        SectionPropertyChanged?.Invoke(sender, e);\n    }\n\n    void OnCellPropertyChanged(object sender, CellPropertyChangedEventArgs e)\n    {\n        CellPropertyChanged?.Invoke(sender, e);\n    }\n\n    /// <summary>\n    /// Ons the property changed.\n    /// </summary>\n    /// <param name=\"propertyName\">Property name.</param>\n    protected override void OnPropertyChanged(string propertyName = null)\n    {\n        base.OnPropertyChanged(propertyName);\n        if (propertyName == HasUnevenRowsProperty.PropertyName ||\n            propertyName == HeaderHeightProperty.PropertyName ||\n            propertyName == HeaderFontSizeProperty.PropertyName ||\n            propertyName == HeaderFontFamilyProperty.PropertyName ||\n            propertyName == HeaderFontAttributesProperty.PropertyName ||\n            propertyName == HeaderTextColorProperty.PropertyName ||\n            propertyName == HeaderBackgroundColorProperty.PropertyName ||\n            propertyName == HeaderTextVerticalAlignProperty.PropertyName ||\n            propertyName == HeaderPaddingProperty.PropertyName ||\n            propertyName == FooterFontSizeProperty.PropertyName ||\n            propertyName == FooterFontFamilyProperty.PropertyName ||\n            propertyName == FooterFontAttributesProperty.PropertyName ||\n            propertyName == FooterTextColorProperty.PropertyName ||\n            propertyName == FooterBackgroundColorProperty.PropertyName ||\n            propertyName == FooterPaddingProperty.PropertyName\n           ) {\n\n            OnModelChanged();\n        }\n    }\n\n    /// <summary>\n    /// CollectionChanged by the section\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">E.</param>\n    public void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        if(e.NewItems != null)\n        {\n            foreach(var section in e.NewItems.Cast<Section>())\n            {\n                section.Parent = this;\n\n                if (section.HeaderView != null)\n                {\n                    section.HeaderView.Parent = this;\n                }\n                if (section.FooterView != null)\n                {\n                    section.FooterView.Parent = this;\n                }\n                foreach (var cell in section)\n                {\n                    var context = cell.BindingContext;\n                    cell.Parent = this; // When setting the parent, the bindingcontext is updated too.\n                    if (context != null)\n                    {\n                        cell.BindingContext = context; // so set the original bindingcontext again.\n                    }\n                }\n            }\n        }\n        CollectionChanged?.Invoke(sender, e);\n    }\n\n    /// <summary>\n    /// CollectionChanged by the child in section\n    /// </summary>\n    /// <param name=\"sender\">Sender.</param>\n    /// <param name=\"e\">The ${ParameterType} instance containing the event data.</param>\n    public void OnSectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        if (e.NewItems != null)\n        {\n            foreach(var cell in e.NewItems.Cast<CellBase>())\n            {\n                cell.Parent = this;\n            }\n        }\n        SectionCollectionChanged?.Invoke(sender, e);\n    }\n\n    void OnModelChanged()\n    {\n        if(Root == null)\n        {\n            return;\n        }\n\n        foreach(var section in Root)\n        {\n            section.Parent = this;\n            if (section.HeaderView != null)\n            {\n                section.HeaderView.Parent = this;\n            }\n            if (section.FooterView != null)\n            {\n                section.FooterView.Parent = this;\n            }\n            foreach (var cell in section)\n            {\n                var context = cell.BindingContext;\n                cell.Parent = this; // When setting the parent, the bindingcontext is updated too.\n                if (context != null)\n                {\n                    cell.BindingContext = context; // so set the original bindingcontext again.\n                }\n            }\n        }\n\n        var cells = Root?.SelectMany(r => r);\n        if (cells == null)\n        {\n            return;\n        }\n\n\n        //notify Native\n        if (ModelChanged != null)\n            ModelChanged(this, EventArgs.Empty);\n\n    }\n}\n"
  },
  {
    "path": "SettingsView/SettingsView.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\r\n\r\n\t<PropertyGroup>\r\n\t\t<TargetFrameworks>net9.0;net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks>\r\n\t\t<UseMaui>true</UseMaui>\r\n\t\t<MauiVersion>9.0.120</MauiVersion>\r\n\t\t<SingleProject>true</SingleProject>\r\n\t\t<ImplicitUsings>enable</ImplicitUsings>\r\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'\">14.2</SupportedOSPlatformVersion>\r\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'\">14.2</SupportedOSPlatformVersion>\r\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'\">27.0</SupportedOSPlatformVersion>\r\n\t\t<RootNamespace>AiForms.Settings</RootNamespace>\r\n\r\n\t\t<PackageId>AiForms.Maui.SettingsView</PackageId>\r\n\t\t<Authors>kamu</Authors>\r\n\t\t<Company>kamu</Company>\r\n\t\t<Product>SettingsView for .NET MAUI</Product>\r\n\t\t<PackageProjectUrl>https://github.com/muak/AiForms.Maui.SettingsView</PackageProjectUrl>\r\n\t\t<PackageLicenseUrl>https://github.com/muak/AiForms.Maui.SettingsView/blob/master/LICENSE.txt</PackageLicenseUrl>\r\n\t\t<PackageIconUrl>https://raw.githubusercontent.com/muak/AiForms.Maui.SettingsView/master/images/icon.png</PackageIconUrl>\r\n\t\t<Description>This is a flexible TableView specialized in settings for Android / iOS. \r\nThere are various cells such as (LabelCell,ButtonCell,CommandCell,SwitchCell,CheckboxCell,RadioCell,PickerCell,EntryCell,NumberPickerCell,TimePickerCell,DatePickerCell,CustomCell)</Description>\r\n\t\t<PackageReleaseNotes>\r\n\t\t\t.NET9 supported\r\n        </PackageReleaseNotes>\r\n\t\t<PackageTags>MAUI TableView Cell Setting Configuration Option ListView UITableView RecyclerView ReOrder DragDrop</PackageTags>\r\n\t</PropertyGroup>\r\n\r\n\t<PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net9.0-ios|AnyCPU'\">\r\n\t  <EnableCodeSigning>False</EnableCodeSigning>\r\n\t  <CreatePackage>false</CreatePackage>\r\n\t</PropertyGroup>\r\n\t<PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\r\n\t  <WarningLevel>4</WarningLevel>\r\n\t</PropertyGroup>\r\n\t<PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\r\n\t  <DebugSymbols>true</DebugSymbols>\r\n\t  <WarningLevel>4</WarningLevel>\r\n\t  <DebugType>pdbonly</DebugType>\r\n      <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n\t</PropertyGroup>\r\n\t<PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-ios|AnyCPU'\">\r\n\t  <DebugSymbols>true</DebugSymbols>\r\n\t  <EnableCodeSigning>false</EnableCodeSigning>\r\n\t</PropertyGroup>\r\n\r\n\t<!-- Android -->\r\n\t<ItemGroup Condition=\"$(TargetFramework.StartsWith('net9.0-android')) != true\">\r\n\t\t<Compile Remove=\"**\\**\\*.Android.cs\" />\r\n\t\t<None Include=\"**\\**\\*.Android.cs\" Exclude=\"$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)\" />\r\n\t\t<Compile Remove=\"**\\Android\\**\\*.cs\" />\r\n\t\t<None Include=\"**\\Android\\**\\*.cs\" Exclude=\"$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)\" />  \r\n\t</ItemGroup>\r\n\r\n\t<!-- iOS / Mac -->\r\n\t<ItemGroup Condition=\"$(TargetFramework.StartsWith('net9.0-ios')) != true AND $(TargetFramework.StartsWith('net9.0-maccatalyst')) != true\">\r\n\t\t<Compile Remove=\"**\\**\\*.iOS.cs\" />\r\n\t\t<None Include=\"**\\**\\*.iOS.cs\" Exclude=\"$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)\" />\r\n\t\t<Compile Remove=\"**\\iOS\\**\\*.cs\" />\r\n\t\t<None Include=\"**\\iOS\\**\\*.cs\" Exclude=\"$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)\" />  \r\n\t</ItemGroup>\r\n\r\n\t<!-- NET -->\r\n\t<ItemGroup Condition=\"'$(TargetFramework)' != 'net9.0'\">\r\n\t\t<Compile Remove=\"**\\**\\*.Net.cs\" />\r\n\t\t<None Include=\"**\\**\\*.Net.cs\" Exclude=\"$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)\" />\r\n\t</ItemGroup>\r\n\t\r\n\r\n\t<ItemGroup>\r\n\t  <PackageReference Include=\"Microsoft.Maui.Controls\" Version=\"$(MauiVersion)\" />\r\n\t  <PackageReference Include=\"Microsoft.Maui.Controls.Compatibility\" Version=\"$(MauiVersion)\" />\r\n\t</ItemGroup>\r\n\r\n</Project>\r\n"
  },
  {
    "path": "SettingsView/SettingsViewConfiguration.cs",
    "content": "﻿using System;\nnamespace AiForms.Settings;\n\ninternal static class SettingsViewConfiguration\n{\n    internal static bool ShouldAutoDisconnect { get; set; }\n}\n\n"
  },
  {
    "path": "SettingsView/SizeTypeConverter.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing System.Globalization;\n\nnamespace AiForms.Settings;\n\r\n/// <summary>\n/// Size converter.\n/// </summary>\npublic class SizeConverter : TypeConverter\n{\n    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)\n    {\n        if (value is string valueStr)\n        {\n            var size = valueStr.Split(',');\n\n            switch (size.Length)\n            {\n                case 1:\n                    var w = double.Parse(size[0]);\n                    return new Size(w, w);\n                case 2:\n                    return new Size(double.Parse(size[0]), double.Parse(size[1]));\n            }\n        }\n        throw new InvalidOperationException($\"Cannot convert \\\"{value}\\\" into {typeof(Size)}\");\n    }    \n}\n"
  },
  {
    "path": "global.json",
    "content": "{\n  \"sdk\": {\n    \"version\": \"9.0.311\",\n    \"workloadVersion\": \"9.0.311\"\n  }\n}"
  }
]