diff --git a/UI/HtmlControls/HtmlControls.Shared/App.xaml.cs b/UI/HtmlControls/HtmlControls.Shared/App.xaml.cs index 23c6092bc..b9ba8b0b0 100644 --- a/UI/HtmlControls/HtmlControls.Shared/App.xaml.cs +++ b/UI/HtmlControls/HtmlControls.Shared/App.xaml.cs @@ -1,20 +1,10 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; +using System; +using Microsoft.Extensions.Logging; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; -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; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Navigation; namespace HtmlControls { @@ -23,13 +13,8 @@ namespace HtmlControls /// public sealed partial class App : Application { -#if NET5_0 && WINDOWS private Window _window; -#else - private Windows.UI.Xaml.Window _window; -#endif - /// /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). @@ -49,8 +34,8 @@ public App() /// Invoked when the application is launched normally by the end user. Other entry points /// will be used such as when the application is launched to open a specific file. /// - /// Details about the launch request and process. - protected override void OnLaunched(LaunchActivatedEventArgs e) + /// Details about the launch request and process. + protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { #if DEBUG if (System.Diagnostics.Debugger.IsAttached) @@ -59,11 +44,11 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) } #endif -#if NET6_0_OR_GREATER && WINDOWS +#if NET6_0_OR_GREATER && WINDOWS && !HAS_UNO _window = new Window(); _window.Activate(); #else - _window = Windows.UI.Xaml.Window.Current; + _window = Microsoft.UI.Xaml.Window.Current; #endif var rootFrame = _window.Content as Frame; @@ -77,9 +62,9 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) rootFrame.NavigationFailed += OnNavigationFailed; - if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) + if (args.UWPLaunchActivatedEventArgs.PreviousExecutionState == ApplicationExecutionState.Terminated) { - //TODO: Load state from previously suspended application + // TODO: Load state from previously suspended application } // Place the frame in the current Window @@ -87,7 +72,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) } #if !(NET6_0_OR_GREATER && WINDOWS) - if (e.PrelaunchActivated == false) + if (args.UWPLaunchActivatedEventArgs.PrelaunchActivated == false) #endif { if (rootFrame.Content == null) @@ -95,7 +80,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) // When the navigation stack isn't restored navigate to the first page, // configuring the new page by passing required information as a navigation // parameter - rootFrame.Navigate(typeof(MainPage), e.Arguments); + rootFrame.Navigate(typeof(MainPage), args.Arguments); } // Ensure the current window is active _window.Activate(); @@ -109,7 +94,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) /// Details about the navigation failure void OnNavigationFailed(object sender, NavigationFailedEventArgs e) { - throw new Exception($"Failed to load {e.SourcePageType.FullName}: {e.Exception}"); + throw new InvalidOperationException($"Failed to load {e.SourcePageType.FullName}: {e.Exception}"); } /// @@ -131,6 +116,14 @@ private void OnSuspending(object sender, SuspendingEventArgs e) /// private static void InitializeLogging() { +#if DEBUG + // Logging is disabled by default for release builds, as it incurs a significant + // initialization cost from Microsoft.Extensions.Logging setup. If startup performance + // is a concern for your application, keep this disabled. If you're running on web or + // desktop targets, you can use url or command line parameters to enable it. + // + // For more performance documentation: https://platform.uno/docs/articles/Uno-UI-Performance.html + var factory = LoggerFactory.Create(builder => { #if __WASM__ @@ -152,22 +145,22 @@ private static void InitializeLogging() builder.AddFilter("Microsoft", LogLevel.Warning); // Generic Xaml events - // builder.AddFilter("Windows.UI.Xaml", LogLevel.Debug ); - // builder.AddFilter("Windows.UI.Xaml.VisualStateGroup", LogLevel.Debug ); - // builder.AddFilter("Windows.UI.Xaml.StateTriggerBase", LogLevel.Debug ); - // builder.AddFilter("Windows.UI.Xaml.UIElement", LogLevel.Debug ); - // builder.AddFilter("Windows.UI.Xaml.FrameworkElement", LogLevel.Trace ); + // builder.AddFilter("Microsoft.UI.Xaml", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.VisualStateGroup", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.StateTriggerBase", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.UIElement", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.FrameworkElement", LogLevel.Trace ); // Layouter specific messages - // builder.AddFilter("Windows.UI.Xaml.Controls", LogLevel.Debug ); - // builder.AddFilter("Windows.UI.Xaml.Controls.Layouter", LogLevel.Debug ); - // builder.AddFilter("Windows.UI.Xaml.Controls.Panel", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.Controls", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.Controls.Layouter", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.Controls.Panel", LogLevel.Debug ); // builder.AddFilter("Windows.Storage", LogLevel.Debug ); // Binding related messages - // builder.AddFilter("Windows.UI.Xaml.Data", LogLevel.Debug ); - // builder.AddFilter("Windows.UI.Xaml.Data", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.Data", LogLevel.Debug ); + // builder.AddFilter("Microsoft.UI.Xaml.Data", LogLevel.Debug ); // Binder memory references tracking // builder.AddFilter("Uno.UI.DataBinding.BinderReferenceHolder", LogLevel.Debug ); @@ -180,6 +173,11 @@ private static void InitializeLogging() }); global::Uno.Extensions.LogExtensionPoint.AmbientLoggerFactory = factory; + +#if HAS_UNO + global::Uno.UI.Adapter.Microsoft.Extensions.Logging.LoggingAdapter.Initialize(); +#endif +#endif } } } diff --git a/UI/HtmlControls/HtmlControls.Shared/MainPage.xaml b/UI/HtmlControls/HtmlControls.Shared/MainPage.xaml index ba73cdf74..47aca9356 100644 --- a/UI/HtmlControls/HtmlControls.Shared/MainPage.xaml +++ b/UI/HtmlControls/HtmlControls.Shared/MainPage.xaml @@ -8,25 +8,50 @@ xmlns:html="using:HtmlControls" mc:Ignorable="d"> - - HtmlTimePicker <input type='time' /> - - + + + HtmlTimePicker <input type='time' /> + + - HtmlDatePicker <input type='date' /> - - + HtmlDatePicker <input type='date' /> + + - HtmlNumberInput <input type='number' /> - - + HtmlNumberInput <input type='number' /> + + - HtmlColorPicker <input type='color' /> - - + HtmlColorPicker <input type='color' /> + + - HtmlRangeInput <input type='range' /> - - - + HtmlRangeInput <input type='range' /> + + + + HtmlProgress <progress/> + + + HtmlMeter <meter/> + + + HtmlHxText <h1 />, <h2 />, <h3 />, <h4 /> + + + + + + + HtmlSelect / HtmlOption <select />, <option /> + + + Option 1 + Option 2 + Option 3 + + + + + diff --git a/UI/HtmlControls/HtmlControls.Shared/MainPage.xaml.cs b/UI/HtmlControls/HtmlControls.Shared/MainPage.xaml.cs index 24cb4bd88..603c1fe8f 100644 --- a/UI/HtmlControls/HtmlControls.Shared/MainPage.xaml.cs +++ b/UI/HtmlControls/HtmlControls.Shared/MainPage.xaml.cs @@ -1,19 +1,4 @@ -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 http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 +using Microsoft.UI.Xaml.Controls; namespace HtmlControls { diff --git a/UI/HtmlControls/HtmlControls.Wasm/HtmlControls.Wasm.csproj b/UI/HtmlControls/HtmlControls.Wasm/HtmlControls.Wasm.csproj index b81a8e62f..ba2b5fc44 100644 --- a/UI/HtmlControls/HtmlControls.Wasm/HtmlControls.Wasm.csproj +++ b/UI/HtmlControls/HtmlControls.Wasm/HtmlControls.Wasm.csproj @@ -1,51 +1,57 @@ - - Exe - net5.0 - NU1701 - - - true - $(DefineConstants);TRACE;DEBUG - portable - true - - - - - - - - - - - - - - - - + false + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + You can safely remove this ItemGroup completely. + --> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UI/HtmlControls/HtmlControls.Wasm/Program.cs b/UI/HtmlControls/HtmlControls.Wasm/Program.cs index 0d24c37e4..c64b29451 100644 --- a/UI/HtmlControls/HtmlControls.Wasm/Program.cs +++ b/UI/HtmlControls/HtmlControls.Wasm/Program.cs @@ -9,7 +9,7 @@ public class Program static int Main(string[] args) { - Windows.UI.Xaml.Application.Start(_ => _app = new App()); + Microsoft.UI.Xaml.Application.Start(_ => _app = new App()); return 0; } diff --git a/UI/HtmlControls/HtmlControls.Wasm/Properties/launchSettings.json b/UI/HtmlControls/HtmlControls.Wasm/Properties/launchSettings.json index aeb27fcea..bfe0145fd 100644 --- a/UI/HtmlControls/HtmlControls.Wasm/Properties/launchSettings.json +++ b/UI/HtmlControls/HtmlControls.Wasm/Properties/launchSettings.json @@ -3,25 +3,28 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:10385/", - "sslPort": 44320 + "applicationUrl": "http://localhost:8080", + "sslPort": 0 } }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", + "HtmlControls.Wasm": { + "commandName": "Project", + "dotnetRunMessages": true, "launchBrowser": true, + "applicationUrl": "http://localhost:5000", + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, - "HtmlControls.Wasm": { - "commandName": "Project", + "IIS Express": { + "commandName": "IISExpress", "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "https://localhost:5001;http://localhost:5000" + } } } -} \ No newline at end of file +} diff --git a/UI/HtmlControls/HtmlControls.Wasm/WasmScripts/AppManifest.js b/UI/HtmlControls/HtmlControls.Wasm/WasmScripts/AppManifest.js index d2ab6243d..c061c94ed 100644 --- a/UI/HtmlControls/HtmlControls.Wasm/WasmScripts/AppManifest.js +++ b/UI/HtmlControls/HtmlControls.Wasm/WasmScripts/AppManifest.js @@ -1,7 +1,7 @@ var UnoAppManifest = { splashScreenImage: "Assets/SplashScreen.png", - splashScreenColor: "#fff", + splashScreenColor: "transparent", displayName: "HtmlControls" } diff --git a/UI/HtmlControls/HtmlControls/HtmlColorPicker.cs b/UI/HtmlControls/HtmlControls/HtmlColorPicker.cs index 88aa516ff..2f9e919e9 100644 --- a/UI/HtmlControls/HtmlControls/HtmlColorPicker.cs +++ b/UI/HtmlControls/HtmlControls/HtmlColorPicker.cs @@ -2,11 +2,12 @@ using System.Globalization; using System.Runtime.CompilerServices; using Windows.Foundation; -using Windows.UI; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Media; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; using Uno.Extensions; using Uno.UI.Runtime.WebAssembly; +using Windows.UI; namespace HtmlControls { diff --git a/UI/HtmlControls/HtmlControls/HtmlControls.csproj b/UI/HtmlControls/HtmlControls/HtmlControls.csproj index df384a8ef..840201068 100644 --- a/UI/HtmlControls/HtmlControls/HtmlControls.csproj +++ b/UI/HtmlControls/HtmlControls/HtmlControls.csproj @@ -1,11 +1,11 @@  - netstandard2.0 + net6.0 - + diff --git a/UI/HtmlControls/HtmlControls/HtmlDatePicker.cs b/UI/HtmlControls/HtmlControls/HtmlDatePicker.cs index 3dab49e61..21fcc8915 100644 --- a/UI/HtmlControls/HtmlControls/HtmlDatePicker.cs +++ b/UI/HtmlControls/HtmlControls/HtmlDatePicker.cs @@ -2,9 +2,9 @@ using System.Globalization; using System.Runtime.CompilerServices; using Windows.Foundation; -using Windows.UI; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Media; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; using Uno.Extensions; using Uno.UI.Runtime.WebAssembly; diff --git a/UI/HtmlControls/HtmlControls/HtmlH1Text.cs b/UI/HtmlControls/HtmlControls/HtmlH1Text.cs new file mode 100644 index 000000000..a09e7422c --- /dev/null +++ b/UI/HtmlControls/HtmlControls/HtmlH1Text.cs @@ -0,0 +1,43 @@ +using Windows.Foundation; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; +using Uno.Extensions; +using Uno.UI.Runtime.WebAssembly; + +namespace HtmlControls +{ + [HtmlElement("h1")] + public partial class HtmlH1Text : FrameworkElement + { + public HtmlH1Text() + { + // Avoid flicking while we're measuring the element + this.SetCssStyle("overflow", "hidden"); + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(HtmlH1Text), new PropertyMetadata("", propertyChangedCallback: OnTextChanged)); + + public string Text + { + get => (string)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlH1Text element && args.NewValue is string text) + { + element.SetHtmlContent(text); + element.InvalidateMeasure(); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + // Delegate measurement to Html

element + return this.MeasureHtmlView(availableSize, false); + } + } +} diff --git a/UI/HtmlControls/HtmlControls/HtmlH2Text.cs b/UI/HtmlControls/HtmlControls/HtmlH2Text.cs new file mode 100644 index 000000000..5dceb71bb --- /dev/null +++ b/UI/HtmlControls/HtmlControls/HtmlH2Text.cs @@ -0,0 +1,44 @@ +using Windows.Foundation; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; +using Uno.UI.Runtime.WebAssembly; + +namespace HtmlControls +{ + [HtmlElement("h2")] + public partial class HtmlH2Text : FrameworkElement + { + public HtmlH2Text() + { + // Avoid flicking while we're measuring the element + this.SetCssStyle("overflow", "hidden"); + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(HtmlH2Text), new PropertyMetadata("", propertyChangedCallback: OnTextChanged)); + + public string Text + { + get => (string)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlH2Text element && args.NewValue is string text) + { + element.SetHtmlContent(text); + element.InvalidateMeasure(); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + // Delegate measurement to Html

element + return this.MeasureHtmlView(availableSize, false); + } + } + + +} diff --git a/UI/HtmlControls/HtmlControls/HtmlH3Text.cs b/UI/HtmlControls/HtmlControls/HtmlH3Text.cs new file mode 100644 index 000000000..f6b880f72 --- /dev/null +++ b/UI/HtmlControls/HtmlControls/HtmlH3Text.cs @@ -0,0 +1,44 @@ +using Windows.Foundation; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; +using Uno.UI.Runtime.WebAssembly; + +namespace HtmlControls +{ + [HtmlElement("h3")] + public partial class HtmlH3Text : FrameworkElement + { + public HtmlH3Text() + { + // Avoid flicking while we're measuring the element + this.SetCssStyle("overflow", "hidden"); + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(HtmlH3Text), new PropertyMetadata("", propertyChangedCallback: OnTextChanged)); + + public string Text + { + get => (string)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlH3Text element && args.NewValue is string text) + { + element.SetHtmlContent(text); + element.InvalidateMeasure(); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + // Delegate measurement to Html

element + return this.MeasureHtmlView(availableSize, false); + } + } + + +} diff --git a/UI/HtmlControls/HtmlControls/HtmlH4Text.cs b/UI/HtmlControls/HtmlControls/HtmlH4Text.cs new file mode 100644 index 000000000..4879dd76d --- /dev/null +++ b/UI/HtmlControls/HtmlControls/HtmlH4Text.cs @@ -0,0 +1,44 @@ +using Windows.Foundation; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; +using Uno.UI.Runtime.WebAssembly; + +namespace HtmlControls +{ + [HtmlElement("h4")] + public partial class HtmlH4Text : FrameworkElement + { + public HtmlH4Text() + { + // Avoid flicking while we're measuring the element + this.SetCssStyle("overflow", "hidden"); + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(HtmlH4Text), new PropertyMetadata("", propertyChangedCallback: OnTextChanged)); + + public string Text + { + get => (string)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlH4Text element && args.NewValue is string text) + { + element.SetHtmlContent(text); + element.InvalidateMeasure(); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + // Delegate measurement to Html

element + return this.MeasureHtmlView(availableSize, false); + } + } + + +} diff --git a/UI/HtmlControls/HtmlControls/HtmlMeter.cs b/UI/HtmlControls/HtmlControls/HtmlMeter.cs new file mode 100644 index 000000000..75f157d47 --- /dev/null +++ b/UI/HtmlControls/HtmlControls/HtmlMeter.cs @@ -0,0 +1,73 @@ +using System; +using System.Globalization; +using System.Runtime.CompilerServices; +using Windows.Foundation; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; +using Uno.Extensions; +using Uno.UI.Runtime.WebAssembly; + +namespace HtmlControls +{ + [HtmlElement("meter")] + public partial class HtmlMeter : FrameworkElement + { + public static readonly DependencyProperty MinProperty = DependencyProperty.Register( + "Min", typeof(double), typeof(HtmlMeter), new PropertyMetadata(0d, propertyChangedCallback: OnMinChanged)); + + public double Min + { + get => (double)GetValue(MinProperty); + set => SetValue(MinProperty, value); + } + + private static void OnMinChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlMeter meter && args.NewValue is double min) + { + meter.SetHtmlAttribute("min", min.ToString()); + } + } + + public static readonly DependencyProperty MaxProperty = DependencyProperty.Register( + "Max", typeof(double), typeof(HtmlMeter), new PropertyMetadata(1.0d, propertyChangedCallback: OnMaxChanged)); + + public double Max + { + get => (double)GetValue(MaxProperty); + set => SetValue(MaxProperty, value); + } + + private static void OnMaxChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlMeter meter && args.NewValue is double max) + { + meter.SetHtmlAttribute("max", max.ToString()); + } + } + + public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( + "Value", typeof(double), typeof(HtmlMeter), new PropertyMetadata(default(double), propertyChangedCallback: OnValueChanged)); + + public double Value + { + get => (double)GetValue(ValueProperty); + set => SetValue(ValueProperty, value); + } + + private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlMeter meter && args.NewValue is double value) + { + meter.SetHtmlAttribute("value", value.ToString()); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + // Delegate measurement to Html element + return this.MeasureHtmlView(availableSize, false); + } + } +} \ No newline at end of file diff --git a/UI/HtmlControls/HtmlControls/HtmlNumberInput.cs b/UI/HtmlControls/HtmlControls/HtmlNumberInput.cs index 17e4a6c88..43c37ae5a 100644 --- a/UI/HtmlControls/HtmlControls/HtmlNumberInput.cs +++ b/UI/HtmlControls/HtmlControls/HtmlNumberInput.cs @@ -2,9 +2,9 @@ using System.Globalization; using System.Runtime.CompilerServices; using Windows.Foundation; -using Windows.UI; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Media; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; using Uno.Extensions; using Uno.UI.Runtime.WebAssembly; diff --git a/UI/HtmlControls/HtmlControls/HtmlOption.cs b/UI/HtmlControls/HtmlControls/HtmlOption.cs new file mode 100644 index 000000000..6f63dd669 --- /dev/null +++ b/UI/HtmlControls/HtmlControls/HtmlOption.cs @@ -0,0 +1,53 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Markup; +using Uno.UI.Runtime.WebAssembly; + +namespace HtmlControls +{ + [HtmlElement("option")] + [ContentProperty(Name = nameof(Content))] + public partial class HtmlOption : UIElement + { + public static DependencyProperty ContentProperty { get; } = DependencyProperty.Register( + "ContentProperty", typeof(string), typeof(HtmlOption), new PropertyMetadata(null, OnContentChanged)); + + public string Content + { + get => (string)GetValue(ContentProperty); + set => SetValue(ContentProperty, value); + } + + private static void OnContentChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlOption option) + { + if (args.NewValue is string str) + { + // TODO: Clearchildren no longer accessible + //option.ClearChildren(); + option.SetHtmlContent(str); + } + } + } + + public static DependencyProperty ValueProperty { get; } = DependencyProperty.Register( + "ValueProperty", typeof(string), typeof(HtmlOption), new PropertyMetadata(null, OnValueChanged)); + + public string Value + { + get => (string)GetValue(ValueProperty); + set => SetValue(ValueProperty, value); + } + + private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlOption option) + { + if (args.NewValue is string str) + { + option.SetHtmlAttribute("value", str); + } + } + } + } +} diff --git a/UI/HtmlControls/HtmlControls/HtmlProgress.cs b/UI/HtmlControls/HtmlControls/HtmlProgress.cs new file mode 100644 index 000000000..50ee94e2e --- /dev/null +++ b/UI/HtmlControls/HtmlControls/HtmlProgress.cs @@ -0,0 +1,62 @@ +using System; +using System.Globalization; +using System.Runtime.CompilerServices; +using Windows.Foundation; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; +using Uno.Extensions; +using Uno.UI.Runtime.WebAssembly; + +namespace HtmlControls +{ + [HtmlElement("progress")] + public partial class HtmlProgress : FrameworkElement + { + public HtmlProgress() + { + // Set a background to ensure pointer events are allowed + Background = new SolidColorBrush(Colors.Transparent); + } + + public static readonly DependencyProperty MaxProperty = DependencyProperty.Register( + "Max", typeof(double), typeof(HtmlProgress), new PropertyMetadata(1.0d, propertyChangedCallback: OnMaxChanged)); + + public double Max + { + get => (double)GetValue(MaxProperty); + set => SetValue(MaxProperty, value); + } + + private static void OnMaxChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlProgress progress && args.NewValue is double max) + { + progress.SetHtmlAttribute("max", max.ToString()); + } + } + + public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( + "Value", typeof(double), typeof(HtmlProgress), new PropertyMetadata(default(double), propertyChangedCallback: OnValueChanged)); + + public double Value + { + get => (double)GetValue(ValueProperty); + set => SetValue(ValueProperty, value); + } + + private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlProgress progress && args.NewValue is double value) + { + progress.SetHtmlAttribute("value", value.ToString()); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + // Delegate measurement to Html element + return this.MeasureHtmlView(availableSize, false); + } + } +} \ No newline at end of file diff --git a/UI/HtmlControls/HtmlControls/HtmlRangeInput.cs b/UI/HtmlControls/HtmlControls/HtmlRangeInput.cs index 00f7cd2d6..c2edf1d92 100644 --- a/UI/HtmlControls/HtmlControls/HtmlRangeInput.cs +++ b/UI/HtmlControls/HtmlControls/HtmlRangeInput.cs @@ -1,9 +1,9 @@ using System; using System.Globalization; using Windows.Foundation; -using Windows.UI; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Media; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; using Uno.Extensions; using Uno.UI.Runtime.WebAssembly; diff --git a/UI/HtmlControls/HtmlControls/HtmlSelect.cs b/UI/HtmlControls/HtmlControls/HtmlSelect.cs new file mode 100644 index 000000000..9f794a739 --- /dev/null +++ b/UI/HtmlControls/HtmlControls/HtmlSelect.cs @@ -0,0 +1,118 @@ +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using Windows.Foundation; +using Microsoft.UI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Markup; +using Microsoft.UI.Xaml.Media; +using Uno.UI.Runtime.WebAssembly; +using System; +using Uno.Extensions; +using System.Globalization; + +namespace HtmlControls +{ + [HtmlElement("select")] + [ContentProperty(Name = nameof(Options))] + public partial class HtmlSelect : FrameworkElement + { + public ObservableCollection Options { get; } = new ObservableCollection(); + + public HtmlSelect() + { + // Set a background to ensure pointer events are allowed + Background = new SolidColorBrush(Colors.Transparent); + + Options.CollectionChanged += OnOptionsChanged; + + this.ExecuteJavascript("element.addEventListener(\"change\", ()=>element.dispatchEvent(new CustomEvent(\"value\", {detail: \"\"+element.selectedIndex})));"); + this.ExecuteJavascript("element.addEventListener(\"loaded\", ()=>element.dispatchEvent(new CustomEvent(\"value\", {detail: \"\"+element.selectedIndex})));"); + this.RegisterHtmlCustomEventHandler("value", OnHtmlSelectionChanged); + } + + private void OnHtmlSelectionChanged(object sender, HtmlCustomEventArgs e) + { + if(int.TryParse(e.Detail, System.Globalization.NumberStyles.Integer | NumberStyles.AllowLeadingSign, NumberFormatInfo.InvariantInfo, out var index)) + { + SelectedIndex = index; + + if (index < 0) + { + // No selection + SelectedValue = null; + } + else + { + SelectedValue = Options[index].Value; + } + } + } + + public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register( + "SelectedValue", typeof(string), typeof(HtmlSelect), new PropertyMetadata(default(string), propertyChangedCallback: OnSelectedValueChanged)); + + public string SelectedValue + { + get => (string)GetValue(SelectedValueProperty); + set => SetValue(SelectedValueProperty, value); + } + + private static void OnSelectedValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlSelect select && args.NewValue is string selectedValue) + { + // TODO + } + } + + public static readonly DependencyProperty SelectedIndexProperty = DependencyProperty.Register( + "SelectedIndex", typeof(int), typeof(HtmlSelect), new PropertyMetadata(default(int), propertyChangedCallback: OnSelectedIndexChanged)); + + public int SelectedIndex + { + get => (int)GetValue(SelectedIndexProperty); + set => SetValue(SelectedIndexProperty, value); + } + + private static void OnSelectedIndexChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + if (o is HtmlSelect select && args.NewValue is int selectedIndex) + { + select.ExecuteJavascript($"element.selectedIndex={selectedIndex};"); + } + } + + private void OnOptionsChanged(object sender, NotifyCollectionChangedEventArgs e) + { + // TODO: Need a fix for calling AddChild/RemoveChild + //switch(e.Action) + //{ + // case NotifyCollectionChangedAction.Add: + // { + // var index = e.NewStartingIndex; + // foreach(var newItem in e.NewItems) + // { + // AddChild(newItem as UIElement, index++); + // } + // break; + // } + // case NotifyCollectionChangedAction.Remove: + // { + // foreach (var removedItem in e.OldItems) + // { + // RemoveChild(removedItem as UIElement); + // } + // break; + // } + // default: + // throw new NotSupportedException($"CollectionChanged Action \"{e.Action}\" not supported yet."); + //} + } + + protected override Size MeasureOverride(Size availableSize) + { + // Delegate measurement to Html