-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0c2d807
commit 4f3632d
Showing
28 changed files
with
1,107 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
global using System; | ||
global using System.Collections.Generic; | ||
global using System.Linq; | ||
global using System.Text; | ||
global using System.Threading.Tasks; | ||
global using Microsoft.Extensions.DependencyInjection; | ||
global using Microsoft.Extensions.Logging; | ||
global using Microsoft.Maui.Embedding; | ||
global using Microsoft.Maui.Platform; | ||
global using Microsoft.UI.Xaml; | ||
global using Microsoft.UI.Xaml.Controls; | ||
global using Microsoft.UI.Xaml.Markup; | ||
global using Uno.Extensions.Maui.Properties; | ||
global using Application = Microsoft.UI.Xaml.Application; | ||
global using MauiApplication = Microsoft.Maui.Controls.Application; | ||
global using Binding = Microsoft.Maui.Controls.Binding; | ||
global using BindingMode = Microsoft.Maui.Controls.BindingMode; | ||
global using View = Microsoft.Maui.Controls.View; | ||
global using MauiApp = Microsoft.Maui.Hosting.MauiApp; | ||
global using MauiAppBuilder = Microsoft.Maui.Hosting.MauiAppBuilder; | ||
global using IMauiContext = Microsoft.Maui.IMauiContext; | ||
global using MauiContext = Microsoft.Maui.MauiContext; | ||
global using NativeMauiBinding = Microsoft.Maui.Controls.Binding; | ||
global using WinUIColor = Windows.UI.Color; | ||
global using NativeMauiColor = Microsoft.Maui.Graphics.Color; | ||
global using MauiResourceDictionary = Microsoft.Maui.Controls.ResourceDictionary; | ||
global using MauiConverter = Microsoft.Maui.Controls.IValueConverter; | ||
global using WinUIConverter = Microsoft.UI.Xaml.Data.IValueConverter; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
namespace Uno.Extensions.Maui.Internals; | ||
|
||
internal static class ConversionExtensions | ||
{ | ||
public static Microsoft.Maui.Controls.ResourceDictionary ToMauiResources(this ResourceDictionary input) | ||
{ | ||
var output = new Microsoft.Maui.Controls.ResourceDictionary(); | ||
foreach (var merged in input.MergedDictionaries) | ||
{ | ||
output.MergedDictionaries.Add(merged.ToMauiResources()); | ||
} | ||
|
||
foreach (var key in input.Keys) | ||
{ | ||
if (input.MergedDictionaries.Any(x => x.ContainsKey(key))) | ||
{ | ||
continue; | ||
} | ||
|
||
TryAddValue(ref output, key, input[key]); | ||
} | ||
|
||
return output; | ||
} | ||
|
||
private static void TryAddValue(ref Microsoft.Maui.Controls.ResourceDictionary resources, object sourceKey, object value) | ||
{ | ||
if (value is Style winUIStyle) | ||
{ | ||
// This needs to be nested to prevent further processing if we cannot generate a Maui Style | ||
if(Interop.MauiInterop.TryGetStyle(winUIStyle, out var style) && style != null) | ||
{ | ||
var key = sourceKey is string str ? str : style.TargetType.FullName; | ||
resources[key] = style; | ||
} | ||
} | ||
else if (sourceKey is string key && !string.IsNullOrEmpty(key) && !resources.ContainsKey(key)) | ||
{ | ||
var mauiValue = ConversionHelpers.ToMauiValue(value); | ||
resources[key] = mauiValue ?? value; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using System.Globalization; | ||
using Microsoft.UI.Xaml.Media; | ||
using LayoutOptions = Microsoft.Maui.Controls.LayoutOptions; | ||
using Thickness = Microsoft.UI.Xaml.Thickness; | ||
|
||
namespace Uno.Extensions.Maui.Internals; | ||
|
||
internal static class ConversionHelpers | ||
{ | ||
internal static object? ToMauiValue(object input) | ||
{ | ||
return input switch | ||
{ | ||
int valueAsInt => valueAsInt, | ||
double valueAsDouble => valueAsDouble, | ||
float valueAsFloat => valueAsFloat, | ||
WinUIConverter converter => new UnoHostConverter(converter), | ||
SolidColorBrush solidColorBrush => new Microsoft.Maui.Controls.SolidColorBrush(new NativeMauiColor(solidColorBrush.Color.R, solidColorBrush.Color.G, solidColorBrush.Color.B, solidColorBrush.Color.A)), | ||
WinUIColor color => new NativeMauiColor(color.R, color.G, color.B, color.A), | ||
Thickness thickness => new Microsoft.Maui.Thickness(thickness.Left, thickness.Top, thickness.Right, thickness.Bottom), | ||
HorizontalAlignment horizontalAlignment => GetLayoutOptions(horizontalAlignment), | ||
VerticalAlignment verticalAlignment => GetLayoutOptions(verticalAlignment), | ||
_ => null | ||
}; | ||
} | ||
|
||
private static LayoutOptions GetLayoutOptions(HorizontalAlignment alignment) => | ||
alignment switch | ||
{ | ||
HorizontalAlignment.Center => LayoutOptions.Center, | ||
HorizontalAlignment.Right => LayoutOptions.End, | ||
HorizontalAlignment.Left => LayoutOptions.Start, | ||
_ => LayoutOptions.Fill | ||
}; | ||
|
||
private static LayoutOptions GetLayoutOptions(VerticalAlignment alignment) => | ||
alignment switch | ||
{ | ||
VerticalAlignment.Center => LayoutOptions.Center, | ||
VerticalAlignment.Bottom => LayoutOptions.End, | ||
VerticalAlignment.Top => LayoutOptions.Start, | ||
_ => LayoutOptions.Fill | ||
}; | ||
|
||
private class UnoHostConverter : MauiConverter | ||
{ | ||
private WinUIConverter _converter { get; } | ||
|
||
public UnoHostConverter(WinUIConverter converter) => _converter = converter; | ||
|
||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => | ||
_converter.Convert(value, targetType, parameter, culture.Name); | ||
|
||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => | ||
_converter.ConvertBack(value, targetType, parameter, culture.Name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Uno.Extensions.Maui.Internals; | ||
|
||
internal class UnoHost : Microsoft.Maui.Controls.VisualElement | ||
{ | ||
public UnoHost(ResourceDictionary resources) | ||
{ | ||
Resources = resources.ToMauiResources(); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
src/Uno.Extensions.Maui/Internals/UnoMauiEmbeddingInitializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using Microsoft.Maui.Hosting; | ||
|
||
namespace Uno.Extensions.Maui.Internals; | ||
|
||
internal class UnoMauiEmbeddingInitializer : IMauiInitializeService | ||
{ | ||
private readonly Application _app; | ||
|
||
public UnoMauiEmbeddingInitializer(Application app) | ||
{ | ||
_app = app; | ||
} | ||
|
||
public void Initialize(IServiceProvider services) | ||
{ | ||
var resources = _app.Resources.ToMauiResources(); | ||
var iApp = services.GetRequiredService<global::Microsoft.Maui.IApplication>(); | ||
if (HasResources(resources) && iApp is MauiApplication mauiApp) | ||
{ | ||
mauiApp.Resources.MergedDictionaries.Add(resources); | ||
} | ||
} | ||
|
||
private static bool HasResources(MauiResourceDictionary resources) | ||
{ | ||
if (resources.Keys.Any()) | ||
{ | ||
return true; | ||
} | ||
else if (resources.MergedDictionaries is not null && resources.MergedDictionaries.Any()) | ||
{ | ||
for (var i = 0; i < resources.MergedDictionaries.Count; i++) | ||
{ | ||
if (HasResources(resources.MergedDictionaries.ElementAt(i))) | ||
{ | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Uno.Extensions.Maui.Interop; | ||
|
||
public interface IWinUIToMauiStyleHandler | ||
{ | ||
Type TargetType { get; } | ||
|
||
(Microsoft.Maui.Controls.BindableProperty Property, object? Value)? Process(DependencyProperty property, object value); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
namespace Uno.Extensions.Maui.Interop; | ||
|
||
internal class LabelStyleHandler : WinUIToMauiStyleHandler | ||
{ | ||
public override Type TargetType => typeof(Microsoft.Maui.Controls.Label); | ||
|
||
public override (Microsoft.Maui.Controls.BindableProperty Property, object? Value)? Process(DependencyProperty property, object value) | ||
{ | ||
if (property == Control.ForegroundProperty && TryConvertValue(value, out var converted) && converted is Microsoft.Maui.Controls.SolidColorBrush brush) | ||
{ | ||
return (Microsoft.Maui.Controls.Label.TextColorProperty, brush.Color); | ||
} | ||
else if (property == TextBlock.FontSizeProperty) | ||
{ | ||
return (Microsoft.Maui.Controls.Label.FontSizeProperty, ConvertToMauiValue(value)); | ||
} | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace Uno.Extensions.Maui.Interop; | ||
|
||
internal class LayoutStyleHandler : WinUIToMauiStyleHandler | ||
{ | ||
public override Type TargetType => typeof(Microsoft.Maui.Controls.Layout); | ||
|
||
public override (Microsoft.Maui.Controls.BindableProperty Property, object? Value)? Process(DependencyProperty property, object value) | ||
{ | ||
return property == Control.PaddingProperty | ||
? (Microsoft.Maui.Controls.Layout.PaddingProperty, ConvertToMauiValue(value)) | ||
: null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
namespace Uno.Extensions.Maui.Interop; | ||
|
||
internal static class MauiInterop | ||
{ | ||
private static readonly List<ControlMapping> _mappings = new(); | ||
private static readonly List<IWinUIToMauiStyleHandler> _styleHandlers = new(); | ||
|
||
static MauiInterop() | ||
{ | ||
MapControl<TextBlock, Microsoft.Maui.Controls.Label>(); | ||
MapControl<TextBox, Microsoft.Maui.Controls.Entry>(); | ||
MapControl<Grid, Microsoft.Maui.Controls.Grid>(); | ||
MapControl<StackPanel, Microsoft.Maui.Controls.StackLayout>(); | ||
|
||
MapStyleHandler<LabelStyleHandler>(); | ||
MapStyleHandler<VisualElementStyleHandler>(); | ||
MapStyleHandler<ViewStyleHandler>(); | ||
MapStyleHandler<LayoutStyleHandler>(); | ||
} | ||
|
||
public static void MapControl<TWinUI, TMaui>() | ||
where TWinUI : FrameworkElement | ||
where TMaui : Microsoft.Maui.Controls.View => | ||
_mappings.Add(new(typeof(TWinUI), typeof(TMaui))); | ||
|
||
public static void MapStyleHandler<THandler>() | ||
where THandler : IWinUIToMauiStyleHandler, new() => | ||
_styleHandlers.Add(new THandler()); | ||
|
||
public static bool TryGetMapping(Type winUI, out Type? maui) | ||
{ | ||
maui = _mappings.FirstOrDefault(x => x.WinUI == winUI)?.Maui; | ||
return maui is not null; | ||
} | ||
|
||
public static bool TryGetStyle(Style winUIStyle, out Microsoft.Maui.Controls.Style? style) | ||
{ | ||
style = null; | ||
|
||
if (winUIStyle.TargetType is null | ||
|| !TryGetMapping(winUIStyle.TargetType, out var targetType) | ||
|| targetType is null | ||
|| (!winUIStyle.Setters.Any() && winUIStyle.BasedOn is null)) | ||
{ | ||
return false; | ||
} | ||
|
||
var tempStyle = new Microsoft.Maui.Controls.Style(targetType); | ||
foreach(var setter in winUIStyle.Setters.OfType<Setter>()) | ||
{ | ||
if (setter.Property is null || setter.Value is null) | ||
{ | ||
continue; | ||
} | ||
|
||
var handlers = GetHandlers(targetType); | ||
|
||
handlers.ForEach(handler => | ||
{ | ||
var processed = handler.Process(setter.Property, setter.Value); | ||
if (processed is null) | ||
{ | ||
return; | ||
} | ||
|
||
tempStyle.Setters.Add(new Microsoft.Maui.Controls.Setter { Property = processed.Value.Property, Value = processed.Value.Value }); | ||
}); | ||
} | ||
|
||
style = tempStyle; | ||
|
||
return style.Setters.Any() || style.BasedOn is not null; | ||
} | ||
|
||
private static List<IWinUIToMauiStyleHandler> GetHandlers(Type targetType) => | ||
_styleHandlers.Where(x => x.TargetType == targetType | ||
|| x.TargetType.IsAssignableFrom(targetType)).ToList(); | ||
|
||
private record ControlMapping(Type WinUI, Type Maui); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace Uno.Extensions.Maui.Interop; | ||
|
||
internal class ViewStyleHandler : WinUIToMauiStyleHandler | ||
{ | ||
public override Type TargetType => typeof(Microsoft.Maui.Controls.View); | ||
|
||
public override (Microsoft.Maui.Controls.BindableProperty Property, object? Value)? Process(DependencyProperty property, object value) | ||
{ | ||
return property == Control.MarginProperty | ||
? (Microsoft.Maui.Controls.View.MarginProperty, ConvertToMauiValue(value)) | ||
: null; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/Uno.Extensions.Maui/Interop/VisualElementStyleHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace Uno.Extensions.Maui.Interop; | ||
|
||
internal class VisualElementStyleHandler : WinUIToMauiStyleHandler | ||
{ | ||
public override Type TargetType => typeof(Microsoft.Maui.Controls.VisualElement); | ||
|
||
public override (Microsoft.Maui.Controls.BindableProperty Property, object? Value)? Process(DependencyProperty property, object value) | ||
{ | ||
return property == Control.BackgroundProperty | ||
? (Microsoft.Maui.Controls.VisualElement.BackgroundProperty, ConvertToMauiValue(value)) | ||
: null; | ||
} | ||
} |
Oops, something went wrong.