diff --git a/.all-contributorsrc b/.all-contributorsrc index e0b0dbeeca29..384c68f36974 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -370,7 +370,8 @@ "profile": "https://github.com/pkar70", "contributions": [ "code", - "test" + "test", + "doc" ] }, { @@ -507,6 +508,87 @@ "contributions": [ "doc" ] + }, + { + "login": "mrassili", + "name": "Marouane R", + "avatar_url": "https://avatars0.githubusercontent.com/u/25288435?v=4", + "profile": "https://mrassili.com", + "contributions": [ + "doc" + ] + }, + { + "login": "avinasjha", + "name": "Avinash Jha", + "avatar_url": "https://avatars1.githubusercontent.com/u/56090532?v=4", + "profile": "https://github.com/avinasjha", + "contributions": [ + "doc" + ] + }, + { + "login": "khyativalera", + "name": "Khyati Valera", + "avatar_url": "https://avatars3.githubusercontent.com/u/47522632?v=4", + "profile": "https://github.com/khyativalera", + "contributions": [ + "doc" + ] + }, + { + "login": "pushkyn", + "name": "Alex", + "avatar_url": "https://avatars0.githubusercontent.com/u/3326427?v=4", + "profile": "https://github.com/pushkyn", + "contributions": [ + "doc" + ] + }, + { + "login": "m1guelpf", + "name": "Miguel Piedrafita", + "avatar_url": "https://avatars0.githubusercontent.com/u/23558090?v=4", + "profile": "https://miguelpiedrafita.com", + "contributions": [ + "doc" + ] + }, + { + "login": "gagandeepp", + "name": "Gagan Deep", + "avatar_url": "https://avatars1.githubusercontent.com/u/34858937?v=4", + "profile": "http://www.linkedin.com/in/gagandeepp", + "contributions": [ + "doc" + ] + }, + { + "login": "RobJenks", + "name": "RobJenks", + "avatar_url": "https://avatars0.githubusercontent.com/u/3159730?v=4", + "profile": "https://github.com/RobJenks", + "contributions": [ + "doc" + ] + }, + { + "login": "cTxplorer", + "name": "Pratik Gadhiya", + "avatar_url": "https://avatars0.githubusercontent.com/u/28287478?v=4", + "profile": "https://github.com/cTxplorer", + "contributions": [ + "doc" + ] + }, + { + "login": "mkwhalen", + "name": "MacKenzie Whalen", + "avatar_url": "https://avatars0.githubusercontent.com/u/17869199?v=4", + "profile": "https://github.com/mkwhalen", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 5, diff --git a/.azure-devops-android-tests.yml b/.azure-devops-android-tests.yml index 7c84ea04978e..5d7092cf3d8b 100644 --- a/.azure-devops-android-tests.yml +++ b/.azure-devops-android-tests.yml @@ -24,8 +24,7 @@ jobs: env: BUILD_SOURCESDIRECTORY: "$(build.sourcesdirectory)" BUILD_ARTIFACTSTAGINGDIRECTORY: "$(build.artifactstagingdirectory)" - - + - task: PublishTestResults@2 condition: always() inputs: diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 000000000000..5eb028653551 --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,23 @@ +# Configuration for welcome - https://github.com/behaviorbot/welcome + +## Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome + +# Comment to be posted to on first time issues +#newIssueWelcomeComment: > +# Thanks for opening your first issue here! Be sure to follow the issue template! + +## Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome + +# Comment to be posted to on PRs from first time contributors in your repository +#newPRWelcomeComment: > +# Thanks for opening this pull request! Please check out our contributing guidelines. + +## Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge + +# Comment to be posted to on pull requests merged by a first time user +firstPRMergeComment: > + Congrats on your first pull-request! We ❤ the people who are involved in this project, and we’d love to pay it forward by [sending you some swag](https://forms.office.com/Pages/ResponsePage.aspx?id=Ye9TbdG2UEGuC0O5DnXgzai0HkTgxONNjPmzuZ5zgdRUQzFJMVBPSU8xWDBUUlNOTExCWFUwQjNBNy4u). If you have any feedback (or ideas how to improve Uno as a open-source project) please [open a feedback issue](https://github.com/unoplatform/uno/issues/new?labels=kind%2Ffeedback%2C+triage%2Funtriaged&template=feedback.md). +
+ ![giphy](https://user-images.githubusercontent.com/127353/66220548-37ae4d00-e69b-11e9-8a16-f08f87b3b27c.gif) +
+ Merci beaucoup 👋 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 698b5a325d13..df010d2cdcfd 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -4,7 +4,7 @@ This project has adopted the code of conduct defined by the Contributor Covenant As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. -We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. +We are committed to making participation in this project a harassment-free experience for everyone, regardless of the level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: @@ -21,6 +21,6 @@ By adopting this Code of Conduct, project maintainers commit themselves to fairl This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at conduct@platform.uno. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. +Instances of abusive, harassing or otherwise, unacceptable behavior may be reported by contacting a project maintainer at conduct@platform.uno. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality concerning the reporter of an incident. This Code of Conduct is adapted from the Contributor Covenant, version 1.3.0, available from http://contributor-covenant.org/version/1/3/0/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3c1516a3ff49..465d0b2d6c99 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,8 @@ We want to hear about your experience, scenarios, and requirements. ### Report a bug -If you think you've found a bug, please log a new issue in the [Uno Platform GitHub issue tracker](https://github.com/nventive/Uno/issues). When filing issues, please use our [bug filing template](.github/ISSUE_TEMPLATE.md). +If you think you've found a bug, please log a new issue in the [Uno Platform GitHub issue tracker](https://github.com/nventive/Uno/issues). When filing issues, please use our [bug filing template](https://github.com/unoplatform/uno/blob/master/.github/ISSUE_TEMPLATE/bug-report.md). + The best way to get your bug fixed is to be as detailed as you can be about the problem. Providing a minimal project with steps to reproduce the problem is ideal. Here are questions you can answer before you file a bug to make sure you're not missing any important information. diff --git a/README.md b/README.md index 8056c71fe868..131ea7ae302c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ -# Uno Platform - Build Mobile, Desktop and WebAssembly apps with C# and XAML. Today. -[![Gitter](https://badges.gitter.im/uno-platform/Lobby.svg)](https://gitter.im/uno-platform/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=unoplatform/uno)](https://dependabot.com) [![All Contributors](https://img.shields.io/badge/all_contributors-50-orange.svg?style=flat-square)](#contributors) [![GitHub stars](https://img.shields.io/github/stars/unoplatform/uno.svg?style=social&label=Star&maxAge=2592000)](https://github.com/unoplatform/uno/stargazers/) + + + +## Build Mobile, Desktop and WebAssembly apps with C# and XAML. Today. + +[![GitHub stars](https://img.shields.io/azure-devops/build/uno-platform/1dd81cbd-cb35-41de-a570-b0df3571a196/5/master?label=master)](https://uno-platform.visualstudio.com/Uno%20Platform/_build?definitionId=5) +[![GitHub stars](https://img.shields.io/azure-devops/build/uno-platform/1dd81cbd-cb35-41de-a570-b0df3571a196/5/master?label=release/beta/Batman)](https://uno-platform.visualstudio.com/Uno%20Platform/_build?definitionId=5) +[![GitHub stars](https://img.shields.io/azure-devops/build/uno-platform/1dd81cbd-cb35-41de-a570-b0df3571a196/5/master?label=release/stable/Batman)](https://uno-platform.visualstudio.com/Uno%20Platform/_build?definitionId=5) + [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=unoplatform/uno)](https://dependabot.com) +[![Gitter](https://badges.gitter.im/uno-platform/Lobby.svg)](https://gitter.im/uno-platform/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + [![Twitter Followers](https://img.shields.io/twitter/follow/unoplatform?label=follow%20%40unoplatform&style=flat)](https://twitter.com/unoplatform) [![GitHub Stars](https://img.shields.io/github/stars/unoplatform/uno?label=github%20stars)](https://github.com/unoplatform/uno/stargazers/) [![NuGet Downloads](https://img.shields.io/nuget/dt/uno.ui.svg)](https://www.nuget.org/packages/uno.ui) [![All Contributors](https://img.shields.io/badge/all_contributors-59-orange.svg?style=flat-square)](#contributors) # What is the Uno Platform @@ -14,40 +23,40 @@ Visit [our documentation](doc/articles/intro.md) for more details. ## Prerequisites * [**Visual Studio 2017 15.5 or later**](https://visualstudio.microsoft.com/), with: - * **Universal Windows Platform component** installed + * **Universal Windows Platform component** installed. - * **Xamarin component** installed (for Android and iOS development) + * **Xamarin component** installed (for Android and iOS development). - * **ASP.NET/web component** installed, along with .NET Core 2.2 (for WASM development) + * **ASP.NET/web component** installed, along with .NET Core 2.2 (for WASM development). To easily create a multi-platform application: -* Install the [Uno Solution Template Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=nventivecorp.uno-platform-addin) +* Install the [Uno Solution Template Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=nventivecorp.uno-platform-addin). * Create a new C# solution using the **Cross-Platform App (Uno Platform)** template, from Visual Studio's **Start Page**. See the complete [Getting Started guide](https://platform.uno/docs/articles/get-started.html) for more information. For a larger example and features demo: -* Visit the [Uno Gallery and Playground](https://github.com/nventive/Uno.Playground) repository -* Try the [WebAssembly Uno Playground](https://playground.platform.uno) live in your browser +* Visit the [Uno Gallery and Playground](https://github.com/nventive/Uno.Playground) repository. +* Try the [WebAssembly Uno Playground](https://playground.platform.uno) live in your browser. # Uno Features * Supported platforms: * Windows (via the standard UWP Toolkit) * iOS and Android (via [Xamarin](https://www.visualstudio.com/xamarin/)) * WebAssembly through the [Mono Wasm SDK](https://github.com/mono/mono/blob/master/sdks/wasm/README.md) -* Dev loop +* Dev loop: * Develop on Windows first using Visual Studio * [XAML Edit and Continue](https://blogs.msdn.microsoft.com/visualstudio/2016/04/06/ui-development-made-easier-with-xaml-edit-continue/) for live XAML edition on each key stroke * [C# Edit and Continue](https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-use-edit-and-continue-csharp) * Validate on other platforms as late as possible * Experimental XAML Hot Reload for WebAssembly, iOS and Android * [Uno.UITest](https://github.com/unoplatform/Uno.UITest), a library to create Cross-Platform UI Tests for WebAssembly, iOS and Android. -* Cross Platform Controls +* Cross Platform Controls: * [Control Templating](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/control-templates) * [Data Templating](https://code.msdn.microsoft.com/Data-Binding-in-UWP-b5c98114) * [Styling](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/xaml-styles) * [Rich Animations](https://docs.microsoft.com/en-us/windows/uwp/design/motion/xaml-animation) -* UWP Code Support +* UWP Code Support: * [Windows Community Toolkit](https://github.com/nventive/Uno.WindowsCommunityToolkit) * [MVVM Light Toolkit](https://github.com/nventive/uno.mvvmlight) * [Microsoft XAML Behaviors](https://github.com/nventive/Uno.XamlBehaviors) @@ -61,30 +70,30 @@ For a larger example and features demo: * [Rx.NET](https://github.com/reactiveui/Reactive.Wasm) * [ColorCode-Universal](https://github.com/nventive/Uno.ColorCode-Universal) * Any UWP project -* Responsive Design +* Responsive Design: * [Visual State Manager](https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.VisualStateManager) * [State Triggers](https://blogs.msdn.microsoft.com/mvpawardprogram/2017/02/07/state-triggers-uwp-apps/) * [Adaptive Triggers](https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.AdaptiveTrigger) -* Platform Specific +* Platform Specific: * Native controls and properties via [conditional XAML](doc/articles/using-uno-ui.md#supporting-multiple-platforms-in-xaml-files) * Any of the existing Xamarin iOS/Android libraries available -* Xamarin.Forms Renderers +* Xamarin.Forms Renderers: * [Uno Platform WebAssembly Renderers for Xamarin.Forms](https://github.com/unoplatform/Uno.Xamarin.Forms.Platform) # Live WebAssembly Apps Here's a list of live apps made with the Uno Platform for WebAssembly. -* The [Uno Platform Playground](https://playground.platform.uno) ([Source](https://github.com/nventive/Uno.Playground)) +* The [Uno Platform Playground](https://playground.platform.uno) ([Source](https://github.com/nventive/Uno.Playground)). * The [Uno Calculator](https://calculator.platform.uno), a simple yet powerful iOS/Android/WebAssembly C# port of the calculator that ships with Windows ([Source](https://github.com/unoplatform/calculator)). Also try the [pink theme](https://calculator.platform.uno/?theme=pink), the [iOS version](https://apps.apple.com/app/id1464736591) or the [Android version](https://play.google.com/store/apps/details?id=uno.platform.calculator). -* The [Xaml Controls Gallery](https://xamlcontrolsgallery.platform.uno/) ([Source](https://github.com/nventive/Uno.Xaml-Controls-Gallery)) -* [SkiaSharp fork for the Uno Platform](https://skiasharp-wasm.platform.uno/), Skia is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library ([Source](https://github.com/unoplatform/Uno.SkiaSharp)) +* The [Xaml Controls Gallery](https://xamlcontrolsgallery.platform.uno/) ([Source](https://github.com/nventive/Uno.Xaml-Controls-Gallery)). +* [SkiaSharp fork for the Uno Platform](https://skiasharp-wasm.platform.uno/), Skia is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library ([Source](https://github.com/unoplatform/Uno.SkiaSharp)). * The [Uno.WindowsCommunityToolkit](https://windowstoolkit-wasm.platform.uno/), ([Source](https://github.com/nventive/Uno.WindowsCommunityToolkit)) * The [Uno.Lottie](https://lottie.platform.uno/), a sample that uses the [AnimatedVisualPlayer](https://docs.microsoft.com/en-us/uwp/api/microsoft.ui.xaml.controls.animatedvisualplayer) ([Source](https://github.com/nventive/Uno.LottieSample)) -* The [Uno.RoslynQuoter](http://roslynquoter-wasm.platform.uno/), a [Roslyn](https://github.com/dotnet/roslyn) based C# analysis tool ([Source](https://github.com/nventive/Uno.RoslynQuoter)) +* The [Uno.RoslynQuoter](https://roslynquoter-wasm.platform.uno/), a [Roslyn](https://github.com/dotnet/roslyn) based C# analysis tool ([Source](https://github.com/nventive/Uno.RoslynQuoter)) * The [Uno.BikeSharing360 App](http://bikerider-wasm.platform.uno/), a Xamarin.Forms app running on top of Uno for WebAssembly ([Source](https://github.com/nventive/Uno.BikeSharing360_MobileApps)) * The [Uno.WindowsStateTriggers App](http://winstatetriggers-wasm.platform.uno/), a demo of the [Morten's WindowsStateTriggers](https://github.com/dotMorten/WindowsStateTriggers) ([Source](https://github.com/nventive/Uno.WindowsStateTriggers)) -* The [SQLite + Entity Framework Core App](http://sqliteefcore-wasm.platform.uno), a demo of the combination of [Roslyn](https://github.com/dotnet/roslyn), [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/), [SQLite](https://github.com/nventive/Uno.SQLitePCLRaw.Wasm) and the Uno Platform to manipulate an in-browser database. +* The [SQLite + Entity Framework Core App](https://sqliteefcore-wasm.platform.uno), a demo of the combination of [Roslyn](https://github.com/dotnet/roslyn), [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/), [SQLite](https://github.com/nventive/Uno.SQLitePCLRaw.Wasm) and the Uno Platform to manipulate an in-browser database. * The [Uno.WebSockets App](https://websockets-wasm.platform.uno), a demo of System.Net.WebSocket running from WebAssembly ([Source](https://github.com/nventive/Uno.Wasm.WebSockets)) * A [mono-wasm AOT RayTracer](https://raytracer-mono-aot.platform.uno/) @@ -153,7 +162,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Massimo Cacchiotti
Massimo Cacchiotti

💻 rfrappier
rfrappier

📖 Furkan Kambay
Furkan Kambay

📖 - pkar70
pkar70

💻 ⚠️ + pkar70
pkar70

💻 ⚠️ 📖 Hugo van Kemenade
Hugo van Kemenade

📖 @@ -176,6 +185,19 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Alexey Pyltsyn
Alexey Pyltsyn

📖 José Antonio Chio
José Antonio Chio

📖 + + Marouane R
Marouane R

📖 + Avinash Jha
Avinash Jha

📖 + Khyati Valera
Khyati Valera

📖 + Alex
Alex

📖 + Miguel Piedrafita
Miguel Piedrafita

📖 + + + Gagan Deep
Gagan Deep

📖 + RobJenks
RobJenks

📖 + Pratik Gadhiya
Pratik Gadhiya

📖 + MacKenzie Whalen
MacKenzie Whalen

📖 + diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md index 17541754c11e..c8105f2672e5 100644 --- a/THIRD-PARTY-NOTICES.md +++ b/THIRD-PARTY-NOTICES.md @@ -1,7 +1,7 @@ -The Uno Platform uses third-party libraries or other resources that may be -distributed under licenses different than the Uno Platform software. +The Uno Platform uses third-party libraries and resources that may be +distributed under licenses different from the Uno Platform software. -In the event that we accidentally failed to list a required notice, please +In the event of accidental failure to list a required notice, please bring it to our attention. Post an issue at : https://github.com/nventive/Uno/issues diff --git a/build/GetMsBuildVersion.targets b/build/GetMsBuildVersion.targets deleted file mode 100644 index 2680855f247d..000000000000 --- a/build/GetMsBuildVersion.targets +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/Uno.UI.Build.csproj b/build/Uno.UI.Build.csproj index db65e6e57952..9d1dcf90951c 100644 --- a/build/Uno.UI.Build.csproj +++ b/build/Uno.UI.Build.csproj @@ -56,8 +56,8 @@ - - + http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd @@ -202,6 +202,4 @@ - - diff --git a/build/Uno.UI.Lottie.nuspec b/build/Uno.UI.Lottie.nuspec index 05aaf92291dd..5f13a2c22ad6 100644 --- a/build/Uno.UI.Lottie.nuspec +++ b/build/Uno.UI.Lottie.nuspec @@ -7,7 +7,8 @@ nventive nventive false - https://github.com/nventive/Uno + https://platform.uno/ + Apache-2.0 https://nv-assets.azurewebsites.net/logos/uno.png Support for Lottie on Uno.UI. diff --git a/build/Uno.UI.WpfHost.nuspec b/build/Uno.UI.WpfHost.nuspec index 28210e859974..00802943fc62 100644 --- a/build/Uno.UI.WpfHost.nuspec +++ b/build/Uno.UI.WpfHost.nuspec @@ -7,7 +7,8 @@ nventive nventive false - https://github.com/nventive/Uno + https://platform.uno/ + Apache-2.0 https://nv-assets.azurewebsites.net/logos/uno.png A WPF host for the WebAssembly build on Uno.UI Copyright (C) 2015-2019 nventive inc. - all rights reserved diff --git a/build/Uno.UI.nuspec b/build/Uno.UI.nuspec index 68ca87d76079..4ce68648a99c 100644 --- a/build/Uno.UI.nuspec +++ b/build/Uno.UI.nuspec @@ -7,7 +7,8 @@ nventive nventive false - https://github.com/nventive/Uno + https://platform.uno/ + Apache-2.0 https://nv-assets.azurewebsites.net/logos/uno.png Build Mobile, Desktop and WebAssembly apps with C# and XAML. Today. Open source and professionally supported. Copyright (C) 2015-2019 nventive inc. - all rights reserved @@ -64,11 +65,11 @@ - + - + diff --git a/build/_HOW-TO-BUILD-AND-DEBUG-APPS.md b/build/_HOW-TO-BUILD-AND-DEBUG-APPS.md index 9742661a6c40..5bd7221d8de4 100644 --- a/build/_HOW-TO-BUILD-AND-DEBUG-APPS.md +++ b/build/_HOW-TO-BUILD-AND-DEBUG-APPS.md @@ -7,8 +7,8 @@ on a real application. To do this, you need to recompile your app using a _debug_ version of Uno­ (or a _Release_ version if you prefer). -> Instead of tweaking your app solution to reference the your custom Uno -> output (because there's many steps to follow and you will have to avoid committing this +> Instead of tweaking your app solution to reference your custom Uno +> output (because there are many steps to follow and you will have to avoid committing this > to source control), we found a simpler way: override the nuget output folder. ## HOW-TO (Steps) @@ -17,7 +17,7 @@ To do this, you need to recompile your app using a _debug_ version of Uno­ 1. In your application project (the one referencing Uno): 1. Make sure to build at least once (to ensure the nuget packages are downloaded) 1. Check in the `project.json` file to get the version of the `Uno.UI` package. - The file should look-like this: + The file should look like this: ``` json ... "dependencies": { @@ -33,7 +33,7 @@ To do this, you need to recompile your app using a _debug_ version of Uno­ (where `Uno.UI.sln` is) and put the version number in it - **on the first line and nothing else is the file**. 1. Build the project for the platform you need (or build all the solution to get all of them). - See below for list of project to compile for each platform... + See below for the list of projects to compile for each platform. 1. Never commit the `nuget_version_override.txt` into source control. It should be ignored by default anyway. diff --git a/doc/articles/Uno.UI.Toolkit.md b/doc/articles/Uno.UI.Toolkit.md index 7307f8534720..cf97f51516b4 100644 --- a/doc/articles/Uno.UI.Toolkit.md +++ b/doc/articles/Uno.UI.Toolkit.md @@ -6,7 +6,7 @@ Those methods are built to have no effect on platform that does not support the ## MenuFlyoutItem - Destructive style -iOS can display `MenuFlyoutItem` to warn user the action will be "destructive". In that case, the button text is display in red. +iOS can display `MenuFlyoutItem` to warn user the action will be "destructive". In that case, the button text is displayed in red. To set a `MenuFlyoutItem` as destructive, add the toolkit namespace to your XAML @@ -36,4 +36,4 @@ And declare your `UICommand` as follow ```csharp var uic = new UICommand("Destructive action"); uic.SetDestructive(true); -``` \ No newline at end of file +``` diff --git a/doc/articles/api-differences.md b/doc/articles/api-differences.md index 332b8c242370..9ea9a99c66e4 100644 --- a/doc/articles/api-differences.md +++ b/doc/articles/api-differences.md @@ -50,10 +50,10 @@ must be set at launch time. Documentation: [`Application.RequestedTheme`](https: On Windows, there are some _themes_ that can target, but there is no way to trigger them. The most known is the `HighContrast` theme. -You can do something similar - an even create totally custom themes - by using the following helper: +You can do something similar - and even create totally custom themes - by using the following helper: ``` csharp - // Set current theme to Hich contrast + // Set current theme to High contrast Uno.UI.RequestedCustomTheme = "HighContrast"; ``` diff --git a/doc/articles/concepts/overview/philosophy-of-uno.md b/doc/articles/concepts/overview/philosophy-of-uno.md index 7c9ae5b0ab1b..dccc8f7649a9 100644 --- a/doc/articles/concepts/overview/philosophy-of-uno.md +++ b/doc/articles/concepts/overview/philosophy-of-uno.md @@ -10,11 +10,11 @@ We stand on the shoulders of giants, Microsoft's tooling is a treat to work wit - [Live Visual Tree](https://docs.microsoft.com/en-us/visualstudio/debugger/inspect-xaml-properties-while-debugging). - [XAML Hot Reload](https://docs.microsoft.com/en-us/visualstudio/debugger/xaml-hot-reload?view=vs-2019) -The promise of the Uno Platform is to enable build your app with those tools and then deploy it to iOS, Android, and the web via WebAssembly.  +The promise of the Uno Platform is to enable building your app with those tools and then deploying it to iOS, Android, and the web via WebAssembly.  ## Create rich, responsive UIs -Bland apps don't quite cut it these days. Strong support for animations, templating, and custom visual effects is a must. When phones come in all sizes and manufacturers are [gouging holes out of the screen area](https://www.cnet.com/pictures/phones-with-notches/), your app's layout had better be responsive.  +Bland apps don't quite cut it these days. Strong support for animations, templating, and custom visual effects is a must. When phones come in all sizes and manufacturers are [gouging holes out of the screen area](https://www.cnet.com/pictures/phones-with-notches/), your app's layout had better been responsive.  ## Let views do views diff --git a/doc/articles/contributing/guidelines/issue-triage.md b/doc/articles/contributing/guidelines/issue-triage.md index d00422258d5c..8e0bf1c4b4a5 100644 --- a/doc/articles/contributing/guidelines/issue-triage.md +++ b/doc/articles/contributing/guidelines/issue-triage.md @@ -24,7 +24,7 @@ These guidelines serves as a primary document for triaging incoming issues to Un ## Security -Security related matters should be disclosed in private [as per the our policy on GitHub](https://github.com/unoplatform/uno/security/policy). If a security matter is raised as an issue, please capture the relevant information, [delete the GitHub issue](https://help.github.com/en/articles/deleting-an-issue) and follow up via email. This [tool can be used to find](https://emailaddress.github.io/) (almost) any GitHub user's email address. +Security related matters should be disclosed in private [as per our policy on GitHub](https://github.com/unoplatform/uno/security/policy). If a security matter is raised as an issue, please capture the relevant information, [delete the GitHub issue](https://help.github.com/en/articles/deleting-an-issue) and follow up via email. This [tool can be used to find](https://emailaddress.github.io/) (almost) any GitHub user's email address. ## Support requests diff --git a/doc/articles/debugging-wasm.md b/doc/articles/debugging-wasm.md index 8473317b2f92..b0a44803e7dc 100644 --- a/doc/articles/debugging-wasm.md +++ b/doc/articles/debugging-wasm.md @@ -19,7 +19,7 @@ Debugging WebAssembly via Google Chrome is experimentally supported by the Uno P - Select **IIS Express** as the debugging target - Select **Chrome** as the Web Browser - Make sure script debugging is disabled
- ![iis express settings](Assets/quick-start/wasm-debugging-iis-express.png) + ![IIS express settings](Assets/quick-start/wasm-debugging-iis-express.png) - Start the debugging session using `Ctrl+F5` (`F5` will work, but the debugging experience won't be in Visual Studio) - Once your application has started, press `Alt+Shift+D` (in Chrome, on your application's tab) diff --git a/doc/articles/faq.md b/doc/articles/faq.md index a6e7e0be3155..3ce89936e57a 100644 --- a/doc/articles/faq.md +++ b/doc/articles/faq.md @@ -2,13 +2,13 @@ About Uno platform ## What is the Uno Platform? The Uno Platform is a Universal Windows Platform Bridge to allow UWP based code to run on iOS, Android, and WebAssembly. It provides the full API definitions of the UWP Windows 10 October 2018 Update (17763), and the implementation of parts of the UWP API, such as Windows.UI.Xaml, to enable applications to run on these platforms. -This allows the use the UWP tooling from Windows in Visual Studio, such as XAML Edit and Continue and C# Edit and Continue, to build an application as much as possible on Windows, then validate that the application runs on iOS, Android and WebAssembly. +This allows the use of the UWP tooling from Windows in Visual Studio, such as XAML Edit and Continue and C# Edit and Continue, to build an application as much as possible on Windows, then validate that the application runs on iOS, Android and WebAssembly. The XAML User Interface (UI) provides the ability to display the same XAML files on Windows, iOS, Android and WebAssembly platforms. Uno also provides support for the MVVM pattern on all platforms, with binding, styling, control and data-templating features. As the Uno Platform provides all of the APIs of the complete UWP platform, any UWP library can be compiled on top of Uno (e.g. XamlBehaviors), with the ability to determine which APIs are implemented or not via the IDE using C# Analyzers. ## What does Uno Platform do? -**For users**, it can provide can provide a consistent experience across platforms, particularly between mobile and desktop browsers. +**For users**, it can provide a consistent experience across platforms, particularly between mobile and desktop browsers. **For developers**, it can provide a consistent development experience across all platforms, using Microsoft's tooling as a base for a more efficient development loop. @@ -19,17 +19,17 @@ Developing for Windows (phone, desktop, tablet, XBox), iOS (tablet and phone), A Yet, being able to master all these frameworks at once is a particularly difficult task, because of the amount of platform-specific knowledge required to master each platform. Most of the time it boils down to different teams developing the same application multiple times, with each requiring a full development cycle. With Xamarin, C# comes to all these platforms; however, it only provides transparent translations of the UI frameworks available for iOS and Android. Most non-UI code can be shared, but when it comes to the UI, almost nothing can be shared. To avoid having to learn the UI-layout techniques and approaches for each platform, Uno.UI mimics the Windows XAML approach of defining UI and layouts. This translates into the ability to share styles, layouts, and data-bindings while retaining the ability to mix XAML-style and native layouts. For instance, a StackPanel can easily contain a RelativeLayout on Android, or a MKMapView on iOS. -Uno.UI provides the ability for developers to reuse known layout and coding techniques on all platforms, resulting in a gain of overall productivity when creating UI-rich applications. +Uno.UI provides the ability for developers to reuse known layouts and coding techniques on all platforms, resulting in a gain of overall productivity when creating UI-rich applications. ## Who makes Uno Platform? -Uno Platform was created by Team nventive over the past 4 years. +Uno Platform was developed by Team nventive over the past 4 years. ## What makes Uno Platform unique? The Uno Platform is the only implementation of the UWP API that runs across iOS, Android and WebAssembly. ## Is Uno Platform open source? -Yes, the Uno Platform is open source, under the [Apache 2.0 license](https://github.com/nventive/Uno/blob/master/License.md). +Yes, the Uno Platform is open source, under the [Apache 2.0 license](https://github.com/unoplatform/uno/blob/master/License.md). # Getting started ## How can I try Uno platform? @@ -47,8 +47,8 @@ Support is available through our [gitter](https://gitter.im/uno-platform/Lobby), There are lots of ways to contribute to the Uno Platform and we appreciate the help from the community. You can provide feedback, report bugs, give suggestions, contribute code, and participate in the platform discussions. ## How can I report a bug? -- If you think you've found a bug, please [log a new issue](https://github.com/nventive/Uno/issues) in the Uno Platform GitHub issue tracker. When filing issues, please use our bug filing template. The best way to get your bug fixed is to be as detailed as you can be about the problem. Providing a minimal project with steps to reproduce the problem is ideal. Here are questions you can answer before you file a bug to make sure you're not missing any important information. -- Did you read the [documentation](https://github.com/nventive/Uno/tree/master/doc/)? +- If you think you've found a bug, please [log a new issue](https://github.com/unoplatform/Uno/issues) in the Uno Platform GitHub issue tracker. When filing issues, please use our bug filing template. The best way to get your bug fixed is to be as detailed as you can be about the problem. Providing a minimal project with steps to reproduce the problem is ideal. Here are questions you can answer before you file a bug to make sure you're not missing any important information. +- Did you read the [documentation](https://github.com/unoplatform/Uno/tree/master/doc/)? - Did you include the snippet of broken code in the issue? - What are the EXACT steps to reproduce this problem? - What specific version or build are you using? @@ -115,7 +115,7 @@ For a good introduction to the use of XAML and MVVM patterns see [Microsoft's La ## What are the different flavors of XAML? Over the years, Microsoft has been working on different implementations that use XAML for defining User Interfaces, and currently, three main flavors co-exist: WPF, UWP, Xamarin.Forms and the legacy Silverlight. -All these implementations use the same base XAML definition language, with minor differences in terns of the interpretation of the XML namespaces (`clr-namespace` vs. `using:`), and major differences in terms of the APIs used by the XAML parser. +All these implementations use the same base XAML definition language, with minor differences in terms of the interpretation of the XML namespaces (`clr-namespace` vs. `using:`), and major differences in terms of the APIs used by the XAML parser. For instance, WPF has [`System.Windows.Controls.StackPanel`](https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.stackpanel?redirectedfrom=MSDN&view=netframework-4.7.2), UWP has [`Windows.UI.Xaml.Controls.StackPanel`](https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.StackPanel) and Xamarin.Forms @@ -210,7 +210,7 @@ For live update on UWP you need to edit the XAML while the project is debugging, ## I don't see any "Uno.UI App Solution" from File->Project->New ? -1. Install **Uno.UI Solution Template Visual Studio Extension** https://github.com/nventive/Uno/releases +1. Install **Uno.UI Solution Template Visual Studio Extension** https://github.com/unoplatform/Uno/releases 1. Look for Uno.UI App Solution under Visual C# 1. If you still haven't found it, try the Search box @@ -427,7 +427,7 @@ Yes, make sure to use the following project definition: ## Does Uno offer a TreeView control? It's in the UWP API, but [not implemented yet](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/tree-view) -We have an open Github [issue.](https://github.com/nventive/Uno/issues/3) +We have an open Github [issue.](https://github.com/unoplatform/Uno/issues/3) ## Is there a table of all UWP controls and their features compared to what's offered under Uno? @@ -448,7 +448,7 @@ This file is referenced in the .csproj like [that](https://github.com/nventive/U ## Is NavigationView supported in Uno? -It is indeed not implemented at the time, see [nventive/Uno#4](https://github.com/nventive/Uno/issues/4) for now +Yes, Uno now supports NavigationView , see [nventive/Uno#4](https://github.com/unoplatform/Uno/issues/4) for more ## Is there any particular reason that Uno uses a shared project? and is it possible to use a netstandard project instead? diff --git a/doc/articles/features/routed-events.md b/doc/articles/features/routed-events.md index d5bd9eea53c7..7f02157c022e 100644 --- a/doc/articles/features/routed-events.md +++ b/doc/articles/features/routed-events.md @@ -83,7 +83,7 @@ Notes: 1. **An event is fired**: when an event is intercepted from the platform. 2. **Event dispatcher**: the source element in visual tree receive the event through its event handler. - 3. **Local handlers?**: check if there is any local handlders for the event. + 3. **Local handlers?**: check if there is any local handlers for the event. 4. **Invoke handlers**: they are invoked one after the other, taking care of the "IsHandled" status. 5. **Handled?**: check if any of the local handlers marked the event as _handled_. 6. **Originating from platform?**: check if the source of the event is from native code. diff --git a/doc/articles/features/working-with-animations.md b/doc/articles/features/working-with-animations.md index f036a2abd93c..5e46b3f2ccb0 100644 --- a/doc/articles/features/working-with-animations.md +++ b/doc/articles/features/working-with-animations.md @@ -7,4 +7,4 @@ As of 1.43.1: * `RenderTransform` of type `TranslateTransform`, `RotateTransform`, `ScaleTransform`, or `CompositeTransform`. Transforms cannot be part of a TransformGroup. 1. When animating a `Transform`, you can animate only one property at a time (i.e. `CompositeTransform.TranslateX` *or* `CompositeTransform.TranslateY`), 1. You cannot reuse a `Transform` or an `Animation` declared in resources on multiple controls (instead you have to put your animation in a `Template`) -1. By default on iOS, Android and WASM, controls are clipped by their parent. On iOS ou can set the flag `Uno.UI.FeatureConfiguration.UIElement.UseLegacyClipping = false` to get the Windows behavior. +1. By default on iOS, Android and WASM, controls are clipped by their parent. On iOS you can set the flag `Uno.UI.FeatureConfiguration.UIElement.UseLegacyClipping = false` to get the Windows behavior. diff --git a/doc/articles/howto-migrate-existing-code.md b/doc/articles/howto-migrate-existing-code.md index f40500b09457..33e2b5510e4b 100644 --- a/doc/articles/howto-migrate-existing-code.md +++ b/doc/articles/howto-migrate-existing-code.md @@ -1,12 +1,12 @@ # How to migrate existing UWP code to Uno -There are two separate paths to use an existing UWP codebase on top of uno: +There are two separate paths for using an existing UWP codebase on top of uno: - An existing UWP application - An existing UWP library ## Use an existing application -To use an existing application, the easiest path is to create an Uno QuickStart application from [the solution template](get-started.md), then adjust to project structure for the source code to be shared. +To use an existing application, the easiest path is to create an Uno QuickStart application from [the solution template](get-started.md), then adjust the project structure for the source code to be shared. 1. In the existing application, **create a shared project** 1. In this new shared project, move all the Assets and Xaml and C# Files @@ -14,7 +14,7 @@ To use an existing application, the easiest path is to create an Uno QuickStart 1. On the side, create a new Uno Quick Start project using a name matching your project 1. Copy the iOS, Android and WebAssembly projects over to your existing source tree 1. Adjust the shared project references to use your existing shared project -1. Building your project +1. Build your project > Note: You may need to adjust your code considering the [current API differences](api-differences.md). @@ -24,12 +24,12 @@ To migrate an existing library, the shortest path is to create a Cross-Platform ### Steps Here's how to do it, from scratch. Let's start by creating a basic UWP library, so we can transform it to a cross-platform one: -- In Visual Studio, create a **Class Library (Universal Windows)** project name `MyLibrary` +- In Visual Studio, create a **Class Library (Universal Windows)** project named `MyLibrary` - Make sure it builds. -- Using the Uno Visual Studio Extension, create a **Cross-Platform Library (Uno Platform)** project in the same solution, name it `TempUno` +- Using the Uno Visual Studio Extension, create a **Cross-Platform Library (Uno Platform)** project in the same solution, and name it `TempUno` - Right click on `MyLibrary`, then **Unload Project** - Right click again on `MyLibrary`, then **Edit MyLibrary.csproj** -- Right click on `TempUno`, then **Edit TempUno.csproj** _(There no need to unload this type of project)_ +- Right click on `TempUno`, then **Edit TempUno.csproj** _(There is no need to unload this type of project)_ - Copy the whole content of the `TempUno` csproj, and paste it in the `MyLibrary` project file. - Right click on the `MyLibrary` project, then **Reload Project** - Delete the `TempUno` project from your solution @@ -42,4 +42,4 @@ If you have a set of existing nuget dependencies in your project: - If the dependency **is using .NET Standard 2.0**, there's no need to make any changes, the library will be used as-is. This type of dependency will generally work on other platforms, depending on the type of APIs used, and runtime platform features. - If the dependency **is not using .NET Standard 2.0**: - It may already support the iOS and Android targets, in which case it can be used directly - - If it does not, the Uno Platform team may already have created an Uno port of the library available on Nuget. \ No newline at end of file + - If it does not, the Uno Platform team may have already created an Uno port of the library available on Nuget. diff --git a/doc/articles/supported-features.md b/doc/articles/supported-features.md index 9fae36995e47..e9b5b1a6b8e6 100644 --- a/doc/articles/supported-features.md +++ b/doc/articles/supported-features.md @@ -120,6 +120,7 @@ - XAML Behaviors - AttachedProperty Binding - AttachedProperty Styling +- Custom `MarkupExtension` support - Brightness Control - Native and Custom dialogs - Support for StateTriggers diff --git a/doc/articles/uno-development/debugging-uno-ui.md b/doc/articles/uno-development/debugging-uno-ui.md index 186d70da9e4f..20341029d035 100644 --- a/doc/articles/uno-development/debugging-uno-ui.md +++ b/doc/articles/uno-development/debugging-uno-ui.md @@ -9,7 +9,7 @@ Prerequisites: - `ASP.NET and Web Development` - `.NET Core cross-platform development` - `UWP Development`, install all recent UWP SDKs, starting from 10.0.14393 (or above or equal to `TargetPlatformVersion` line [in this file](/src/Uno.CrossTargetting.props)) -- Install all Android SDKs starting from 7.1 (or the Android versions [`TargetFrameworks` list used here](/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj)) +- Install (**Tools** / **Android** / **Android SDK manager**) all Android SDKs starting from 7.1 (or the Android versions `TargetFrameworks` [list used here](/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj)) ### Building Uno.UI for all available targets * Open the [Uno.UI.sln](/src/Uno.UI.sln) @@ -24,7 +24,7 @@ To enable faster development, it's possible to use the [Visual Studio Solution F For instance, if you want to debug an iOS feature: - Make sure the `Uno.UI.sln` solution is not opened in Visual Studio. - Make a copy of the [src/crosstargeting_override.props.sample](src/crosstargeting_override.props.sample) file to `src/crosstargeting_override.props` -- Uncomment the `UnoTargetFrameworkOverride` line and set its value to `xamarinios10` +- In this new file, uncomment the `UnoTargetFrameworkOverride` line and set its value to `xamarinios10` - Open the `Uno.UI-iOS-only.slnf` solution filter (either via the VS folder view, or the Windows explorer) - Build diff --git a/doc/articles/using-uno-ui.md b/doc/articles/using-uno-ui.md index f36f3d15f54f..e3ca8b94aedf 100644 --- a/doc/articles/using-uno-ui.md +++ b/doc/articles/using-uno-ui.md @@ -2,7 +2,7 @@ ## Pre-requisites -* Visual Studio 2017 15.5 or later, with : +* [**Visual Studio 2017 15.5 or later**](https://visualstudio.microsoft.com/), with : * Xamarin component, with the iOS Remote Simulator installed * A working Mac with Visual Studio for Mac, XCode 8.2 or later installed * The google Android x86 emulators @@ -73,7 +73,7 @@ located in the **MyApp.[iOS|Android]\Obj\[Platform]** folder. You may see those files in Visual Studio by selecting this project in the Solution Explorer, then click the **Show all Files** icon at the top. -If you notice an issue, or an error in the commented code of the generated file, you may need to alter your Xaml. +If you notice an issue, or an error in the commented code of the generated file, you may need to alter your Xaml file. ## Configure the manifest for the WebAssembly head In your WASM head, create a folder named `WasmScripts`, with a file containing the Javascript code below @@ -92,9 +92,9 @@ var UnoAppManifest = { ``` The properties are : -* **splashScreenImage**: defines the image that will be centered on the window during the application's loading time -* **splashScreenColor**: defines the background color of the splash screen -* **displayName**: defines the default name of the application in the browser's window title +* **splashScreenImage**: defines the image that will be centered on the window during the application's loading time. +* **splashScreenColor**: defines the background color of the splash screen. +* **displayName**: defines the default name of the application in the browser's window title. ## Supporting multiple platforms in Xaml files @@ -106,15 +106,13 @@ The layout behavior is the notion of applying margins, paddings and alignments f The Uno.UI layout engine on Android and iOS is applied by a parent to its children. This means that if a control has an alignment or a margin set, if it is not child of a FrameworkElement (ie it's the child of a non-Uno view), those properties will be ignored, and the control will stretch within its parent's available space. -This behavior is is a direct consequence of the ability to mix native and Uno.UI controls. +This behavior is a direct consequence of the ability to mix native and Uno.UI controls. ## Dependency Properties -Uno.UI allows the sharing of [Dependency Property](https://msdn.microsoft.com/en-us/library/ms752914%28v=vs.110%29.aspx) declaration and -code between Windows and Xamarin based platforms. +Uno.UI allows the sharing of [Dependency Property](https://msdn.microsoft.com/en-us/library/ms752914%28v=vs.110%29.aspx) declaration and code between Windows and Xamarin based platforms. -Declaring a dependency property in Uno UI requires a class to implement the -interface `DependencyObject`, to gain access to the GetValue and SetValue methods. +Declaring a dependency property in Uno UI requires a class to implement the interface `DependencyObject`, to gain access to the GetValue and SetValue methods. Here is an example of such a declaration: @@ -203,8 +201,8 @@ Uno.UI also generates a nested class named StaticResources in all non-ResourceDi Uno.UI supports the [authoring of styles](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.style.aspx). For many controls in Uno, two prepackaged styles are provided: -* NativeDefault[Control] which is customized to match the UI guidelines of the target platform -* XamlDefault[Control] which is the default style of controls on Windows +* NativeDefault[Control] which is customized to match the UI guidelines of the target platform. +* XamlDefault[Control] which is the default style of controls on Windows. On WASM, the NativeDefault[Control] styles are currently only aliases to the XamlDefault[Control], for compatibility with other platforms. @@ -251,7 +249,7 @@ For more information, see the [HyperLinkButton](https://msdn.microsoft.com/en-us The RadioButton control is implemented by default using a ControlTemplate that contains a bindable native CheckBox, that binds the Content property as a string, IsChecked as a boolean, and propagates the CanExecute of a databound command. -For more information, see the [RadioButton clas](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.radiobutton.aspx). +For more information, see the [RadioButton class](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.radiobutton.aspx). ### ComboBox @@ -277,7 +275,7 @@ For more information, see [GridView class](https://docs.microsoft.com/en-us/uwp/ ### Image -For more information, see [Image class](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.image.aspx). +For more information, see [Image class](https://msdn.microsoft.com/en-us/library/window/apps/windows.ui.xaml.controls.image.aspx). ### ImageSource @@ -287,8 +285,7 @@ Image handling works 'out of the box' on iOS and WebAssembly without further con On Android, to handle the loading of images from a remote url, the Image control has to be provided a ImageSource.DefaultImageLoader such as the [Android Universal Image Loader](https://github.com/nostra13/Android-Universal-Image-Loader). -This package is installed by default when using the [Uno Cross-Platform solution templates](https://marketplace.visualstudio.com/items?itemName=nventivecorp.uno-platform-addin). If not using the solution template, you can install the [nventive.UniversalImageLoader](https://www.nuget.org/packages/nventive.UniversalImageLoader/) NuGet package and call the following code -from your application's App constructor: +This package is installed by default when using the [Uno Cross-Platform solution templates](https://marketplace.visualstudio.com/items?itemName=nventivecorp.uno-platform-addin). If not using the solution template, you can install the [nventive.UniversalImageLoader](https://www.nuget.org/packages/nventive.UniversalImageLoader/) NuGet package and call the following code from your application's App constructor: ```csharp private void ConfigureUniversalImageLoader() @@ -396,9 +393,7 @@ Adding a custom font is done through the use of WebFonts, using a data-URI: } ``` -This type of declaration is required to avoid measuring errors if the font requested -by a `TextBlock` or a `FontIcon` needs to be downloaded first. Specifying it using a -data-URI ensures the font is readily available. +This type of declaration is required to avoid measuring errors if the font requested by a `TextBlock` or a `FontIcon` needs to be downloaded first. Specifying it using a data-URI ensures the font is readily available. #### Custom Fonts Notes Please note that some custom fonts need the FontFamily and FontWeight properties to be set at the same time in order to work properly on TextBlocks, Runs and for styles Setters. diff --git a/doc/blog/201808-UnoUnderTheHoodIntro.md b/doc/blog/201808-UnoUnderTheHoodIntro.md index 46c34c3f3d01..f5426897005e 100644 --- a/doc/blog/201808-UnoUnderTheHoodIntro.md +++ b/doc/blog/201808-UnoUnderTheHoodIntro.md @@ -28,16 +28,16 @@ top of [WebAssembly](https://webassembly.org/). There are a few things that need to be done to get your app running:  -- At compile time, Uno parses XAML files into C\# code, creating the - > information needed to build the app's visual tree;  +- At compile time, Uno parses XAML files into C\# code, creating the + information needed to build the app's visual tree;  -- It implements a - > complete [databinding](https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/dependency-properties-overview) engine, - > optimised for static type-checking where possible;  +- It implements a + complete [databinding](https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/dependency-properties-overview) engine, + optimised for static type-checking where possible;  -- It implements the views and controls in the [UWP - > framework](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/controls-by-function), - > using each platform's native UI framework as a basis.  +- It implements the views and controls in the + [UWP framework](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/controls-by-function), + using each platform's native UI framework as a basis. Each of those items warrants a post on its own, so I'll move on before I get bogged down.  @@ -50,44 +50,43 @@ we've built this thing.  - **Leverage existing tools**  - - We stand on the shoulders of  giants. Microsoft's tooling is a - > treat to work with: [Edit and - > Continue](https://docs.microsoft.com/en-us/visualstudio/debugger/edit-and-continue), [Live - > Visual - > Tree](https://docs.microsoft.com/en-us/visualstudio/debugger/inspect-xaml-properties-while-debugging), - > the list goes on. The promise of Uno is to build your app with - > those tools and then deploy it to iOS, Android, and ultimately - > to the web.  + > We stand on the shoulders of  giants. Microsoft's tooling is a + > treat to work with: + > [Edit and Continue](https://docs.microsoft.com/en-us/visualstudio/debugger/edit-and-continue),  + > [Live Visual Tree](https://docs.microsoft.com/en-us/visualstudio/debugger/inspect-xaml-properties-while-debugging), + > the list goes on. The promise of Uno is to build your app with + > those tools and then deploy it to iOS, Android, and ultimately + > to the web.  - **Create rich, responsive UIs**  - - Bland apps don't quite cut it these days. Strong support for - > animations, templating, and custom visual effects is a must. - > And when phones come in all sizes and manufacturers - > are [gouging holes out of the screen - > area](https://www.cnet.com/pictures/phones-with-notches/), - > your app's layout had better be responsive.  + > Bland apps don't quite cut it these days. Strong support for + > animations, templating, and custom visual effects is a must. + > And when phones come in all sizes and manufacturers + > are [gouging holes out of the screen + > area](https://www.cnet.com/pictures/phones-with-notches/), + > your app's layout had better be responsive.  - **Let views do views**  - - Separation of model, view and presentation keeps your code - > loosely coupled and easy to maintain. Features like - > databinding and attached properties let you write clean, - > elegant MVVM-style code.  + > Separation of model, view and presentation keeps your code + > loosely coupled and easy to maintain. Features like + > databinding and attached properties let you write clean, + > elegant MVVM-style code.  - **Native intercompatibility (leave an escape hatch)**  - - 100% code reuse is the ideal, but it should also be easy to - > access functionality specific to a single platform, or to - > incorporate native third-party libraries.  + > 100% code reuse is the ideal, but it should also be easy to + > access functionality specific to a single platform, or to + > incorporate native third-party libraries.  - **Performance is a feature**  - - The slow antelope gets eaten, and the slow app gets 1-star - > ratings. We've done a lot of optimisation on the basis of - > profiling in real-world use cases, and we'll continue to do - > so.  + > The slow antelope gets eaten, and the slow app gets 1-star + > ratings. We've done a lot of optimisation on the basis of + > profiling in real-world use cases, and we'll continue to do + > so.  That's a good place to stop. In the next post I'll take up the tale of my favourite UI -control: [ListView](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/listview-and-gridview). \ No newline at end of file +control: [ListView and GridView](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/listview-and-gridview). diff --git a/doc/blog/201901-WebAssembly-Projects-and-debugging.md b/doc/blog/201901-WebAssembly-Projects-and-debugging.md index 7112b79b9872..bc449e820521 100644 --- a/doc/blog/201901-WebAssembly-Projects-and-debugging.md +++ b/doc/blog/201901-WebAssembly-Projects-and-debugging.md @@ -2,7 +2,7 @@ The progress on the Uno Platform support for WebAssembly has been steady, along with the mono runtime making large improvements in the support for a debugging experience. -We've added support for a better Visual Studio project integration as well as a experimental debugging experience. +We've added support for a better Visual Studio project integration as well as an experimental debugging experience. The next release of the [Uno Visual Studio add-in](https://marketplace.visualstudio.com/items?itemName=nventivecorp.uno-platform-addin) will contain the new project format and the debugger, but you can try it today using the [latest experimental release](https://github.com/nventive/Uno/releases) of the Uno Platform. @@ -37,7 +37,7 @@ The Mono team has been working for a while on the debugging experience, and rece There is only one important constraint: the debugging only works with Chrome. It is using the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). -The debugger provides access to all local sources, as well as [Source Link enabled assemblies](https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/sourcelink) when available, provide single stepping, breakpoints, stack trace walking, local variables and watches. Currently local variables watching is limited to primitives and strings. +The debugger provides access to all local sources, as well as [Source Link enabled assemblies](https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/sourcelink) when available, provide single stepping, breakpoints, stack trace walking, local variables and watches. Currently, watching local variables is limited to primitives and strings. To give you an example of the debugging experience, this is a step-into the `DateTime.Now` property in the mono source tree, from a normal user program: ![](Assets/201901-debugger-step-04.png) diff --git a/doc/index.md b/doc/index.md index 2eb42a35e57f..523aaba40e7b 100644 --- a/doc/index.md +++ b/doc/index.md @@ -17,7 +17,7 @@ uid: front-page
uno logo -

What is the Uno Platform

+

What is the Uno Platform?

Uno is a free UWP Bridge for iOS, Android and WebAssembly.

@@ -73,4 +73,4 @@ uid: front-page
- \ No newline at end of file + diff --git a/src/Common.targets b/src/Common.targets index f272317b4104..bf0093fcf757 100644 --- a/src/Common.targets +++ b/src/Common.targets @@ -1,9 +1,9 @@  - @@ -13,10 +13,10 @@ True - + - $(UnoDefineConstants);__IOS_11__ + $(UnoDefineConstants);__IOS_11__ @@ -25,4 +25,4 @@ - \ No newline at end of file + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index ccd305e28902..c5d01b0f89f4 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,6 +1,5 @@ - diff --git a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems index 208f8f427df7..3b964d10d694 100644 --- a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems +++ b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems @@ -2528,7 +2528,7 @@ BarometerTests.xaml - GyrometerTests.xaml + GyrometerTests.xaml MagnetometerTests.xaml @@ -2596,6 +2596,9 @@ Localization_Implicit.xaml + + + Style_Inline.xaml @@ -4573,7 +4576,7 @@ ComboBox_ItemDataContext.xaml - + GyrometerTests.xaml diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/Entity.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/Entity.cs new file mode 100644 index 000000000000..c958de789e09 --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/Entity.cs @@ -0,0 +1,31 @@ +using System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Markup; + +namespace UITests.Shared.Windows_UI_Xaml.MarkupExtension +{ + [MarkupExtensionReturnType(ReturnType = typeof(EntityObject))] + public class Entity : Windows.UI.Xaml.Markup.MarkupExtension + { + public string TextValue { get; set; } + + public int IntValue { get; set; } + + protected override object ProvideValue() + { + return new EntityObject() + { + StringProperty = TextValue, + IntProperty = IntValue + }; + } + } + + public class EntityObject + { + public string StringProperty { get; set; } = string.Empty; + + public int IntProperty { get; set; } + } +} diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/InverseBool.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/InverseBool.cs new file mode 100644 index 000000000000..481043723b40 --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/InverseBool.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Markup; + +namespace UITests.Shared.Windows_UI_Xaml.MarkupExtension +{ + [MarkupExtensionReturnType(ReturnType = typeof(IValueConverter))] + public class InverseBool : Windows.UI.Xaml.Markup.MarkupExtension, IValueConverter + { + protected override object ProvideValue() => this; + + public object Convert(object value, Type targetType, object parameter, string language) + { + return !(bool)(value ?? false); + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return !(bool)(value ?? false); + } + } +} diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/MarkupExtension.xaml b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/MarkupExtension.xaml index a94fcf4f8a3e..184ecacd90de 100644 --- a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/MarkupExtension.xaml +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/MarkupExtension.xaml @@ -4,37 +4,79 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ex="using:UITests.Shared.Windows_UI_Xaml.MarkupExtension" - xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:ios="http://uno.ui/ios" - xmlns:android="http://uno.ui/android" - xmlns:wasm="http://uno.ui/wasm" - mc:Ignorable="d ios android wasm" + xmlns:beh="using:UITests.Shared.Windows_UI_Xaml.MarkupExtensionTests.Behaviors" + mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> - + - + I'm a StaticResource, look for 123 below me... + ...and from within a DataTemplate I'm a custom ... + + + + + + + + + + - + - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/MarkupExtensionBehaviors.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/MarkupExtensionBehaviors.cs new file mode 100644 index 000000000000..f43bc0db76ec --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml/MarkupExtensionTests/MarkupExtensionBehaviors.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace UITests.Shared.Windows_UI_Xaml.MarkupExtensionTests.Behaviors +{ + public static class MarkupExtensionBehaviors + { + public static string GetCustomText(TextBlock obj) => (string)obj.GetValue(CustomTextProperty); + + public static void SetCustomText(TextBlock obj, string value) => obj.SetValue(CustomTextProperty, value); + + public static readonly DependencyProperty CustomTextProperty = + DependencyProperty.RegisterAttached( + "CustomText", + typeof(string), + typeof(MarkupExtensionBehaviors), + new PropertyMetadata(string.Empty, OnCustomTextChanged)); + + private static void OnCustomTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) + { + if (dependencyObject is TextBlock tb) + { + tb.Text = GetCustomText(tb); + } + } + } +} diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/Helpers/RoslynMetadataHelper.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/Helpers/RoslynMetadataHelper.cs index 604d0056c7c6..ab33f0251c69 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators/Helpers/RoslynMetadataHelper.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators/Helpers/RoslynMetadataHelper.cs @@ -22,6 +22,7 @@ internal class RoslynMetadataHelper private readonly Dictionary _legacyTypes; private readonly Func _findTypesByName; private readonly Func _findTypeByFullName; + private readonly Func> _getAllDerivingTypes; private readonly Dictionary _additionalTypesMap; public Compilation Compilation { get; } @@ -36,7 +37,8 @@ public RoslynMetadataHelper(string configuration, Compilation sourceCompilation, _findTypeByFullName = Funcs.Create(SourceFindTypeByFullName).AsLockedMemoized(); _additionalTypes = additionalTypes ?? new string[0]; _legacyTypes = BuildLegacyTypes(legacyTypes); - _project = roslynProject; + _getAllDerivingTypes = Funcs.Create>(GetAllDerivingTypes).AsLockedMemoized(); + _project = roslynProject; _nullableSymbol = Compilation.GetTypeByMetadataName("System.Nullable`1"); } @@ -239,5 +241,36 @@ public ITypeSymbol GetTypeByFullName(string fullName) public INamedTypeSymbol GetGenericType(string name = "T") => Compilation.CreateErrorTypeSymbol(null, name, 0); public IArrayTypeSymbol GetArray(ITypeSymbol type) => Compilation.CreateArrayTypeSymbol(type); + + public IEnumerable GetAllTypesDerivingFrom(INamedTypeSymbol baseType) + { + return _getAllDerivingTypes(baseType); + } + + private IEnumerable GetAllDerivingTypes(INamedTypeSymbol baseType) + { + return GetTypesDerivingFrom(Compilation.GlobalNamespace); + + IEnumerable GetTypesDerivingFrom(INamespaceSymbol ns) + { + foreach (var member in ns.GetMembers()) + { + if (member is INamespaceSymbol nsInner) + { + foreach (var t in GetTypesDerivingFrom(nsInner)) + { + yield return t; + } + } + else if (member is INamedTypeSymbol type) + { + if (((INamedTypeSymbol)member).Is(baseType)) + { + yield return type; + } + } + } + } + } } } diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlConstants.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlConstants.cs index 9b035ada79aa..c148175eae19 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlConstants.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlConstants.cs @@ -65,9 +65,10 @@ public static class Types public const string Style = BaseXamlNamespace + ".Style"; public const string ElementStub = BaseXamlNamespace + ".ElementStub"; public const string ContentPresenter = Namespaces.Controls + ".ContentPresenter"; + public const string Markup = BaseXamlNamespace + ".Markup"; // Attributes - public const string ContentPropertyAttribute = BaseXamlNamespace + ".Markup.ContentPropertyAttribute"; + public const string ContentPropertyAttribute = Markup + ".ContentPropertyAttribute"; // Text public const string FontWeight = Namespaces.Text + ".FontWeight"; @@ -103,10 +104,15 @@ public static class Types public const string Panel = Namespaces.Controls + ".Panel"; public const string Button = Namespaces.Controls + ".Button"; public const string TextBox = Namespaces.Controls + ".TextBox"; - + // Documents public const string Run = Namespaces.Documents + ".Run"; public const string Span = Namespaces.Documents + ".Span"; + + // MarkupExtension + public const string MarkupExtension = Markup + ".MarkupExtension"; + public const string IMarkupExtensionOverrides = Markup + ".IMarkupExtensionOverrides"; + public const string MarkupExtensionReturnTypeAttribute = Markup + ".MarkupExtensionReturnTypeAttribute"; } } } diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs index f6b73b501968..a862674d6840 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs @@ -84,6 +84,7 @@ internal partial class XamlFileGenerator private readonly INamedTypeSymbol _objectSymbol; private readonly INamedTypeSymbol _iFrameworkElementSymbol; private readonly INamedTypeSymbol _dependencyObjectSymbol; + private readonly INamedTypeSymbol _markupExtensionSymbol; private readonly INamedTypeSymbol _iCollectionSymbol; private readonly INamedTypeSymbol _iCollectionOfTSymbol; @@ -93,6 +94,8 @@ internal partial class XamlFileGenerator private readonly INamedTypeSymbol _dataBindingSymbol; private readonly INamedTypeSymbol _styleSymbol; + private readonly List _markupExtensionTypes; + private readonly bool _isWasm; private bool _isGeneratingGlobalResource = false; @@ -147,6 +150,7 @@ bool skipUserControlsInVisualTree _contentPresenterSymbol = GetType(XamlConstants.Types.ContentPresenter); _iFrameworkElementSymbol = GetType(XamlConstants.Types.IFrameworkElement); _dependencyObjectSymbol = GetType(XamlConstants.Types.DependencyObject); + _markupExtensionSymbol = GetType(XamlConstants.Types.MarkupExtension); _iCollectionSymbol = GetType("System.Collections.ICollection"); _iCollectionOfTSymbol = GetType("System.Collections.Generic.ICollection`1"); _iListSymbol = GetType("System.Collections.IList"); @@ -155,6 +159,8 @@ bool skipUserControlsInVisualTree _dataBindingSymbol = GetType("Windows.UI.Xaml.Data.Binding"); _styleSymbol = GetType(XamlConstants.Types.Style); + _markupExtensionTypes = _medataHelper.GetAllTypesDerivingFrom(_markupExtensionSymbol).ToList(); + _isWasm = isWasm; } @@ -1340,6 +1346,12 @@ private void GenerateSilentWarning(IIndentedStringBuilder writer, string message private bool HasMarkupExtension(XamlMemberDefinition valueNode) { + // Return false if the Owner is a custom markup extension + if (IsCustomMarkupExtensionType(valueNode.Owner?.Type)) + { + return false; + } + return valueNode .Objects .Any(o => @@ -1351,6 +1363,14 @@ private bool HasMarkupExtension(XamlMemberDefinition valueNode) ); } + private bool HasCustomMarkupExtension(XamlMemberDefinition valueNode) + { + // Verify if a custom markup extension exists + return valueNode + .Objects + .Any(o => IsCustomMarkupExtensionType(o.Type)); + } + private bool HasBindingMarkupExtension(XamlMemberDefinition valueNode) { return valueNode @@ -1362,6 +1382,20 @@ private bool HasBindingMarkupExtension(XamlMemberDefinition valueNode) ); } + private bool IsCustomMarkupExtensionType(XamlType xamlType) + { + if (xamlType == null) + { + return false; + } + + // Adjustment for Uno.Xaml parser which returns the namespace in the name + var xamlTypeName = xamlType.Name.Contains(':') ? xamlType.Name.Split(':').LastOrDefault() : xamlType.Name; + + // Determine if the type is a custom markup extension + return _markupExtensionTypes.Any(ns => ns.Name.Equals(xamlTypeName, StringComparison.InvariantCulture)); + } + private XamlMemberDefinition FindMember(XamlObjectDefinition xamlObjectDefinition, string memberName) { return xamlObjectDefinition.Members.FirstOrDefault(m => m.Member.Name == memberName); @@ -2011,6 +2045,17 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj BuildComplexPropertyValue(writer, member, closureName + ".", closureName); } + else if (HasCustomMarkupExtension(member)) + { + if (IsAttachedProperty(member) && FindPropertyType(member.Member) != null) + { + BuildSetAttachedProperty(writer, closureName, member, objectUid, isCustomMarkupExtension: true); + } + else + { + BuildCustomMarkupExtensionPropertyValue(writer, member, closureName + "."); + } + } else if (member.Objects.Any()) { if (member.Member.Name == "_UnknownContent") // So : FindType(member.Owner.Type) is INamedTypeSymbol type && IsCollectionOrListType(type) @@ -2218,7 +2263,7 @@ private void BuildExtendedProperties(IIndentedStringBuilder outerwriter, XamlObj { if (FindPropertyType(member.Member) != null) { - BuildSetAttachedProperty(writer, closureName, member, objectUid); + BuildSetAttachedProperty(writer, closureName, member, objectUid, isCustomMarkupExtension: false); } else if (eventSymbol != null) { @@ -2305,6 +2350,21 @@ void writeEvent(string ownerPrefix) } } } + + // Local function used to build a property/value for any custom MarkupExtensions + void BuildCustomMarkupExtensionPropertyValue(IIndentedStringBuilder writer, XamlMemberDefinition member, string prefix) + { + Func formatLine = format => prefix + format + (prefix.HasValue() ? ";\r\n" : ""); + + var propertyValue = GetCustomMarkupExtensionValue(member); + + if (propertyValue.HasValue()) + { + var formatted = formatLine($"{member.Member.Name} = {propertyValue}"); + + writer.AppendLine(formatted); + } + } } /// @@ -2394,13 +2454,17 @@ private bool IsRelativePanelSiblingProperty(string name) name.Equals("AlignVerticalCenterWith"); } - private void BuildSetAttachedProperty(IIndentedStringBuilder writer, string closureName, XamlMemberDefinition member, string objectUid) + private void BuildSetAttachedProperty(IIndentedStringBuilder writer, string closureName, XamlMemberDefinition member, string objectUid, bool isCustomMarkupExtension) { + var literalValue = isCustomMarkupExtension + ? GetCustomMarkupExtensionValue(member) + : BuildLiteralValue(member, owner: member, objectUid: objectUid); + writer.AppendLineInvariant( "{0}.Set{1}({3}, {2});", GetGlobalizedTypeName(FindType(member.Member.DeclaringType).SelectOrDefault(t => t.ToDisplayString(), member.Member.DeclaringType.Name)), member.Member.Name, - BuildLiteralValue(member, owner: member, objectUid: objectUid), + literalValue, closureName ); } @@ -2466,7 +2530,7 @@ string GetBindingOptions() { return (bindingNode ?? bindNode) .Members - .Select(m => "{0} = {1}".InvariantCultureFormat(m.Member.Name == "_PositionalParameters" ? "Path" : m.Member.Name, BuildBindingOption(m, FindPropertyType(m.Member), prependCastToType: true))) + .Select(BuildMemberPropertyValue) .Concat(bindNode != null && !isInsideDataTemplate ? new[] { "CompiledSource = this" } : Enumerable.Empty()) .JoinBy(", "); @@ -2475,13 +2539,13 @@ string GetBindingOptions() { return templateBindingNode .Members - .Select(m => "{0} = {1}".InvariantCultureFormat(m.Member.Name == "_PositionalParameters" ? "Path" : m.Member.Name, BuildBindingOption(m, FindPropertyType(m.Member), prependCastToType: true))) + .Select(BuildMemberPropertyValue) .Concat("RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent)") .JoinBy(", "); } return null; - }; + } var bindingOptions = GetBindingOptions(); @@ -2533,6 +2597,67 @@ string GetBindingOptions() } } + private string BuildMemberPropertyValue(XamlMemberDefinition m) + { + if (IsCustomMarkupExtensionType(m.Objects.FirstOrDefault()?.Type)) + { + // If the member contains a custom markup extension, build the inner part first + var propertyValue = GetCustomMarkupExtensionValue(m); + return "{0} = {1}".InvariantCultureFormat(m.Member.Name, propertyValue); + } + else + { + return "{0} = {1}".InvariantCultureFormat(m.Member.Name == "_PositionalParameters" ? "Path" : m.Member.Name, BuildBindingOption(m, FindPropertyType(m.Member), prependCastToType: true)); + } + } + + private string GetCustomMarkupExtensionValue(XamlMemberDefinition member) + { + // Get the type of the custom markup extension + var markupTypeDef = member + .Objects + .FirstOrDefault(o => IsCustomMarkupExtensionType(o.Type)); + + // Build a string of all its properties + var properties = markupTypeDef + .Members + .Select(m => + { + var resourceName = GetStaticResourceName(m); + + var value = resourceName != null + ? resourceName + : BuildLiteralValue(m, owner: member); + + return "{0} = {1}".InvariantCultureFormat(m.Member.Name, value); + }) + .JoinBy(", "); + + // Get the full globalized namespaces for the custom markup extension and also for IMarkupExtensionOverrides + var markupType = GetType(markupTypeDef.Type); + var markupTypeFullName = GetGlobalizedTypeName(markupType.GetFullName()); + var xamlMarkupFullName = GetGlobalizedTypeName(XamlConstants.Types.IMarkupExtensionOverrides); + + // Get the attribute from the custom markup extension class then get the return type specifed with MarkupExtensionReturnTypeAttribute + var attributeData = markupType.FindAttribute(XamlConstants.Types.MarkupExtensionReturnTypeAttribute); + + if (attributeData == null) + { + this.Log().Error($"The custom markup extension {markupTypeDef.Type.Name} must specify the return type using {nameof(XamlConstants.Types.MarkupExtensionReturnTypeAttribute)}."); + return string.Empty; + } + + var returnType = attributeData.NamedArguments.FirstOrDefault(kvp => kvp.Key == "ReturnType").Value.Value; + + if (returnType == null) + { + this.Log().Error($"The custom markup extension contains a ReturnType that cannot be found."); + return string.Empty; + } + + return $"({returnType})(({xamlMarkupFullName})(new {markupTypeFullName} {{ {properties} }})).ProvideValue()"; + } + private bool IsMemberInsideDataTemplate(XamlObjectDefinition xamlObject) => IsMemberInside(xamlObject, "DataTemplate"); @@ -3054,7 +3179,16 @@ private string BuildBindingOption(XamlMemberDefinition m, INamedTypeSymbol prope return $"new RelativeSource(RelativeSourceMode.{resourceName})"; } - return "Unsupported"; + // If type specified in the binding was not found, log and return an error message + if (!string.IsNullOrEmpty(bindingType?.Type?.Name ?? string.Empty)) + { + var message = $"#Error // {bindingType.Type.Name} could not be found."; + this.Log().Error(message); + + return message; + } + + return "#Error"; } else { @@ -3233,6 +3367,7 @@ private void BuildLiteralProperties(IIndentedStringBuilder writer, XamlObjectDef && m.Type.Name != "StaticResource" && m.Type.Name != "ThemeResource" && m.Type.Name != "TemplateBinding" + && !IsCustomMarkupExtensionType(m.Type) ); if (nonBindingObjects.Any()) diff --git a/src/SourceGenerators/XamlGenerationTests/CustomMarkupExtensions.xaml b/src/SourceGenerators/XamlGenerationTests/CustomMarkupExtensions.xaml new file mode 100644 index 000000000000..2e7d8950e3ba --- /dev/null +++ b/src/SourceGenerators/XamlGenerationTests/CustomMarkupExtensions.xaml @@ -0,0 +1,57 @@ + + + + + + Resource String + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/SourceGenerators/XamlGenerationTests/CustomMarkupExtensions.xaml.cs b/src/SourceGenerators/XamlGenerationTests/CustomMarkupExtensions.xaml.cs new file mode 100644 index 000000000000..bbaca71e872e --- /dev/null +++ b/src/SourceGenerators/XamlGenerationTests/CustomMarkupExtensions.xaml.cs @@ -0,0 +1,127 @@ +using System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Markup; + +namespace XamlGenerationTests.Shared +{ + public partial class CustomMarkupExtensions : UserControl + { + public CustomMarkupExtensions() + { + this.InitializeComponent(); + } + } +} + +namespace XamlGenerationTests.Shared.MarkupExtensions +{ + public class TestObject + { + public string StringProp { get; set; } + + public int IntProp { get; set; } + + public bool BoolProp { get; set; } + } + + public class TestConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotSupportedException(); + } + } + + public static class AttachedTest + { + public static bool GetIsAttached(DependencyObject obj) => (bool)obj.GetValue(IsAttachedProperty); + + public static void SetIsAttached(DependencyObject obj, bool value) => obj.SetValue(IsAttachedProperty, value); + + public static readonly DependencyProperty IsAttachedProperty = + DependencyProperty.RegisterAttached( + "IsAttached", + typeof(bool), + typeof(AttachedTest), + new PropertyMetadata(false)); + } + + [MarkupExtensionReturnType(ReturnType = typeof(string))] + public class TestMarkup : MarkupExtension + { + public string String1 { get; set; } + + public string String2 { get; set; } + + public int Number { get; set; } + + protected override object ProvideValue() + { + return $"{String1 ?? string.Empty} AND {String2 ?? string.Empty} THEN #{Number}"; + } + } + + [MarkupExtensionReturnType(ReturnType = typeof(IValueConverter))] + public class InverseBoolMarkup : MarkupExtension, IValueConverter + { + protected override object ProvideValue() => this; + + public object Convert(object value, Type targetType, object parameter, string language) + { + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return !(bool)value; + } + } + + [MarkupExtensionReturnType(ReturnType = typeof(TestObject))] + public class ComplexMarkup : MarkupExtension + { + public string String { get; set; } + + public int Number { get; set; } + + public bool Boolean { get; set; } + + protected override object ProvideValue() + { + return new TestObject() + { + StringProp = String, + IntProp = Number + }; + } + } + + public static class MarkupExtensionTestBehavior + { + public static string GetCustomText(TextBlock obj) => (string)obj.GetValue(CustomTextProperty); + + public static void SetCustomText(TextBlock obj, string value) => obj.SetValue(CustomTextProperty, value); + + public static readonly DependencyProperty CustomTextProperty = + DependencyProperty.RegisterAttached( + "CustomText", + typeof(string), + typeof(MarkupExtensionTestBehavior), + new PropertyMetadata(string.Empty, OnCustomTextChanged)); + + private static void OnCustomTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) + { + if (dependencyObject is TextBlock tb) + { + tb.Text = GetCustomText(tb); + } + } + } +} diff --git a/src/TargetFrameworkSelection.targets b/src/TargetFrameworkSelection.targets index 2e424370b2d7..8b4bee6a10b7 100644 --- a/src/TargetFrameworkSelection.targets +++ b/src/TargetFrameworkSelection.targets @@ -30,11 +30,10 @@ + BeforeTargets="@(_OverrideTargetFrameworksDependency)"> - $(TargetFrameworks) + $(TargetFrameworks) $(TargetFrameworksCI) <_CanOverrideFramework>false @@ -49,7 +48,7 @@ - + diff --git a/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj b/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj index f03db5b37183..16d74e7b45b0 100644 --- a/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj +++ b/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj @@ -6,10 +6,10 @@ True obj\$(TargetFramework)\Resources\Resource.Designer.cs - + false true - + true <_isWindows>$([MSBuild]::IsOsPlatform(Windows)) @@ -22,7 +22,7 @@ 28.0.3 - + @@ -56,14 +56,14 @@ - + - @@ -89,10 +89,10 @@ GenerateBindings target is not given proper api mappings, ending in the generation of an empty assembly. --> - + - + <_CompileUnoJavaBeforeTargets Include="ExportJarToXml"/> <_CompileUnoJavaBeforeTargets Include="GenerateBindings"/> @@ -108,8 +108,8 @@ AfterTargets="@(_CompileUnoJavaAfterTargets)" Inputs="@(_JavaFile)" Outputs="@(EmbeddedJar)" - DependsOnTargets="_CompileUnoJavaCreateOutputs;@(XamarinBuildRestoreResources);_FillMsBuildVersion"> - + DependsOnTargets="_CompileUnoJavaCreateOutputs;@(XamarinBuildRestoreResources)"> + <_AndroidJar Include="%ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\MonoAndroid\$(TargetFrameworkVersion)\mono.android.jar" /> <_AndroidJar Include="$(IntermediateOutputPath)\__library_projects__\Xamarin.Android.Support.Annotations\library_project_imports\support-annotations.jar" /> @@ -119,11 +119,11 @@ <_JavaVersion>1.8 - <_JavaVersion Condition="'$(MicrosoftBuildVersion)' < '15.4'">1.7 + <_JavaVersion Condition="'$(MSBuildVersion)' < '15.4'">1.7 <_JavaCBinPath>javac <_JavaCBinPath Condition="Exists('$(_JavaSdkDirectory)bin\javac.exe')">$(_JavaSdkDirectory)bin\javac.exe - + <_JarBinPath>$(_JavaSdkDirectory)bin\jar <_JarBinPath Condition="Exists('$(_JavaSdkDirectory)bin\jar.exe')">$(_JavaSdkDirectory)bin\jar.exe @@ -132,17 +132,17 @@ <_CompileCommand>"$(_JavaCBinPath)" -g -source $(_javaVersion) -d .\$(IntermediateOutputPath)\unoclasses -target $(_javaVersion) -J-Dfile.encoding=UTF8 -classpath "$(_flattenAndroidJar)" -bootclasspath "$(_AndroidSdkDirectory)platforms\android-$(_AndroidApiLevel)\android.jar" -encoding UTF-8 .\Uno\UI\*.java - + - + - + - + @@ -154,7 +154,7 @@ - + diff --git a/src/Uno.UI.TestComparer/Uno.UI.TestComparer.csproj b/src/Uno.UI.TestComparer/Uno.UI.TestComparer.csproj index e9122820187b..7c5dd1ccdf2b 100644 --- a/src/Uno.UI.TestComparer/Uno.UI.TestComparer.csproj +++ b/src/Uno.UI.TestComparer/Uno.UI.TestComparer.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/Uno.UI.Tests/App/Behaviors/AttachedPropertiesBehavior.cs b/src/Uno.UI.Tests/App/Behaviors/AttachedPropertiesBehavior.cs new file mode 100644 index 000000000000..2779ec6d48ac --- /dev/null +++ b/src/Uno.UI.Tests/App/Behaviors/AttachedPropertiesBehavior.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace Uno.UI.Tests.App.Behaviors +{ + public static class AttachedPropertiesBehavior + { + public static string GetCustomText(TextBlock obj) => (string)obj.GetValue(CustomTextProperty); + + public static void SetCustomText(TextBlock obj, string value) => obj.SetValue(CustomTextProperty, value); + + public static readonly DependencyProperty CustomTextProperty = + DependencyProperty.RegisterAttached( + "CustomText", + typeof(string), + typeof(AttachedPropertiesBehavior), + new PropertyMetadata(string.Empty, OnCustomTextChanged)); + + private static void OnCustomTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) + { + if (dependencyObject is TextBlock tb) + { + tb.Text = GetCustomText(tb); + } + } + } +} diff --git a/src/Uno.UI.Tests/App/Xaml/Test_MarkupExtension.xaml b/src/Uno.UI.Tests/App/Xaml/Test_MarkupExtension.xaml new file mode 100644 index 000000000000..e7aae496a557 --- /dev/null +++ b/src/Uno.UI.Tests/App/Xaml/Test_MarkupExtension.xaml @@ -0,0 +1,41 @@ + + + + From a Resource String + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Uno.UI.Tests/App/Xaml/Test_MarkupExtension.xaml.cs b/src/Uno.UI.Tests/App/Xaml/Test_MarkupExtension.xaml.cs new file mode 100644 index 000000000000..d524bd4f0488 --- /dev/null +++ b/src/Uno.UI.Tests/App/Xaml/Test_MarkupExtension.xaml.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace Uno.UI.Tests.App.Xaml +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class Test_MarkupExtension : UserControl + { + public TextBlock TestText1 => Text1; + public TextBlock TestText2 => Text2; + public TextBlock TestText3 => Text3; + public TextBlock TestText4 => Text4; + public TextBlock TestText5 => Text5; + public TextBlock TestText6 => Text6; + public TextBlock TestText7 => Text7; + + public Test_MarkupExtension() + { + this.InitializeComponent(); + } + } +} diff --git a/src/Uno.UI.Tests/Uno.UI.Tests.csproj b/src/Uno.UI.Tests/Uno.UI.Tests.csproj index 707192593b9b..e35d8e7a46b1 100644 --- a/src/Uno.UI.Tests/Uno.UI.Tests.csproj +++ b/src/Uno.UI.Tests/Uno.UI.Tests.csproj @@ -23,7 +23,7 @@ - + @@ -102,6 +102,7 @@ + diff --git a/src/Uno.UI.Tests/Windows_UI_Xaml/MarkupExtensionTests/Given_MarkupExtension.cs b/src/Uno.UI.Tests/Windows_UI_Xaml/MarkupExtensionTests/Given_MarkupExtension.cs new file mode 100644 index 000000000000..b38468096a6c --- /dev/null +++ b/src/Uno.UI.Tests/Windows_UI_Xaml/MarkupExtensionTests/Given_MarkupExtension.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Uno.UI.Tests.App.Xaml; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Markup; + +namespace Uno.UI.Tests.Windows_UI_Xaml.MarkupExtensionTests +{ + [TestClass] + public class Given_MarkupExtension + { + [TestMethod] + public void When_ExtensionProvidesValues() + { + var app = UnitTestsApp.App.EnsureApplication(); + + var control = new Test_MarkupExtension(); + app.HostView.Children.Add(control); + + Assert.AreEqual("Just a simple ... markup extension", control.TestText1.Text); + Assert.AreEqual("We should see the number 100 below:", control.TestText2.Text); + Assert.AreEqual("100", control.TestText3.Text); + Assert.AreEqual("True", control.TestText4.Text); + Assert.AreEqual("From a Resource String markup extension", control.TestText5.Text); + Assert.AreEqual("String from attached property markup extension", control.TestText6.Text); + Assert.AreEqual("True", control.TestText7.Text); + } + } + + [MarkupExtensionReturnType(ReturnType = typeof(string))] + public class SimpleMarkupExt : Windows.UI.Xaml.Markup.MarkupExtension + { + public string TextValue { get; set; } + + protected override object ProvideValue() + { + return TextValue + " markup extension"; + } + } + + [MarkupExtensionReturnType(ReturnType = typeof(TestEntityObject))] + public class EntityMarkupExt : Windows.UI.Xaml.Markup.MarkupExtension + { + public string TextValue { get; set; } + + public int IntValue { get; set; } + + protected override object ProvideValue() + { + return new TestEntityObject() + { + StringProperty = TextValue, + IntProperty = IntValue + }; + } + } + + [MarkupExtensionReturnType(ReturnType = typeof(IValueConverter))] + public class InverseBoolMarkupExt : Windows.UI.Xaml.Markup.MarkupExtension, IValueConverter + { + protected override object ProvideValue() => this; + + public object Convert(object value, Type targetType, object parameter, string language) + { + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return !(bool)value; + } + } + + public class TestEntityObject + { + public string StringProperty { get; set; } = string.Empty; + + public int IntProperty { get; set; } + } +} diff --git a/src/Uno.UI/UI/Xaml/Markup/IMarkupExtensionOverrides.cs b/src/Uno.UI/UI/Xaml/Markup/IMarkupExtensionOverrides.cs new file mode 100644 index 000000000000..d3d0d690d9d9 --- /dev/null +++ b/src/Uno.UI/UI/Xaml/Markup/IMarkupExtensionOverrides.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Windows.UI.Xaml.Markup +{ + public partial interface IMarkupExtensionOverrides + { + object ProvideValue(); + } +} diff --git a/src/Uno.UI/UI/Xaml/Markup/MarkupExtensions.cs b/src/Uno.UI/UI/Xaml/Markup/MarkupExtensions.cs new file mode 100644 index 000000000000..366f1c676f19 --- /dev/null +++ b/src/Uno.UI/UI/Xaml/Markup/MarkupExtensions.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Windows.UI.Xaml.Markup +{ + public partial class MarkupExtension : IMarkupExtensionOverrides + { + object IMarkupExtensionOverrides.ProvideValue() + { + return ProvideValue(); + } + } +}