diff --git a/src/Compatibility/Core/src/Tizen/Forms.cs b/src/Compatibility/Core/src/Tizen/Forms.cs index 995ef054faf6..440a8a3edde7 100644 --- a/src/Compatibility/Core/src/Tizen/Forms.cs +++ b/src/Compatibility/Core/src/Tizen/Forms.cs @@ -484,6 +484,9 @@ static void SetupInit(IMauiContext context, InitializationOptions options = null Device.Info = new Forms.TizenDeviceInfo(); Device.SetFlags(s_flags); + if (options?.Flags.HasFlag(InitializationFlags.SkipRenderers) != true) + RegisterCompatRenderers(options); + string profile = ((TizenDeviceInfo)Device.Info).Profile; if (profile == "mobile") { @@ -523,6 +526,50 @@ static void SetupInit(IMauiContext context, InitializationOptions options = null IsInitialized = true; } + internal static void RegisterCompatRenderers(InitializationOptions maybeOptions = null) + { + if (!IsInitializedRenderers) + { + IsInitializedRenderers = true; + if (maybeOptions != null) + { + var options = maybeOptions; + var handlers = options.Handlers; + var flags = options.Flags; + var effectScopes = options.EffectScopes; + + //TODO: ExportCell? + //TODO: ExportFont + + // renderers + Registrar.RegisterRenderers(handlers); + + // effects + if (effectScopes != null) + { + for (var i = 0; i < effectScopes.Length; i++) + { + var effectScope = effectScopes[0]; + Registrar.RegisterEffects(effectScope.Name, effectScope.Effects); + } + } + + // css + Registrar.RegisterStylesheets(flags); + } + else + { + // Only need to do this once + Registrar.RegisterAll(new[] { + typeof(ExportRendererAttribute), + typeof(ExportCellAttribute), + typeof(ExportImageSourceHandlerAttribute), + typeof(ExportFontAttribute) + }); + } + } + } + static void RegisterSkiaSharpRenderers() { // Register all skiasharp-based rednerers here. diff --git a/src/Compatibility/Core/src/Tizen/HandlerToRendererShim.cs b/src/Compatibility/Core/src/Tizen/HandlerToRendererShim.cs index ee12b4dbfad4..06785c6b6b6b 100644 --- a/src/Compatibility/Core/src/Tizen/HandlerToRendererShim.cs +++ b/src/Compatibility/Core/src/Tizen/HandlerToRendererShim.cs @@ -123,13 +123,14 @@ public MockParentHandler(VisualElement parent) public IMauiContext MauiContext => null; - object IViewHandler.NativeView => NativeView; + object IElementHandler.NativeView => NativeView; object IViewHandler.ContainerView => NativeView; - bool HasContainer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } bool IViewHandler.HasContainer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + Maui.IElement IElementHandler.VirtualView => throw new NotImplementedException(); + public void DisconnectHandler() { } public void Dispose() @@ -170,6 +171,11 @@ public void UpdateValue(string property) { throw new NotImplementedException(); } + + public void SetVirtualView(Maui.IElement view) + { + throw new NotImplementedException(); + } } } diff --git a/src/Compatibility/Core/src/Tizen/Platform.cs b/src/Compatibility/Core/src/Tizen/Platform.cs index d37f84de8498..f48c1d1c6d73 100644 --- a/src/Compatibility/Core/src/Tizen/Platform.cs +++ b/src/Compatibility/Core/src/Tizen/Platform.cs @@ -53,7 +53,7 @@ internal static IVisualElementRenderer CreateRenderer(VisualElement element) //TODO: Handle this with AppBuilderHost try { - handler = Forms.MauiContext.Handlers.GetHandler(element.GetType()); + handler = Forms.MauiContext.Handlers.GetHandler(element.GetType()) as IViewHandler; handler.SetMauiContext(Forms.MauiContext); } catch diff --git a/src/Controls/src/Core/HandlerImpl/Window.Tizen.cs b/src/Controls/src/Core/HandlerImpl/Window.Tizen.cs new file mode 100644 index 000000000000..12dcf19a25ea --- /dev/null +++ b/src/Controls/src/Core/HandlerImpl/Window.Tizen.cs @@ -0,0 +1,12 @@ +#nullable enable +using System; +using EWindow = ElmSharp.Window; + +namespace Microsoft.Maui.Controls +{ + public partial class Window + { + internal EWindow NativeWindow => + (Handler?.NativeView as EWindow) ?? throw new InvalidOperationException("Window should have a ElmSharp.Window set."); + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Platform/AlertManager/AlertManager.Tizen.cs b/src/Controls/src/Core/Platform/AlertManager/AlertManager.Tizen.cs new file mode 100644 index 000000000000..ecaa6da7cd91 --- /dev/null +++ b/src/Controls/src/Core/Platform/AlertManager/AlertManager.Tizen.cs @@ -0,0 +1,19 @@ +using System; + +namespace Microsoft.Maui.Controls.Platform +{ + internal partial class AlertManager + { + internal static void Subscribe(Window window) + { + //TODO: Need to implementation + //throw new NotImplementedException(); + } + + internal static void Unsubscribe(Window window) + { + //TODO: Need to implementation + //throw new NotImplementedException(); + } + } +} diff --git a/src/Controls/src/Core/Platform/ModalNavigationService/ModalNavigationService.Tizen.cs b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Tizen.cs similarity index 96% rename from src/Controls/src/Core/Platform/ModalNavigationService/ModalNavigationService.Tizen.cs rename to src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Tizen.cs index c02e54e0f0ea..48522ffb46ac 100644 --- a/src/Controls/src/Core/Platform/ModalNavigationService/ModalNavigationService.Tizen.cs +++ b/src/Controls/src/Core/Platform/ModalNavigationManager/ModalNavigationManager.Tizen.cs @@ -4,7 +4,7 @@ namespace Microsoft.Maui.Controls.Platform { - internal partial class ModalNavigationService + internal partial class ModalNavigationManager { ModalStack _modalStack => MauiContext.Context!.ModalStack; IPageController CurrentPageController => _navModel.CurrentPage; diff --git a/src/Core/src/Handlers/Label/LabelHandler.Tizen.cs b/src/Core/src/Handlers/Label/LabelHandler.Tizen.cs index 42ac959432c2..c38bfa605f15 100644 --- a/src/Core/src/Handlers/Label/LabelHandler.Tizen.cs +++ b/src/Core/src/Handlers/Label/LabelHandler.Tizen.cs @@ -24,6 +24,11 @@ public static void MapHorizontalTextAlignment(LabelHandler handler, ILabel label handler.NativeView?.UpdateHorizontalTextAlignment(label); } + public static void MapVerticalTextAlignment(LabelHandler handler, ILabel label) + { + handler.NativeView?.UpdateVerticalTextAlignment(label); + } + public static void MapLineBreakMode(LabelHandler handler, ILabel label) { handler.NativeView?.UpdateLineBreakMode(label); diff --git a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Tizen.cs b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Tizen.cs index 36df0ff3e91d..096339459cc7 100644 --- a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Tizen.cs +++ b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Tizen.cs @@ -15,7 +15,7 @@ protected override EProgressBar CreateNativeView() return progressBar; } - protected override void SetupDefaults(EProgressBar nativeView) + void SetupDefaults(EProgressBar nativeView) { nativeView.Color = ThemeConstants.ProgressBar.ColorClass.Default; } diff --git a/src/Core/src/Handlers/Slider/SliderHandler.Tizen.cs b/src/Core/src/Handlers/Slider/SliderHandler.Tizen.cs index 884755f80a50..0f1ffe36c673 100644 --- a/src/Core/src/Handlers/Slider/SliderHandler.Tizen.cs +++ b/src/Core/src/Handlers/Slider/SliderHandler.Tizen.cs @@ -27,7 +27,7 @@ protected override void DisconnectHandler(ESlider nativeView) nativeView!.DragStopped -= OnDragStopped; } - protected override void SetupDefaults(ESlider nativeView) + void SetupDefaults(ESlider nativeView) { DefaultMinTrackColor = nativeView.GetBarColor(); DefaultMaxTrackColor = nativeView.GetBackgroundColor(); diff --git a/src/Core/src/Handlers/View/ViewHandlerOfT.Tizen.cs b/src/Core/src/Handlers/View/ViewHandlerOfT.Tizen.cs index 60d1b47b272c..c4d8c14915e9 100644 --- a/src/Core/src/Handlers/View/ViewHandlerOfT.Tizen.cs +++ b/src/Core/src/Handlers/View/ViewHandlerOfT.Tizen.cs @@ -193,10 +193,10 @@ protected virtual void Dispose(bool disposing) if (disposing) { // Dispose managed state (managed objects) - if (WrappedNativeView != null) + if (WrappedNativeView is TNativeView wrapped) { - DisconnectHandler(WrappedNativeView); - WrappedNativeView.Unrealize(); + DisconnectHandler(wrapped); + wrapped.Unrealize(); } } diff --git a/src/Core/src/Handlers/Window/WindowHandler.Tizen.cs b/src/Core/src/Handlers/Window/WindowHandler.Tizen.cs new file mode 100644 index 000000000000..04849ed0b73b --- /dev/null +++ b/src/Core/src/Handlers/Window/WindowHandler.Tizen.cs @@ -0,0 +1,19 @@ +using System; +using ElmSharp; + +namespace Microsoft.Maui.Handlers +{ + public partial class WindowHandler : ElementHandler + { + public static void MapTitle(WindowHandler handler, IWindow window) { } + + public static void MapContent(WindowHandler handler, IWindow window) + { + _ = handler.MauiContext ?? throw new InvalidOperationException($"{nameof(MauiContext)} should have been set by base class."); + _ = handler.MauiContext.Context ?? throw new InvalidOperationException($"{nameof(CoreUIAppContext)} should have been set by base class."); + + var nativeContent = window.Content.ToNative(handler.MauiContext); + handler.MauiContext.Context.SetContent(nativeContent); + } + } +} \ No newline at end of file diff --git a/src/Core/src/Handlers/Window/WindowHandler.cs b/src/Core/src/Handlers/Window/WindowHandler.cs index 68bc5149b83e..a713f8d21915 100644 --- a/src/Core/src/Handlers/Window/WindowHandler.cs +++ b/src/Core/src/Handlers/Window/WindowHandler.cs @@ -5,6 +5,8 @@ using NativeView = Android.App.Activity; #elif WINDOWS using NativeView = Microsoft.UI.Xaml.Window; +#elif TIZEN +using NativeView = ElmSharp.Window; #endif namespace Microsoft.Maui.Handlers diff --git a/src/Core/src/LifecycleEvents/Tizen/TizenLifecycle.cs b/src/Core/src/LifecycleEvents/Tizen/TizenLifecycle.cs index af6b26c745b6..f6425b73f96e 100644 --- a/src/Core/src/LifecycleEvents/Tizen/TizenLifecycle.cs +++ b/src/Core/src/LifecycleEvents/Tizen/TizenLifecycle.cs @@ -19,5 +19,7 @@ public static class TizenLifecycle public delegate void OnRegionFormatChanged(CoreUIApplication application, RegionFormatChangedEventArgs e); public delegate void OnTerminate(CoreUIApplication application); + // Internal events + internal delegate void OnMauiContextCreated(IMauiContext mauiContext); } } \ No newline at end of file diff --git a/src/Core/src/LifecycleEvents/Tizen/TizenLifecycleBuilderExtensions.cs b/src/Core/src/LifecycleEvents/Tizen/TizenLifecycleBuilderExtensions.cs index 1b5322c5aa68..c1b5de9a15f5 100644 --- a/src/Core/src/LifecycleEvents/Tizen/TizenLifecycleBuilderExtensions.cs +++ b/src/Core/src/LifecycleEvents/Tizen/TizenLifecycleBuilderExtensions.cs @@ -13,5 +13,7 @@ public static class TizenLifecycleBuilderExtensions public static ITizenLifecycleBuilder OnLowMemory(this ITizenLifecycleBuilder lifecycle, TizenLifecycle.OnLowMemory del) => lifecycle.OnEvent(del); public static ITizenLifecycleBuilder OnRegionFormatChanged(this ITizenLifecycleBuilder lifecycle, TizenLifecycle.OnRegionFormatChanged del) => lifecycle.OnEvent(del); public static ITizenLifecycleBuilder OnTerminate(this ITizenLifecycleBuilder lifecycle, TizenLifecycle.OnTerminate del) => lifecycle.OnEvent(del); + + internal static ITizenLifecycleBuilder OnMauiContextCreated(this ITizenLifecycleBuilder lifecycle, TizenLifecycle.OnMauiContextCreated del) => lifecycle.OnEvent(del); } } \ No newline at end of file diff --git a/src/Core/src/Platform/IMauiContext.cs b/src/Core/src/Platform/IMauiContext.cs index 2ef39ace4335..3bbc9b456305 100644 --- a/src/Core/src/Platform/IMauiContext.cs +++ b/src/Core/src/Platform/IMauiContext.cs @@ -17,6 +17,7 @@ public interface IMauiContext UI.Xaml.Window? Window { get; } #elif TIZEN CoreUIAppContext? Context { get; } + ElmSharp.Window? Window { get; } #endif } diff --git a/src/Core/src/Platform/MauiContext.Tizen.cs b/src/Core/src/Platform/MauiContext.Tizen.cs index 3a0b26c4b7cc..231f6a27583f 100644 --- a/src/Core/src/Platform/MauiContext.Tizen.cs +++ b/src/Core/src/Platform/MauiContext.Tizen.cs @@ -1,4 +1,5 @@ using System; +using ElmSharp; namespace Microsoft.Maui { @@ -33,5 +34,6 @@ public MauiContext(IServiceProvider services, CoreUIAppContext context) : this(s } } + public Window? Window => Context?.MainWindow; } } \ No newline at end of file diff --git a/src/Core/src/Platform/Tizen/CoreUIAppContext.cs b/src/Core/src/Platform/Tizen/CoreUIAppContext.cs index f0ef2e8b0d26..f6eca62286bf 100644 --- a/src/Core/src/Platform/Tizen/CoreUIAppContext.cs +++ b/src/Core/src/Platform/Tizen/CoreUIAppContext.cs @@ -25,7 +25,6 @@ public static CoreUIAppContext GetInstance(CoreApplication application, Window? if (IsInitialized) return _instance!; - _instance = (window == null) ? new CoreUIAppContext(application) : new CoreUIAppContext(application, window); return _instance; } diff --git a/src/Core/src/Platform/Tizen/HandlerExtensions.cs b/src/Core/src/Platform/Tizen/HandlerExtensions.cs index e55243bcb187..f69811a80726 100644 --- a/src/Core/src/Platform/Tizen/HandlerExtensions.cs +++ b/src/Core/src/Platform/Tizen/HandlerExtensions.cs @@ -1,4 +1,5 @@ using System; +using Tizen.Applications; using ElmSharp; namespace Microsoft.Maui @@ -15,34 +16,47 @@ public static EvasObject ToNative(this IView view, IMauiContext context) view = ir.ReplacedView; var handler = view.Handler; - - if (handler?.MauiContext != null && - handler.MauiContext != context) - { + if (handler?.MauiContext != null && handler.MauiContext != context) handler = null; - } if (handler == null) - { - handler = context.Handlers.GetHandler(view.GetType()); + handler = context.Handlers.GetHandler(view.GetType()) as IViewHandler; + + if (handler == null) + throw new Exception($"Handler not found for view {view} or was not {nameof(IViewHandler)}."); - if (handler == null) - throw new Exception($"Handler not found for view {view}"); + handler.SetMauiContext(context); - handler.SetMauiContext(context); - view.Handler = handler; - } + view.Handler = handler; if (handler.VirtualView != view) handler.SetVirtualView(view); - if (((INativeViewHandler)handler).NativeView is not EvasObject result) - { throw new InvalidOperationException($"Unable to convert {view} to {typeof(EvasObject)}"); - } return result; } + + public static void SetWindow(this Window nativeWindow, IWindow window, IMauiContext mauiContext) + { + _ = nativeWindow ?? throw new ArgumentNullException(nameof(nativeWindow)); + _ = window ?? throw new ArgumentNullException(nameof(window)); + _ = mauiContext ?? throw new ArgumentNullException(nameof(mauiContext)); + + var handler = window.Handler as IWindowHandler; + if (handler == null) + handler = mauiContext.Handlers.GetHandler(window.GetType()) as IWindowHandler; + + if (handler == null) + throw new Exception($"Handler not found for view {window} or was not {nameof(IWindowHandler)}'"); + + handler.SetMauiContext(mauiContext); + + window.Handler = handler; + + if (handler.VirtualView != window) + handler.SetVirtualView(window); + } } } \ No newline at end of file diff --git a/src/Core/src/Platform/Tizen/LabelExtensions.cs b/src/Core/src/Platform/Tizen/LabelExtensions.cs index 8ce235c76a98..7a8825c05e52 100644 --- a/src/Core/src/Platform/Tizen/LabelExtensions.cs +++ b/src/Core/src/Platform/Tizen/LabelExtensions.cs @@ -31,6 +31,11 @@ public static void UpdateHorizontalTextAlignment(this Label nativeLabel, ILabel nativeLabel.HorizontalTextAlignment = label.HorizontalTextAlignment.ToNative(); } + public static void UpdateVerticalTextAlignment(this Label nativeLabel, ILabel label) + { + nativeLabel.VerticalTextAlignment = label.VerticalTextAlignment.ToNative(); + } + public static void UpdateLineBreakMode(this Label nativeLabel, ILabel label) { nativeLabel.LineBreakMode = label.LineBreakMode.ToNative(); diff --git a/src/Core/src/Platform/Tizen/MauiApplication.cs b/src/Core/src/Platform/Tizen/MauiApplication.cs index 874435ecd8f0..7cddf5f68485 100644 --- a/src/Core/src/Platform/Tizen/MauiApplication.cs +++ b/src/Core/src/Platform/Tizen/MauiApplication.cs @@ -1,5 +1,6 @@ using System; using Tizen.Applications; +using ElmSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Maui.Hosting; @@ -39,28 +40,30 @@ protected override void OnCreate() if (Application == null) throw new InvalidOperationException($"The {nameof(IApplication)} instance was not found."); - MauiContext mauiContext; - IWindow window; + MainWindow = CreateNativeWindow(); + MainWindow.Show(); + Current.Services?.InvokeLifecycleEvents(del => del(this)); + } + + Window CreateNativeWindow() + { var context = CoreUIAppContext.GetInstance(this); + var mauiContext = new MauiContext(Services, context); - // TODO Fix once we have multiple windows - if (Application.Windows.Count > 0) - { - window = Application.Windows[0]; - mauiContext = new MauiContext(Services, context); - } - else - { - mauiContext = new MauiContext(Services, context); - ActivationState state = new ActivationState(mauiContext); - window = Application.CreateWindow(state); - } - - var page = window.View; - context.SetContent(page.ToNative(mauiContext)); + Services.InvokeLifecycleEvents(del => del(mauiContext)); - Current.Services?.InvokeLifecycleEvents(del => del(this)); + var tizenWindow = mauiContext.Window; + + if (tizenWindow == null) + throw new InvalidOperationException($"The {nameof(tizenWindow)} instance was not found."); + + var activationState = new ActivationState(mauiContext); + var window = Application.CreateWindow(activationState); + + tizenWindow.SetWindow(window, mauiContext); + + return tizenWindow; } protected override void OnAppControlReceived(AppControlReceivedEventArgs e) @@ -133,6 +136,8 @@ protected MauiApplication() public static new MauiApplication Current { get; private set; } = null!; + public Window MainWindow { get; protected set; } = null!; + public IServiceProvider Services { get; protected set; } = null!; public IApplication Application { get; protected set; } = null!; diff --git a/src/Core/src/Platform/Tizen/ViewExtensions.cs b/src/Core/src/Platform/Tizen/ViewExtensions.cs index 50e50d9b34c9..8e991e7d0e91 100644 --- a/src/Core/src/Platform/Tizen/ViewExtensions.cs +++ b/src/Core/src/Platform/Tizen/ViewExtensions.cs @@ -60,9 +60,10 @@ public static void UpdateOpacity(this EvasObject nativeView, IView view) } } - public static void UpdateClip(this WrapperView nativeView, IView view) + public static void UpdateClip(this EvasObject nativeView, IView view) { - nativeView.Clip = view.Clip; + if (nativeView is WrapperView wrapper) + wrapper.Clip = view.Clip; } public static void UpdateAutomationId(this EvasObject nativeView, IView view)