Update with recovered code from VM binaries (Jan 1)

Recovered from decompiled OpenMaui.Controls.Linux.dll:
- SkiaShell.cs: FlyoutHeader, FlyoutFooter, scroll support (918 -> 1325 lines)
- X11Window.cs: Cursor support (XCreateFontCursor, XDefineCursor)
- All handlers with dark mode support
- All services with latest implementations
- LinuxApplication with theme change handling
This commit is contained in:
2026-01-01 06:22:48 -05:00
parent 1e84c6168a
commit 1f096c38dc
254 changed files with 49359 additions and 38457 deletions

View File

@@ -1,64 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for ActivityIndicator on Linux using Skia rendering.
/// Maps IActivityIndicator interface to SkiaActivityIndicator platform view.
/// </summary>
public partial class ActivityIndicatorHandler : ViewHandler<IActivityIndicator, SkiaActivityIndicator>
public class ActivityIndicatorHandler : ViewHandler<IActivityIndicator, SkiaActivityIndicator>
{
public static IPropertyMapper<IActivityIndicator, ActivityIndicatorHandler> Mapper = new PropertyMapper<IActivityIndicator, ActivityIndicatorHandler>(ViewHandler.ViewMapper)
{
[nameof(IActivityIndicator.IsRunning)] = MapIsRunning,
[nameof(IActivityIndicator.Color)] = MapColor,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<IActivityIndicator, ActivityIndicatorHandler> Mapper = (IPropertyMapper<IActivityIndicator, ActivityIndicatorHandler>)(object)new PropertyMapper<IActivityIndicator, ActivityIndicatorHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsRunning"] = MapIsRunning,
["Color"] = MapColor,
["Background"] = MapBackground
};
public static CommandMapper<IActivityIndicator, ActivityIndicatorHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IActivityIndicator, ActivityIndicatorHandler> CommandMapper = new CommandMapper<IActivityIndicator, ActivityIndicatorHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public ActivityIndicatorHandler() : base(Mapper, CommandMapper)
{
}
public ActivityIndicatorHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ActivityIndicatorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public ActivityIndicatorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaActivityIndicator CreatePlatformView()
{
return new SkiaActivityIndicator();
}
protected override SkiaActivityIndicator CreatePlatformView()
{
return new SkiaActivityIndicator();
}
public static void MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsRunning = activityIndicator.IsRunning;
}
public static void MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
if (((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView != null)
{
((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView.IsRunning = activityIndicator.IsRunning;
}
}
public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
if (handler.PlatformView is null) return;
public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView != null && activityIndicator.Color != null)
{
((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView.Color = activityIndicator.Color.ToSKColor();
}
}
if (activityIndicator.Color is not null)
handler.PlatformView.Color = activityIndicator.Color.ToSKColor();
}
public static void MapBackground(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
if (handler.PlatformView is null) return;
if (activityIndicator.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackground(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView != null)
{
Paint background = ((IView)activityIndicator).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
}

View File

@@ -1,137 +1,59 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform.Linux.Hosting;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for MAUI Application on Linux.
/// Bridges the MAUI Application lifecycle with LinuxApplication.
/// </summary>
public partial class ApplicationHandler : ElementHandler<IApplication, LinuxApplicationContext>
public class ApplicationHandler : ElementHandler<IApplication, LinuxApplicationContext>
{
public static IPropertyMapper<IApplication, ApplicationHandler> Mapper =
new PropertyMapper<IApplication, ApplicationHandler>(ElementHandler.ElementMapper)
{
};
public static IPropertyMapper<IApplication, ApplicationHandler> Mapper = (IPropertyMapper<IApplication, ApplicationHandler>)(object)new PropertyMapper<IApplication, ApplicationHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ElementHandler.ElementMapper });
public static CommandMapper<IApplication, ApplicationHandler> CommandMapper =
new(ElementHandler.ElementCommandMapper)
{
[nameof(IApplication.OpenWindow)] = MapOpenWindow,
[nameof(IApplication.CloseWindow)] = MapCloseWindow,
};
public static CommandMapper<IApplication, ApplicationHandler> CommandMapper = new CommandMapper<IApplication, ApplicationHandler>((CommandMapper)(object)ElementHandler.ElementCommandMapper)
{
["OpenWindow"] = MapOpenWindow,
["CloseWindow"] = MapCloseWindow
};
public ApplicationHandler() : base(Mapper, CommandMapper)
{
}
public ApplicationHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ApplicationHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public ApplicationHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override LinuxApplicationContext CreatePlatformElement()
{
return new LinuxApplicationContext();
}
protected override LinuxApplicationContext CreatePlatformElement()
{
return new LinuxApplicationContext();
}
protected override void ConnectHandler(LinuxApplicationContext platformView)
{
base.ConnectHandler(platformView);
platformView.Application = VirtualView;
}
protected override void ConnectHandler(LinuxApplicationContext platformView)
{
base.ConnectHandler(platformView);
platformView.Application = base.VirtualView;
}
protected override void DisconnectHandler(LinuxApplicationContext platformView)
{
platformView.Application = null;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(LinuxApplicationContext platformView)
{
platformView.Application = null;
base.DisconnectHandler(platformView);
}
public static void MapOpenWindow(ApplicationHandler handler, IApplication application, object? args)
{
if (args is IWindow window)
{
handler.PlatformView?.OpenWindow(window);
}
}
public static void MapOpenWindow(ApplicationHandler handler, IApplication application, object? args)
{
IWindow val = (IWindow)((args is IWindow) ? args : null);
if (val != null)
{
((ElementHandler<IApplication, LinuxApplicationContext>)(object)handler).PlatformView?.OpenWindow(val);
}
}
public static void MapCloseWindow(ApplicationHandler handler, IApplication application, object? args)
{
if (args is IWindow window)
{
handler.PlatformView?.CloseWindow(window);
}
}
}
/// <summary>
/// Platform context for the MAUI Application on Linux.
/// Manages windows and the application lifecycle.
/// </summary>
public class LinuxApplicationContext
{
private readonly List<IWindow> _windows = new();
private IApplication? _application;
/// <summary>
/// Gets or sets the MAUI Application.
/// </summary>
public IApplication? Application
{
get => _application;
set
{
_application = value;
if (_application != null)
{
// Initialize windows from the application
foreach (var window in _application.Windows)
{
if (!_windows.Contains(window))
{
_windows.Add(window);
}
}
}
}
}
/// <summary>
/// Gets the list of open windows.
/// </summary>
public IReadOnlyList<IWindow> Windows => _windows;
/// <summary>
/// Opens a window and creates its handler.
/// </summary>
public void OpenWindow(IWindow window)
{
if (!_windows.Contains(window))
{
_windows.Add(window);
}
}
/// <summary>
/// Closes a window and cleans up its handler.
/// </summary>
public void CloseWindow(IWindow window)
{
_windows.Remove(window);
if (_windows.Count == 0)
{
// Last window closed, stop the application
LinuxApplication.Current?.MainWindow?.Stop();
}
}
/// <summary>
/// Gets the main window of the application.
/// </summary>
public IWindow? MainWindow => _windows.Count > 0 ? _windows[0] : null;
public static void MapCloseWindow(ApplicationHandler handler, IApplication application, object? args)
{
IWindow val = (IWindow)((args is IWindow) ? args : null);
if (val != null)
{
((ElementHandler<IApplication, LinuxApplicationContext>)(object)handler).PlatformView?.CloseWindow(val);
}
}
}

View File

@@ -1,158 +1,186 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using Microsoft.Maui.Controls.Shapes;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Border on Linux using Skia rendering.
/// </summary>
public partial class BorderHandler : ViewHandler<IBorderView, SkiaBorder>
public class BorderHandler : ViewHandler<IBorderView, SkiaBorder>
{
public static IPropertyMapper<IBorderView, BorderHandler> Mapper =
new PropertyMapper<IBorderView, BorderHandler>(ViewHandler.ViewMapper)
{
[nameof(IBorderView.Content)] = MapContent,
[nameof(IBorderStroke.Stroke)] = MapStroke,
[nameof(IBorderStroke.StrokeThickness)] = MapStrokeThickness,
["StrokeShape"] = MapStrokeShape, // StrokeShape is on Border, not IBorderStroke
[nameof(IView.Background)] = MapBackground,
["BackgroundColor"] = MapBackgroundColor,
[nameof(IPadding.Padding)] = MapPadding,
};
public static IPropertyMapper<IBorderView, BorderHandler> Mapper = (IPropertyMapper<IBorderView, BorderHandler>)(object)new PropertyMapper<IBorderView, BorderHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Content"] = MapContent,
["Stroke"] = MapStroke,
["StrokeThickness"] = MapStrokeThickness,
["StrokeShape"] = MapStrokeShape,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor,
["Padding"] = MapPadding
};
public static CommandMapper<IBorderView, BorderHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IBorderView, BorderHandler> CommandMapper = new CommandMapper<IBorderView, BorderHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public BorderHandler() : base(Mapper, CommandMapper)
{
}
public BorderHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public BorderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public BorderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaBorder CreatePlatformView()
{
return new SkiaBorder();
}
protected override SkiaBorder CreatePlatformView()
{
return new SkiaBorder();
}
protected override void ConnectHandler(SkiaBorder platformView)
{
base.ConnectHandler(platformView);
}
protected override void ConnectHandler(SkiaBorder platformView)
{
base.ConnectHandler(platformView);
IBorderView virtualView = base.VirtualView;
View val = (View)(object)((virtualView is View) ? virtualView : null);
if (val != null)
{
platformView.MauiView = val;
}
platformView.Tapped += OnPlatformViewTapped;
}
protected override void DisconnectHandler(SkiaBorder platformView)
{
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaBorder platformView)
{
platformView.Tapped -= OnPlatformViewTapped;
platformView.MauiView = null;
base.DisconnectHandler(platformView);
}
public static void MapContent(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null || handler.MauiContext is null) return;
private void OnPlatformViewTapped(object? sender, EventArgs e)
{
IBorderView virtualView = base.VirtualView;
View val = (View)(object)((virtualView is View) ? virtualView : null);
if (val != null)
{
GestureManager.ProcessTap(val, 0.0, 0.0);
}
}
handler.PlatformView.ClearChildren();
public static void MapContent(BorderHandler handler, IBorderView border)
{
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.ClearChildren();
IView presentedContent = ((IContentView)border).PresentedContent;
if (presentedContent != null)
{
if (presentedContent.Handler == null)
{
Console.WriteLine("[BorderHandler] Creating handler for content: " + ((object)presentedContent).GetType().Name);
presentedContent.Handler = presentedContent.ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = presentedContent.Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
Console.WriteLine("[BorderHandler] Adding content: " + ((object)skiaView).GetType().Name);
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.AddChild(skiaView);
}
}
}
var content = border.PresentedContent;
if (content != null)
{
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
Console.WriteLine($"[BorderHandler] Creating handler for content: {content.GetType().Name}");
content.Handler = content.ToHandler(handler.MauiContext);
}
public static void MapStroke(BorderHandler handler, IBorderView border)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
Paint stroke = ((IStroke)border).Stroke;
SolidPaint val = (SolidPaint)(object)((stroke is SolidPaint) ? stroke : null);
if (val != null && val.Color != null)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.Stroke = val.Color.ToSKColor();
}
}
}
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
Console.WriteLine($"[BorderHandler] Adding content: {skiaContent.GetType().Name}");
handler.PlatformView.AddChild(skiaContent);
}
}
}
public static void MapStrokeThickness(BorderHandler handler, IBorderView border)
{
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.StrokeThickness = (float)((IStroke)border).StrokeThickness;
}
}
public static void MapStroke(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
public static void MapBackground(BorderHandler handler, IBorderView border)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
Paint background = ((IView)border).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (border.Stroke is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.Stroke = solidPaint.Color.ToSKColor();
}
}
public static void MapBackgroundColor(BorderHandler handler, IBorderView border)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
VisualElement val = (VisualElement)(object)((border is VisualElement) ? border : null);
if (val != null && val.BackgroundColor != null)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.BackgroundColor = val.BackgroundColor.ToSKColor();
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.Invalidate();
}
}
}
public static void MapStrokeThickness(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
handler.PlatformView.StrokeThickness = (float)border.StrokeThickness;
}
public static void MapPadding(BorderHandler handler, IBorderView border)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
Thickness padding = ((IPadding)border).Padding;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.PaddingLeft = (float)((Thickness)(ref padding)).Left;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.PaddingTop = (float)((Thickness)(ref padding)).Top;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.PaddingRight = (float)((Thickness)(ref padding)).Right;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.PaddingBottom = (float)((Thickness)(ref padding)).Bottom;
}
}
public static void MapBackground(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
if (border.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackgroundColor(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
if (border is VisualElement ve && ve.BackgroundColor != null)
{
handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
handler.PlatformView.Invalidate();
}
}
public static void MapPadding(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
var padding = border.Padding;
handler.PlatformView.PaddingLeft = (float)padding.Left;
handler.PlatformView.PaddingTop = (float)padding.Top;
handler.PlatformView.PaddingRight = (float)padding.Right;
handler.PlatformView.PaddingBottom = (float)padding.Bottom;
}
public static void MapStrokeShape(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
// StrokeShape is on the Border control class, not IBorderView interface
if (border is not Border borderControl) return;
var shape = borderControl.StrokeShape;
if (shape is Microsoft.Maui.Controls.Shapes.RoundRectangle roundRect)
{
// RoundRectangle can have different corner radii, but we use a uniform one
// Take the top-left corner as the uniform radius
var cornerRadius = roundRect.CornerRadius;
handler.PlatformView.CornerRadius = (float)cornerRadius.TopLeft;
}
else if (shape is Microsoft.Maui.Controls.Shapes.Rectangle)
{
handler.PlatformView.CornerRadius = 0;
}
else if (shape is Microsoft.Maui.Controls.Shapes.Ellipse)
{
// For ellipse, use half the min dimension as corner radius
// This will be applied during rendering when bounds are known
handler.PlatformView.CornerRadius = float.MaxValue; // Marker for "fully rounded"
}
handler.PlatformView.Invalidate();
}
public static void MapStrokeShape(BorderHandler handler, IBorderView border)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView == null)
{
return;
}
Border val = (Border)(object)((border is Border) ? border : null);
if (val != null)
{
IShape strokeShape = val.StrokeShape;
RoundRectangle val2 = (RoundRectangle)(object)((strokeShape is RoundRectangle) ? strokeShape : null);
if (val2 != null)
{
CornerRadius cornerRadius = val2.CornerRadius;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.CornerRadius = (float)((CornerRadius)(ref cornerRadius)).TopLeft;
}
else if (strokeShape is Rectangle)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.CornerRadius = 0f;
}
else if (strokeShape is Ellipse)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.CornerRadius = float.MaxValue;
}
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.Invalidate();
}
}
}

View File

@@ -1,67 +1,66 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for BoxView on Linux.
/// </summary>
public partial class BoxViewHandler : ViewHandler<BoxView, SkiaBoxView>
public class BoxViewHandler : ViewHandler<BoxView, SkiaBoxView>
{
public static IPropertyMapper<BoxView, BoxViewHandler> Mapper =
new PropertyMapper<BoxView, BoxViewHandler>(ViewMapper)
{
[nameof(BoxView.Color)] = MapColor,
[nameof(BoxView.CornerRadius)] = MapCornerRadius,
[nameof(IView.Background)] = MapBackground,
["BackgroundColor"] = MapBackgroundColor,
};
public static IPropertyMapper<BoxView, BoxViewHandler> Mapper = (IPropertyMapper<BoxView, BoxViewHandler>)(object)new PropertyMapper<BoxView, BoxViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Color"] = MapColor,
["CornerRadius"] = MapCornerRadius,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public BoxViewHandler() : base(Mapper)
{
}
public BoxViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)null)
{
}
protected override SkiaBoxView CreatePlatformView()
{
return new SkiaBoxView();
}
protected override SkiaBoxView CreatePlatformView()
{
return new SkiaBoxView();
}
public static void MapColor(BoxViewHandler handler, BoxView boxView)
{
if (boxView.Color != null)
{
handler.PlatformView.Color = new SKColor(
(byte)(boxView.Color.Red * 255),
(byte)(boxView.Color.Green * 255),
(byte)(boxView.Color.Blue * 255),
(byte)(boxView.Color.Alpha * 255));
}
}
public static void MapColor(BoxViewHandler handler, BoxView boxView)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (boxView.Color != null)
{
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.Color = new SKColor((byte)(boxView.Color.Red * 255f), (byte)(boxView.Color.Green * 255f), (byte)(boxView.Color.Blue * 255f), (byte)(boxView.Color.Alpha * 255f));
}
}
public static void MapCornerRadius(BoxViewHandler handler, BoxView boxView)
{
handler.PlatformView.CornerRadius = (float)boxView.CornerRadius.TopLeft;
}
public static void MapCornerRadius(BoxViewHandler handler, BoxView boxView)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
SkiaBoxView platformView = ((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView;
CornerRadius cornerRadius = boxView.CornerRadius;
platformView.CornerRadius = (float)((CornerRadius)(ref cornerRadius)).TopLeft;
}
public static void MapBackground(BoxViewHandler handler, BoxView boxView)
{
if (boxView.Background is SolidColorBrush solidBrush && solidBrush.Color != null)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
handler.PlatformView.Invalidate();
}
}
public static void MapBackground(BoxViewHandler handler, BoxView boxView)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
Brush background = ((VisualElement)boxView).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapBackgroundColor(BoxViewHandler handler, BoxView boxView)
{
if (boxView.BackgroundColor != null)
{
handler.PlatformView.BackgroundColor = boxView.BackgroundColor.ToSKColor();
handler.PlatformView.Invalidate();
}
}
public static void MapBackgroundColor(BoxViewHandler handler, BoxView boxView)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
if (((VisualElement)boxView).BackgroundColor != null)
{
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.BackgroundColor = ((VisualElement)boxView).BackgroundColor.ToSKColor();
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.Invalidate();
}
}
}

View File

@@ -1,198 +1,153 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Button on Linux using Skia rendering.
/// Maps IButton interface to SkiaButton platform view.
/// </summary>
public partial class ButtonHandler : ViewHandler<IButton, SkiaButton>
public class ButtonHandler : ViewHandler<IButton, SkiaButton>
{
public static IPropertyMapper<IButton, ButtonHandler> Mapper = new PropertyMapper<IButton, ButtonHandler>(ViewHandler.ViewMapper)
{
[nameof(IButtonStroke.StrokeColor)] = MapStrokeColor,
[nameof(IButtonStroke.StrokeThickness)] = MapStrokeThickness,
[nameof(IButtonStroke.CornerRadius)] = MapCornerRadius,
[nameof(IView.Background)] = MapBackground,
[nameof(IPadding.Padding)] = MapPadding,
[nameof(IView.IsEnabled)] = MapIsEnabled,
};
public static IPropertyMapper<IButton, ButtonHandler> Mapper = (IPropertyMapper<IButton, ButtonHandler>)(object)new PropertyMapper<IButton, ButtonHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["StrokeColor"] = MapStrokeColor,
["StrokeThickness"] = MapStrokeThickness,
["CornerRadius"] = MapCornerRadius,
["Background"] = MapBackground,
["Padding"] = MapPadding,
["IsEnabled"] = MapIsEnabled
};
public static CommandMapper<IButton, ButtonHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IButton, ButtonHandler> CommandMapper = new CommandMapper<IButton, ButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public ButtonHandler() : base(Mapper, CommandMapper)
{
}
public ButtonHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public ButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaButton CreatePlatformView()
{
var button = new SkiaButton();
return button;
}
protected override SkiaButton CreatePlatformView()
{
return new SkiaButton();
}
protected override void ConnectHandler(SkiaButton platformView)
{
base.ConnectHandler(platformView);
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
protected override void ConnectHandler(SkiaButton platformView)
{
base.ConnectHandler(platformView);
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
if (base.VirtualView != null)
{
MapStrokeColor(this, base.VirtualView);
MapStrokeThickness(this, base.VirtualView);
MapCornerRadius(this, base.VirtualView);
MapBackground(this, base.VirtualView);
MapPadding(this, base.VirtualView);
MapIsEnabled(this, base.VirtualView);
}
}
// Manually map all properties on connect since MAUI may not trigger updates
// for properties that were set before handler connection
if (VirtualView != null)
{
MapStrokeColor(this, VirtualView);
MapStrokeThickness(this, VirtualView);
MapCornerRadius(this, VirtualView);
MapBackground(this, VirtualView);
MapPadding(this, VirtualView);
MapIsEnabled(this, VirtualView);
}
}
protected override void DisconnectHandler(SkiaButton platformView)
{
platformView.Clicked -= OnClicked;
platformView.Pressed -= OnPressed;
platformView.Released -= OnReleased;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaButton platformView)
{
platformView.Clicked -= OnClicked;
platformView.Pressed -= OnPressed;
platformView.Released -= OnReleased;
base.DisconnectHandler(platformView);
}
private void OnClicked(object? sender, EventArgs e)
{
IButton virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Clicked();
}
}
private void OnClicked(object? sender, EventArgs e) => VirtualView?.Clicked();
private void OnPressed(object? sender, EventArgs e) => VirtualView?.Pressed();
private void OnReleased(object? sender, EventArgs e) => VirtualView?.Released();
private void OnPressed(object? sender, EventArgs e)
{
IButton virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Pressed();
}
}
public static void MapStrokeColor(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
private void OnReleased(object? sender, EventArgs e)
{
IButton virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Released();
}
}
var strokeColor = button.StrokeColor;
if (strokeColor is not null)
handler.PlatformView.BorderColor = strokeColor.ToSKColor();
}
public static void MapStrokeColor(ButtonHandler handler, IButton button)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Color strokeColor = ((IButtonStroke)button).StrokeColor;
if (strokeColor != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.BorderColor = strokeColor.ToSKColor();
}
}
}
public static void MapStrokeThickness(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
handler.PlatformView.BorderWidth = (float)button.StrokeThickness;
}
public static void MapStrokeThickness(ButtonHandler handler, IButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.BorderWidth = (float)((IButtonStroke)button).StrokeThickness;
}
}
public static void MapCornerRadius(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CornerRadius = button.CornerRadius;
}
public static void MapCornerRadius(ButtonHandler handler, IButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.CornerRadius = ((IButtonStroke)button).CornerRadius;
}
}
public static void MapBackground(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
public static void MapBackground(ButtonHandler handler, IButton button)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Paint background = ((IView)button).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.ButtonBackgroundColor = val.Color.ToSKColor();
}
}
}
if (button.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
// Set ButtonBackgroundColor (used for rendering) not base BackgroundColor
handler.PlatformView.ButtonBackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapPadding(ButtonHandler handler, IButton button)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Thickness padding = ((IPadding)button).Padding;
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.Padding = new SKRect((float)((Thickness)(ref padding)).Left, (float)((Thickness)(ref padding)).Top, (float)((Thickness)(ref padding)).Right, (float)((Thickness)(ref padding)).Bottom);
}
}
public static void MapPadding(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
var padding = button.Padding;
handler.PlatformView.Padding = new SKRect(
(float)padding.Left,
(float)padding.Top,
(float)padding.Right,
(float)padding.Bottom);
}
public static void MapIsEnabled(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
Console.WriteLine($"[ButtonHandler] MapIsEnabled - Text='{handler.PlatformView.Text}', IsEnabled={button.IsEnabled}");
handler.PlatformView.IsEnabled = button.IsEnabled;
handler.PlatformView.Invalidate();
}
}
/// <summary>
/// Handler for TextButton on Linux - extends ButtonHandler with text support.
/// Maps ITextButton interface (which includes IText properties).
/// </summary>
public partial class TextButtonHandler : ButtonHandler
{
public static new IPropertyMapper<ITextButton, TextButtonHandler> Mapper =
new PropertyMapper<ITextButton, TextButtonHandler>(ButtonHandler.Mapper)
{
[nameof(IText.Text)] = MapText,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(ITextStyle.CharacterSpacing)] = MapCharacterSpacing,
};
public TextButtonHandler() : base(Mapper)
{
}
protected override void ConnectHandler(SkiaButton platformView)
{
base.ConnectHandler(platformView);
// Manually map text properties on connect since MAUI may not trigger updates
// for properties that were set before handler connection
if (VirtualView is ITextButton textButton)
{
MapText(this, textButton);
MapTextColor(this, textButton);
MapFont(this, textButton);
MapCharacterSpacing(this, textButton);
}
}
public static void MapText(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Text = button.Text ?? string.Empty;
}
public static void MapTextColor(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
if (button.TextColor is not null)
handler.PlatformView.TextColor = button.TextColor.ToSKColor();
}
public static void MapFont(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
var font = button.Font;
if (font.Size > 0)
handler.PlatformView.FontSize = (float)font.Size;
if (!string.IsNullOrEmpty(font.Family))
handler.PlatformView.FontFamily = font.Family;
handler.PlatformView.IsBold = font.Weight >= FontWeight.Bold;
handler.PlatformView.IsItalic = font.Slant == FontSlant.Italic || font.Slant == FontSlant.Oblique;
}
public static void MapCharacterSpacing(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CharacterSpacing = (float)button.CharacterSpacing;
}
public static void MapIsEnabled(ButtonHandler handler, IButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Console.WriteLine($"[ButtonHandler] MapIsEnabled - Text='{((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.Text}', IsEnabled={((IView)button).IsEnabled}");
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.IsEnabled = ((IView)button).IsEnabled;
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.Invalidate();
}
}
}

View File

@@ -1,116 +1,164 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using SkiaSharp;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Primitives;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for CheckBox on Linux using Skia rendering.
/// Maps ICheckBox interface to SkiaCheckBox platform view.
/// </summary>
public partial class CheckBoxHandler : ViewHandler<ICheckBox, SkiaCheckBox>
public class CheckBoxHandler : ViewHandler<ICheckBox, SkiaCheckBox>
{
public static IPropertyMapper<ICheckBox, CheckBoxHandler> Mapper = new PropertyMapper<ICheckBox, CheckBoxHandler>(ViewHandler.ViewMapper)
{
[nameof(ICheckBox.IsChecked)] = MapIsChecked,
[nameof(ICheckBox.Foreground)] = MapForeground,
[nameof(IView.Background)] = MapBackground,
[nameof(IView.VerticalLayoutAlignment)] = MapVerticalLayoutAlignment,
[nameof(IView.HorizontalLayoutAlignment)] = MapHorizontalLayoutAlignment,
};
public static IPropertyMapper<ICheckBox, CheckBoxHandler> Mapper = (IPropertyMapper<ICheckBox, CheckBoxHandler>)(object)new PropertyMapper<ICheckBox, CheckBoxHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsChecked"] = MapIsChecked,
["Foreground"] = MapForeground,
["Background"] = MapBackground,
["IsEnabled"] = MapIsEnabled,
["VerticalLayoutAlignment"] = MapVerticalLayoutAlignment,
["HorizontalLayoutAlignment"] = MapHorizontalLayoutAlignment
};
public static CommandMapper<ICheckBox, CheckBoxHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<ICheckBox, CheckBoxHandler> CommandMapper = new CommandMapper<ICheckBox, CheckBoxHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public CheckBoxHandler() : base(Mapper, CommandMapper)
{
}
public CheckBoxHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public CheckBoxHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public CheckBoxHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaCheckBox CreatePlatformView()
{
return new SkiaCheckBox();
}
protected override SkiaCheckBox CreatePlatformView()
{
return new SkiaCheckBox();
}
protected override void ConnectHandler(SkiaCheckBox platformView)
{
base.ConnectHandler(platformView);
platformView.CheckedChanged += OnCheckedChanged;
}
protected override void ConnectHandler(SkiaCheckBox platformView)
{
base.ConnectHandler(platformView);
platformView.CheckedChanged += OnCheckedChanged;
}
protected override void DisconnectHandler(SkiaCheckBox platformView)
{
platformView.CheckedChanged -= OnCheckedChanged;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaCheckBox platformView)
{
platformView.CheckedChanged -= OnCheckedChanged;
base.DisconnectHandler(platformView);
}
private void OnCheckedChanged(object? sender, Platform.CheckedChangedEventArgs e)
{
if (VirtualView is not null && VirtualView.IsChecked != e.IsChecked)
{
VirtualView.IsChecked = e.IsChecked;
}
}
private void OnCheckedChanged(object? sender, CheckedChangedEventArgs e)
{
if (base.VirtualView != null && base.VirtualView.IsChecked != e.IsChecked)
{
base.VirtualView.IsChecked = e.IsChecked;
}
}
public static void MapIsChecked(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsChecked = checkBox.IsChecked;
}
public static void MapIsChecked(CheckBoxHandler handler, ICheckBox checkBox)
{
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView.IsChecked = checkBox.IsChecked;
}
}
public static void MapForeground(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
public static void MapForeground(CheckBoxHandler handler, ICheckBox checkBox)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
Paint foreground = checkBox.Foreground;
SolidPaint val = (SolidPaint)(object)((foreground is SolidPaint) ? foreground : null);
if (val != null && val.Color != null)
{
((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView.CheckColor = val.Color.ToSKColor();
}
}
}
if (checkBox.Foreground is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.CheckColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackground(CheckBoxHandler handler, ICheckBox checkBox)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
Paint background = ((IView)checkBox).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapBackground(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
public static void MapIsEnabled(CheckBoxHandler handler, ICheckBox checkBox)
{
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView.IsEnabled = ((IView)checkBox).IsEnabled;
}
}
if (checkBox.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapVerticalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
SkiaCheckBox platformView = ((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView;
LayoutAlignment verticalLayoutAlignment = ((IView)checkBox).VerticalLayoutAlignment;
platformView.VerticalOptions = (LayoutOptions)((int)verticalLayoutAlignment switch
{
1 => LayoutOptions.Start,
2 => LayoutOptions.Center,
3 => LayoutOptions.End,
0 => LayoutOptions.Fill,
_ => LayoutOptions.Fill,
});
}
}
public static void MapVerticalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalOptions = checkBox.VerticalLayoutAlignment switch
{
Primitives.LayoutAlignment.Start => LayoutOptions.Start,
Primitives.LayoutAlignment.Center => LayoutOptions.Center,
Primitives.LayoutAlignment.End => LayoutOptions.End,
Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
_ => LayoutOptions.Fill
};
}
public static void MapHorizontalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalOptions = checkBox.HorizontalLayoutAlignment switch
{
Primitives.LayoutAlignment.Start => LayoutOptions.Start,
Primitives.LayoutAlignment.Center => LayoutOptions.Center,
Primitives.LayoutAlignment.End => LayoutOptions.End,
Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
_ => LayoutOptions.Start
};
}
public static void MapHorizontalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
SkiaCheckBox platformView = ((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView;
LayoutAlignment horizontalLayoutAlignment = ((IView)checkBox).HorizontalLayoutAlignment;
platformView.HorizontalOptions = (LayoutOptions)((int)horizontalLayoutAlignment switch
{
1 => LayoutOptions.Start,
2 => LayoutOptions.Center,
3 => LayoutOptions.End,
0 => LayoutOptions.Fill,
_ => LayoutOptions.Start,
});
}
}
}

View File

@@ -1,374 +1,458 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for CollectionView on Linux using Skia rendering.
/// Maps CollectionView to SkiaCollectionView platform view.
/// </summary>
public partial class CollectionViewHandler : ViewHandler<CollectionView, SkiaCollectionView>
public class CollectionViewHandler : ViewHandler<CollectionView, SkiaCollectionView>
{
private bool _isUpdatingSelection;
private bool _isUpdatingSelection;
public static IPropertyMapper<CollectionView, CollectionViewHandler> Mapper =
new PropertyMapper<CollectionView, CollectionViewHandler>(ViewHandler.ViewMapper)
{
// ItemsView properties
[nameof(ItemsView.ItemsSource)] = MapItemsSource,
[nameof(ItemsView.ItemTemplate)] = MapItemTemplate,
[nameof(ItemsView.EmptyView)] = MapEmptyView,
[nameof(ItemsView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
[nameof(ItemsView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
public static IPropertyMapper<CollectionView, CollectionViewHandler> Mapper = (IPropertyMapper<CollectionView, CollectionViewHandler>)(object)new PropertyMapper<CollectionView, CollectionViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["ItemsSource"] = MapItemsSource,
["ItemTemplate"] = MapItemTemplate,
["EmptyView"] = MapEmptyView,
["HorizontalScrollBarVisibility"] = MapHorizontalScrollBarVisibility,
["VerticalScrollBarVisibility"] = MapVerticalScrollBarVisibility,
["SelectedItem"] = MapSelectedItem,
["SelectedItems"] = MapSelectedItems,
["SelectionMode"] = MapSelectionMode,
["Header"] = MapHeader,
["Footer"] = MapFooter,
["ItemsLayout"] = MapItemsLayout,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
// SelectableItemsView properties
[nameof(SelectableItemsView.SelectedItem)] = MapSelectedItem,
[nameof(SelectableItemsView.SelectedItems)] = MapSelectedItems,
[nameof(SelectableItemsView.SelectionMode)] = MapSelectionMode,
public static CommandMapper<CollectionView, CollectionViewHandler> CommandMapper = new CommandMapper<CollectionView, CollectionViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["ScrollTo"] = MapScrollTo };
// StructuredItemsView properties
[nameof(StructuredItemsView.Header)] = MapHeader,
[nameof(StructuredItemsView.Footer)] = MapFooter,
[nameof(StructuredItemsView.ItemsLayout)] = MapItemsLayout,
public CollectionViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
[nameof(IView.Background)] = MapBackground,
[nameof(CollectionView.BackgroundColor)] = MapBackgroundColor,
};
public CollectionViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public static CommandMapper<CollectionView, CollectionViewHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
["ScrollTo"] = MapScrollTo,
};
protected override SkiaCollectionView CreatePlatformView()
{
return new SkiaCollectionView();
}
public CollectionViewHandler() : base(Mapper, CommandMapper)
{
}
protected override void ConnectHandler(SkiaCollectionView platformView)
{
base.ConnectHandler(platformView);
platformView.SelectionChanged += OnSelectionChanged;
platformView.Scrolled += OnScrolled;
platformView.ItemTapped += OnItemTapped;
}
public CollectionViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override void DisconnectHandler(SkiaCollectionView platformView)
{
platformView.SelectionChanged -= OnSelectionChanged;
platformView.Scrolled -= OnScrolled;
platformView.ItemTapped -= OnItemTapped;
base.DisconnectHandler(platformView);
}
protected override SkiaCollectionView CreatePlatformView()
{
return new SkiaCollectionView();
}
private void OnSelectionChanged(object? sender, CollectionSelectionChangedEventArgs e)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Invalid comparison between Unknown and I4
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Invalid comparison between Unknown and I4
if (base.VirtualView == null || _isUpdatingSelection)
{
return;
}
try
{
_isUpdatingSelection = true;
if ((int)((SelectableItemsView)base.VirtualView).SelectionMode == 1)
{
object obj = e.CurrentSelection.FirstOrDefault();
if (!object.Equals(((SelectableItemsView)base.VirtualView).SelectedItem, obj))
{
((SelectableItemsView)base.VirtualView).SelectedItem = obj;
}
}
else
{
if ((int)((SelectableItemsView)base.VirtualView).SelectionMode != 2)
{
return;
}
((SelectableItemsView)base.VirtualView).SelectedItems.Clear();
{
foreach (object item in e.CurrentSelection)
{
((SelectableItemsView)base.VirtualView).SelectedItems.Add(item);
}
return;
}
}
}
finally
{
_isUpdatingSelection = false;
}
}
protected override void ConnectHandler(SkiaCollectionView platformView)
{
base.ConnectHandler(platformView);
platformView.SelectionChanged += OnSelectionChanged;
platformView.Scrolled += OnScrolled;
platformView.ItemTapped += OnItemTapped;
}
private void OnScrolled(object? sender, ItemsScrolledEventArgs e)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Expected O, but got Unknown
CollectionView virtualView = base.VirtualView;
if (virtualView != null)
{
((ItemsView)virtualView).SendScrolled(new ItemsViewScrolledEventArgs
{
VerticalOffset = e.ScrollOffset,
VerticalDelta = 0.0,
HorizontalOffset = 0.0,
HorizontalDelta = 0.0
});
}
}
protected override void DisconnectHandler(SkiaCollectionView platformView)
{
platformView.SelectionChanged -= OnSelectionChanged;
platformView.Scrolled -= OnScrolled;
platformView.ItemTapped -= OnItemTapped;
base.DisconnectHandler(platformView);
}
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Invalid comparison between Unknown and I4
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Invalid comparison between Unknown and I4
if (base.VirtualView == null || _isUpdatingSelection)
{
return;
}
try
{
_isUpdatingSelection = true;
Console.WriteLine($"[CollectionViewHandler] OnItemTapped index={e.Index}, item={e.Item}, SelectionMode={((SelectableItemsView)base.VirtualView).SelectionMode}");
SkiaView skiaView = base.PlatformView?.GetItemView(e.Index);
Console.WriteLine($"[CollectionViewHandler] GetItemView({e.Index}) returned: {((object)skiaView)?.GetType().Name ?? "null"}, MauiView={((object)skiaView?.MauiView)?.GetType().Name ?? "null"}");
if (skiaView?.MauiView != null)
{
Console.WriteLine($"[CollectionViewHandler] Found MauiView: {((object)skiaView.MauiView).GetType().Name}, GestureRecognizers={skiaView.MauiView.GestureRecognizers?.Count ?? 0}");
if (GestureManager.ProcessTap(skiaView.MauiView, 0.0, 0.0))
{
Console.WriteLine("[CollectionViewHandler] Gesture processed successfully");
return;
}
}
if ((int)((SelectableItemsView)base.VirtualView).SelectionMode == 1)
{
((SelectableItemsView)base.VirtualView).SelectedItem = e.Item;
}
else if ((int)((SelectableItemsView)base.VirtualView).SelectionMode == 2)
{
if (((SelectableItemsView)base.VirtualView).SelectedItems.Contains(e.Item))
{
((SelectableItemsView)base.VirtualView).SelectedItems.Remove(e.Item);
}
else
{
((SelectableItemsView)base.VirtualView).SelectedItems.Add(e.Item);
}
}
}
finally
{
_isUpdatingSelection = false;
}
}
private void OnSelectionChanged(object? sender, CollectionSelectionChangedEventArgs e)
{
if (VirtualView is null || _isUpdatingSelection) return;
public static void MapItemsSource(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ItemsSource = ((ItemsView)collectionView).ItemsSource;
}
}
try
{
_isUpdatingSelection = true;
public static void MapItemTemplate(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
DataTemplate template = ((ItemsView)collectionView).ItemTemplate;
if (template != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ItemViewCreator = delegate(object item)
{
try
{
object obj = ((ElementTemplate)template).CreateContent();
View val = (View)((obj is View) ? obj : null);
if (val != null)
{
((BindableObject)val).BindingContext = item;
PropagateBindingContext(val, item);
if (((VisualElement)val).Handler == null && ((ElementHandler)handler).MauiContext != null)
{
((VisualElement)val).Handler = ((IView)(object)val).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = ((VisualElement)val).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
skiaView.MauiView = val;
Console.WriteLine($"[CollectionViewHandler.ItemViewCreator] Set MauiView={((object)val).GetType().Name} on {((object)skiaView).GetType().Name}, GestureRecognizers={val.GestureRecognizers?.Count ?? 0}");
return skiaView;
}
}
else
{
ViewCell val2 = (ViewCell)((obj is ViewCell) ? obj : null);
if (val2 != null)
{
((BindableObject)val2).BindingContext = item;
View view = val2.View;
if (view != null)
{
if (((VisualElement)view).Handler == null && ((ElementHandler)handler).MauiContext != null)
{
((VisualElement)view).Handler = ((IView)(object)view).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler3 = ((VisualElement)view).Handler;
if (((handler3 != null) ? ((IElementHandler)handler3).PlatformView : null) is SkiaView result)
{
return result;
}
}
}
}
}
catch
{
}
return (SkiaView?)null;
};
}
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Invalidate();
}
// Update virtual view selection
if (VirtualView.SelectionMode == SelectionMode.Single)
{
var newItem = e.CurrentSelection.FirstOrDefault();
if (!Equals(VirtualView.SelectedItem, newItem))
{
VirtualView.SelectedItem = newItem;
}
}
else if (VirtualView.SelectionMode == SelectionMode.Multiple)
{
// Clear and update selected items
VirtualView.SelectedItems.Clear();
foreach (var item in e.CurrentSelection)
{
VirtualView.SelectedItems.Add(item);
}
}
}
finally
{
_isUpdatingSelection = false;
}
}
public static void MapEmptyView(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.EmptyView = ((ItemsView)collectionView).EmptyView;
if (((ItemsView)collectionView).EmptyView is string emptyViewText)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.EmptyViewText = emptyViewText;
}
}
}
private void OnScrolled(object? sender, ItemsScrolledEventArgs e)
{
VirtualView?.SendScrolled(new ItemsViewScrolledEventArgs
{
VerticalOffset = e.ScrollOffset,
VerticalDelta = 0,
HorizontalOffset = 0,
HorizontalDelta = 0
});
}
public static void MapHorizontalScrollBarVisibility(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected I4, but got Unknown
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.HorizontalScrollBarVisibility = (ScrollBarVisibility)((ItemsView)collectionView).HorizontalScrollBarVisibility;
}
}
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
{
// Item tap is handled through selection
}
public static void MapVerticalScrollBarVisibility(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected I4, but got Unknown
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.VerticalScrollBarVisibility = (ScrollBarVisibility)((ItemsView)collectionView).VerticalScrollBarVisibility;
}
}
public static void MapItemsSource(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.ItemsSource = collectionView.ItemsSource;
}
public static void MapSelectedItem(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null || handler._isUpdatingSelection)
{
return;
}
try
{
handler._isUpdatingSelection = true;
if (!object.Equals(((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SelectedItem, ((SelectableItemsView)collectionView).SelectedItem))
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SelectedItem = ((SelectableItemsView)collectionView).SelectedItem;
}
}
finally
{
handler._isUpdatingSelection = false;
}
}
public static void MapItemTemplate(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null || handler.MauiContext is null) return;
public static void MapSelectedItems(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null || handler._isUpdatingSelection)
{
return;
}
try
{
handler._isUpdatingSelection = true;
IList<object> selectedItems = ((SelectableItemsView)collectionView).SelectedItems;
if (selectedItems != null && selectedItems.Count > 0)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SelectedItem = selectedItems.First();
}
}
finally
{
handler._isUpdatingSelection = false;
}
}
var template = collectionView.ItemTemplate;
if (template != null)
{
// Set up a renderer that creates views from the DataTemplate
handler.PlatformView.ItemViewCreator = (item) =>
{
try
{
// Create view from template
var content = template.CreateContent();
if (content is View view)
{
// Set binding context FIRST so bindings evaluate
view.BindingContext = item;
public static void MapSelectionMode(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
SkiaCollectionView platformView = ((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView;
SelectionMode selectionMode = ((SelectableItemsView)collectionView).SelectionMode;
platformView.SelectionMode = (int)selectionMode switch
{
0 => SkiaSelectionMode.None,
1 => SkiaSelectionMode.Single,
2 => SkiaSelectionMode.Multiple,
_ => SkiaSelectionMode.None,
};
}
}
// Force binding evaluation by accessing the visual tree
// This ensures child bindings are evaluated before handler creation
PropagateBindingContext(view, item);
public static void MapHeader(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Header = ((StructuredItemsView)collectionView).Header;
}
}
// Create handler for the view
if (view.Handler == null && handler.MauiContext != null)
{
view.Handler = view.ToHandler(handler.MauiContext);
}
public static void MapFooter(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Footer = ((StructuredItemsView)collectionView).Footer;
}
}
if (view.Handler?.PlatformView is SkiaView skiaView)
{
return skiaView;
}
}
else if (content is ViewCell cell)
{
cell.BindingContext = item;
var cellView = cell.View;
if (cellView != null)
{
if (cellView.Handler == null && handler.MauiContext != null)
{
cellView.Handler = cellView.ToHandler(handler.MauiContext);
}
public static void MapItemsLayout(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null)
{
return;
}
IItemsLayout itemsLayout = ((StructuredItemsView)collectionView).ItemsLayout;
LinearItemsLayout val = (LinearItemsLayout)(object)((itemsLayout is LinearItemsLayout) ? itemsLayout : null);
if (val != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Orientation = (((int)((ItemsLayout)val).Orientation != 0) ? ItemsLayoutOrientation.Horizontal : ItemsLayoutOrientation.Vertical);
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SpanCount = 1;
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ItemSpacing = (float)val.ItemSpacing;
return;
}
GridItemsLayout val2 = (GridItemsLayout)(object)((itemsLayout is GridItemsLayout) ? itemsLayout : null);
if (val2 != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Orientation = (((int)((ItemsLayout)val2).Orientation != 0) ? ItemsLayoutOrientation.Horizontal : ItemsLayoutOrientation.Vertical);
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SpanCount = val2.Span;
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ItemSpacing = (float)val2.VerticalItemSpacing;
}
}
if (cellView.Handler?.PlatformView is SkiaView skiaView)
{
return skiaView;
}
}
}
}
catch
{
// Ignore template creation errors
}
return null;
};
}
public static void MapBackground(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null && ((VisualElement)collectionView).BackgroundColor == null)
{
Brush background = ((VisualElement)collectionView).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
handler.PlatformView.Invalidate();
}
public static void MapBackgroundColor(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null && ((VisualElement)collectionView).BackgroundColor != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.BackgroundColor = ((VisualElement)collectionView).BackgroundColor.ToSKColor();
}
}
public static void MapEmptyView(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
public static void MapScrollTo(CollectionViewHandler handler, CollectionView collectionView, object? args)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null)
{
return;
}
ScrollToRequestEventArgs e = (ScrollToRequestEventArgs)((args is ScrollToRequestEventArgs) ? args : null);
if (e != null)
{
if ((int)e.Mode == 1)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ScrollToIndex(e.Index, e.IsAnimated);
}
else if (e.Item != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ScrollToItem(e.Item, e.IsAnimated);
}
}
}
handler.PlatformView.EmptyView = collectionView.EmptyView;
if (collectionView.EmptyView is string text)
{
handler.PlatformView.EmptyViewText = text;
}
}
public static void MapHorizontalScrollBarVisibility(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalScrollBarVisibility = (ScrollBarVisibility)collectionView.HorizontalScrollBarVisibility;
}
public static void MapVerticalScrollBarVisibility(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalScrollBarVisibility = (ScrollBarVisibility)collectionView.VerticalScrollBarVisibility;
}
public static void MapSelectedItem(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null || handler._isUpdatingSelection) return;
try
{
handler._isUpdatingSelection = true;
if (!Equals(handler.PlatformView.SelectedItem, collectionView.SelectedItem))
{
handler.PlatformView.SelectedItem = collectionView.SelectedItem;
}
}
finally
{
handler._isUpdatingSelection = false;
}
}
public static void MapSelectedItems(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null || handler._isUpdatingSelection) return;
try
{
handler._isUpdatingSelection = true;
// Sync selected items
var selectedItems = collectionView.SelectedItems;
if (selectedItems != null && selectedItems.Count > 0)
{
handler.PlatformView.SelectedItem = selectedItems.First();
}
}
finally
{
handler._isUpdatingSelection = false;
}
}
public static void MapSelectionMode(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.SelectionMode = collectionView.SelectionMode switch
{
SelectionMode.None => SkiaSelectionMode.None,
SelectionMode.Single => SkiaSelectionMode.Single,
SelectionMode.Multiple => SkiaSelectionMode.Multiple,
_ => SkiaSelectionMode.None
};
}
public static void MapHeader(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Header = collectionView.Header;
}
public static void MapFooter(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Footer = collectionView.Footer;
}
public static void MapItemsLayout(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
var layout = collectionView.ItemsLayout;
if (layout is LinearItemsLayout linearLayout)
{
handler.PlatformView.Orientation = linearLayout.Orientation == Controls.ItemsLayoutOrientation.Vertical
? Platform.ItemsLayoutOrientation.Vertical
: Platform.ItemsLayoutOrientation.Horizontal;
handler.PlatformView.SpanCount = 1;
handler.PlatformView.ItemSpacing = (float)linearLayout.ItemSpacing;
}
else if (layout is GridItemsLayout gridLayout)
{
handler.PlatformView.Orientation = gridLayout.Orientation == Controls.ItemsLayoutOrientation.Vertical
? Platform.ItemsLayoutOrientation.Vertical
: Platform.ItemsLayoutOrientation.Horizontal;
handler.PlatformView.SpanCount = gridLayout.Span;
handler.PlatformView.ItemSpacing = (float)gridLayout.VerticalItemSpacing;
}
}
public static void MapBackground(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
// Don't override if BackgroundColor is explicitly set
if (collectionView.BackgroundColor is not null)
return;
if (collectionView.Background is SolidColorBrush solidBrush)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
}
}
public static void MapBackgroundColor(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
if (collectionView.BackgroundColor is not null)
{
handler.PlatformView.BackgroundColor = collectionView.BackgroundColor.ToSKColor();
}
}
public static void MapScrollTo(CollectionViewHandler handler, CollectionView collectionView, object? args)
{
if (handler.PlatformView is null || args is not ScrollToRequestEventArgs scrollArgs)
return;
if (scrollArgs.Mode == ScrollToMode.Position)
{
handler.PlatformView.ScrollToIndex(scrollArgs.Index, scrollArgs.IsAnimated);
}
else if (scrollArgs.Item != null)
{
handler.PlatformView.ScrollToItem(scrollArgs.Item, scrollArgs.IsAnimated);
}
}
/// <summary>
/// Recursively propagates binding context to all child views to force binding evaluation.
/// </summary>
private static void PropagateBindingContext(View view, object? bindingContext)
{
view.BindingContext = bindingContext;
// Propagate to children
if (view is Layout layout)
{
foreach (var child in layout.Children)
{
if (child is View childView)
{
PropagateBindingContext(childView, bindingContext);
}
}
}
else if (view is ContentView contentView && contentView.Content != null)
{
PropagateBindingContext(contentView.Content, bindingContext);
}
else if (view is Border border && border.Content is View borderContent)
{
PropagateBindingContext(borderContent, bindingContext);
}
}
private static void PropagateBindingContext(View view, object? bindingContext)
{
((BindableObject)view).BindingContext = bindingContext;
Layout val = (Layout)(object)((view is Layout) ? view : null);
if (val != null)
{
foreach (IView child in val.Children)
{
View val2 = (View)(object)((child is View) ? child : null);
if (val2 != null)
{
PropagateBindingContext(val2, bindingContext);
}
}
return;
}
ContentView val3 = (ContentView)(object)((view is ContentView) ? view : null);
if (val3 != null && val3.Content != null)
{
PropagateBindingContext(val3.Content, bindingContext);
return;
}
Border val4 = (Border)(object)((view is Border) ? view : null);
if (val4 != null)
{
View content = val4.Content;
if (content != null)
{
PropagateBindingContext(content, bindingContext);
}
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ContentPageHandler : PageHandler
{
public new static IPropertyMapper<ContentPage, ContentPageHandler> Mapper = (IPropertyMapper<ContentPage, ContentPageHandler>)(object)new PropertyMapper<ContentPage, ContentPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)PageHandler.Mapper }) { ["Content"] = MapContent };
public new static CommandMapper<ContentPage, ContentPageHandler> CommandMapper = new CommandMapper<ContentPage, ContentPageHandler>((CommandMapper)(object)PageHandler.CommandMapper);
public ContentPageHandler()
: base((IPropertyMapper?)(object)Mapper, (CommandMapper?)(object)CommandMapper)
{
}
public ContentPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper?)(((object)mapper) ?? ((object)Mapper)), (CommandMapper?)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaPage CreatePlatformView()
{
return new SkiaContentPage();
}
public static void MapContent(ContentPageHandler handler, ContentPage page)
{
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
View content = page.Content;
if (content != null)
{
if (((VisualElement)content).Handler == null)
{
Console.WriteLine("[ContentPageHandler] Creating handler for content: " + ((object)content).GetType().Name);
((VisualElement)content).Handler = ((IView)(object)content).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = ((VisualElement)content).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
Console.WriteLine("[ContentPageHandler] Setting content: " + ((object)skiaView).GetType().Name);
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.Content = skiaView;
}
else
{
IViewHandler handler3 = ((VisualElement)content).Handler;
Console.WriteLine("[ContentPageHandler] Content handler PlatformView is not SkiaView: " + (((handler3 == null) ? null : ((IElementHandler)handler3).PlatformView?.GetType().Name) ?? "null"));
}
}
else
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.Content = null;
}
}
}

View File

@@ -1,114 +1,133 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for DatePicker on Linux using Skia rendering.
/// </summary>
public partial class DatePickerHandler : ViewHandler<IDatePicker, SkiaDatePicker>
public class DatePickerHandler : ViewHandler<IDatePicker, SkiaDatePicker>
{
public static IPropertyMapper<IDatePicker, DatePickerHandler> Mapper =
new PropertyMapper<IDatePicker, DatePickerHandler>(ViewHandler.ViewMapper)
{
[nameof(IDatePicker.Date)] = MapDate,
[nameof(IDatePicker.MinimumDate)] = MapMinimumDate,
[nameof(IDatePicker.MaximumDate)] = MapMaximumDate,
[nameof(IDatePicker.Format)] = MapFormat,
[nameof(IDatePicker.TextColor)] = MapTextColor,
[nameof(IDatePicker.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<IDatePicker, DatePickerHandler> Mapper = (IPropertyMapper<IDatePicker, DatePickerHandler>)(object)new PropertyMapper<IDatePicker, DatePickerHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Date"] = MapDate,
["MinimumDate"] = MapMinimumDate,
["MaximumDate"] = MapMaximumDate,
["Format"] = MapFormat,
["TextColor"] = MapTextColor,
["CharacterSpacing"] = MapCharacterSpacing,
["Background"] = MapBackground
};
public static CommandMapper<IDatePicker, DatePickerHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IDatePicker, DatePickerHandler> CommandMapper = new CommandMapper<IDatePicker, DatePickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public DatePickerHandler() : base(Mapper, CommandMapper)
{
}
public DatePickerHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public DatePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public DatePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaDatePicker CreatePlatformView()
{
return new SkiaDatePicker();
}
protected override SkiaDatePicker CreatePlatformView()
{
return new SkiaDatePicker();
}
protected override void ConnectHandler(SkiaDatePicker platformView)
{
base.ConnectHandler(platformView);
platformView.DateSelected += OnDateSelected;
}
protected override void ConnectHandler(SkiaDatePicker platformView)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
base.ConnectHandler(platformView);
platformView.DateSelected += OnDateSelected;
Application current = Application.Current;
if (current != null && (int)current.UserAppTheme == 2)
{
platformView.CalendarBackgroundColor = new SKColor((byte)30, (byte)30, (byte)30);
platformView.TextColor = new SKColor((byte)224, (byte)224, (byte)224);
platformView.BorderColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.DisabledDayColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.BackgroundColor = new SKColor((byte)45, (byte)45, (byte)45);
}
}
protected override void DisconnectHandler(SkiaDatePicker platformView)
{
platformView.DateSelected -= OnDateSelected;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaDatePicker platformView)
{
platformView.DateSelected -= OnDateSelected;
base.DisconnectHandler(platformView);
}
private void OnDateSelected(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnDateSelected(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
base.VirtualView.Date = base.PlatformView.Date;
}
}
VirtualView.Date = PlatformView.Date;
}
public static void MapDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.Date = datePicker.Date;
}
}
public static void MapDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Date = datePicker.Date;
}
public static void MapMinimumDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.MinimumDate = datePicker.MinimumDate;
}
}
public static void MapMinimumDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MinimumDate = datePicker.MinimumDate;
}
public static void MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.MaximumDate = datePicker.MaximumDate;
}
}
public static void MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaximumDate = datePicker.MaximumDate;
}
public static void MapFormat(DatePickerHandler handler, IDatePicker datePicker)
{
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.Format = datePicker.Format ?? "d";
}
}
public static void MapFormat(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Format = datePicker.Format ?? "d";
}
public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null && ((ITextStyle)datePicker).TextColor != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.TextColor = ((ITextStyle)datePicker).TextColor.ToSKColor();
}
}
public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
if (datePicker.TextColor is not null)
{
handler.PlatformView.TextColor = datePicker.TextColor.ToSKColor();
}
}
public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker)
{
}
public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker)
{
// Character spacing would require custom text rendering
}
public static void MapBackground(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
if (datePicker.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackground(DatePickerHandler handler, IDatePicker datePicker)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
Paint background = ((IView)datePicker).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
}

View File

@@ -1,181 +1,182 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Editor (multiline text) on Linux using Skia rendering.
/// </summary>
public partial class EditorHandler : ViewHandler<IEditor, SkiaEditor>
public class EditorHandler : ViewHandler<IEditor, SkiaEditor>
{
public static IPropertyMapper<IEditor, EditorHandler> Mapper =
new PropertyMapper<IEditor, EditorHandler>(ViewHandler.ViewMapper)
{
[nameof(IEditor.Text)] = MapText,
[nameof(IEditor.Placeholder)] = MapPlaceholder,
[nameof(IEditor.PlaceholderColor)] = MapPlaceholderColor,
[nameof(IEditor.TextColor)] = MapTextColor,
[nameof(IEditor.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IEditor.IsReadOnly)] = MapIsReadOnly,
[nameof(IEditor.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled,
[nameof(IEditor.MaxLength)] = MapMaxLength,
[nameof(IEditor.CursorPosition)] = MapCursorPosition,
[nameof(IEditor.SelectionLength)] = MapSelectionLength,
[nameof(IEditor.Keyboard)] = MapKeyboard,
[nameof(IEditor.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(IEditor.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(IView.Background)] = MapBackground,
["BackgroundColor"] = MapBackgroundColor,
};
public static IPropertyMapper<IEditor, EditorHandler> Mapper = (IPropertyMapper<IEditor, EditorHandler>)(object)new PropertyMapper<IEditor, EditorHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Text"] = MapText,
["Placeholder"] = MapPlaceholder,
["PlaceholderColor"] = MapPlaceholderColor,
["TextColor"] = MapTextColor,
["CharacterSpacing"] = MapCharacterSpacing,
["IsReadOnly"] = MapIsReadOnly,
["IsTextPredictionEnabled"] = MapIsTextPredictionEnabled,
["MaxLength"] = MapMaxLength,
["CursorPosition"] = MapCursorPosition,
["SelectionLength"] = MapSelectionLength,
["Keyboard"] = MapKeyboard,
["HorizontalTextAlignment"] = MapHorizontalTextAlignment,
["VerticalTextAlignment"] = MapVerticalTextAlignment,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static CommandMapper<IEditor, EditorHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IEditor, EditorHandler> CommandMapper = new CommandMapper<IEditor, EditorHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public EditorHandler() : base(Mapper, CommandMapper)
{
}
public EditorHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public EditorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public EditorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaEditor CreatePlatformView()
{
return new SkiaEditor();
}
protected override SkiaEditor CreatePlatformView()
{
return new SkiaEditor();
}
protected override void ConnectHandler(SkiaEditor platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.Completed += OnCompleted;
}
protected override void ConnectHandler(SkiaEditor platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.Completed += OnCompleted;
}
protected override void DisconnectHandler(SkiaEditor platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.Completed -= OnCompleted;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaEditor platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.Completed -= OnCompleted;
base.DisconnectHandler(platformView);
}
private void OnTextChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnTextChanged(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
((ITextInput)base.VirtualView).Text = base.PlatformView.Text;
}
}
VirtualView.Text = PlatformView.Text;
}
private void OnCompleted(object? sender, EventArgs e)
{
}
private void OnCompleted(object? sender, EventArgs e)
{
// Editor doesn't typically have a completed event, but we could trigger it
}
public static void MapText(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.Text = ((ITextInput)editor).Text ?? "";
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapText(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Text = editor.Text ?? "";
handler.PlatformView.Invalidate();
}
public static void MapPlaceholder(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.Placeholder = ((IPlaceholder)editor).Placeholder ?? "";
}
}
public static void MapPlaceholder(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Placeholder = editor.Placeholder ?? "";
}
public static void MapPlaceholderColor(EditorHandler handler, IEditor editor)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null && ((IPlaceholder)editor).PlaceholderColor != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.PlaceholderColor = ((IPlaceholder)editor).PlaceholderColor.ToSKColor();
}
}
public static void MapPlaceholderColor(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
if (editor.PlaceholderColor is not null)
{
handler.PlatformView.PlaceholderColor = editor.PlaceholderColor.ToSKColor();
}
}
public static void MapTextColor(EditorHandler handler, IEditor editor)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null && ((ITextStyle)editor).TextColor != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.TextColor = ((ITextStyle)editor).TextColor.ToSKColor();
}
}
public static void MapTextColor(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
if (editor.TextColor is not null)
{
handler.PlatformView.TextColor = editor.TextColor.ToSKColor();
}
}
public static void MapCharacterSpacing(EditorHandler handler, IEditor editor)
{
}
public static void MapCharacterSpacing(EditorHandler handler, IEditor editor)
{
// Character spacing would require custom text rendering
}
public static void MapIsReadOnly(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.IsReadOnly = ((ITextInput)editor).IsReadOnly;
}
}
public static void MapIsReadOnly(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsReadOnly = editor.IsReadOnly;
}
public static void MapIsTextPredictionEnabled(EditorHandler handler, IEditor editor)
{
}
public static void MapIsTextPredictionEnabled(EditorHandler handler, IEditor editor)
{
// Text prediction not applicable to desktop
}
public static void MapMaxLength(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.MaxLength = ((ITextInput)editor).MaxLength;
}
}
public static void MapMaxLength(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaxLength = editor.MaxLength;
}
public static void MapCursorPosition(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.CursorPosition = ((ITextInput)editor).CursorPosition;
}
}
public static void MapCursorPosition(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CursorPosition = editor.CursorPosition;
}
public static void MapSelectionLength(EditorHandler handler, IEditor editor)
{
}
public static void MapSelectionLength(EditorHandler handler, IEditor editor)
{
// Selection would need to be added to SkiaEditor
}
public static void MapKeyboard(EditorHandler handler, IEditor editor)
{
}
public static void MapKeyboard(EditorHandler handler, IEditor editor)
{
// Virtual keyboard type not applicable to desktop
}
public static void MapHorizontalTextAlignment(EditorHandler handler, IEditor editor)
{
}
public static void MapHorizontalTextAlignment(EditorHandler handler, IEditor editor)
{
// Text alignment would require changes to SkiaEditor drawing
}
public static void MapVerticalTextAlignment(EditorHandler handler, IEditor editor)
{
}
public static void MapVerticalTextAlignment(EditorHandler handler, IEditor editor)
{
// Text alignment would require changes to SkiaEditor drawing
}
public static void MapBackground(EditorHandler handler, IEditor editor)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
Paint background = ((IView)editor).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapBackground(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
if (editor.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackgroundColor(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
if (editor is VisualElement ve && ve.BackgroundColor != null)
{
handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
handler.PlatformView.Invalidate();
}
}
public static void MapBackgroundColor(EditorHandler handler, IEditor editor)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
VisualElement val = (VisualElement)(object)((editor is VisualElement) ? editor : null);
if (val != null && val.BackgroundColor != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.BackgroundColor = val.BackgroundColor.ToSKColor();
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.Invalidate();
}
}
}
}

View File

@@ -1,215 +1,280 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Entry on Linux using Skia rendering.
/// Maps IEntry interface to SkiaEntry platform view.
/// </summary>
public partial class EntryHandler : ViewHandler<IEntry, SkiaEntry>
public class EntryHandler : ViewHandler<IEntry, SkiaEntry>
{
public static IPropertyMapper<IEntry, EntryHandler> Mapper = new PropertyMapper<IEntry, EntryHandler>(ViewHandler.ViewMapper)
{
[nameof(ITextInput.Text)] = MapText,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(ITextStyle.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IPlaceholder.Placeholder)] = MapPlaceholder,
[nameof(IPlaceholder.PlaceholderColor)] = MapPlaceholderColor,
[nameof(ITextInput.IsReadOnly)] = MapIsReadOnly,
[nameof(ITextInput.MaxLength)] = MapMaxLength,
[nameof(ITextInput.CursorPosition)] = MapCursorPosition,
[nameof(ITextInput.SelectionLength)] = MapSelectionLength,
[nameof(IEntry.IsPassword)] = MapIsPassword,
[nameof(IEntry.ReturnType)] = MapReturnType,
[nameof(IEntry.ClearButtonVisibility)] = MapClearButtonVisibility,
[nameof(ITextAlignment.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(ITextAlignment.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<IEntry, EntryHandler> Mapper = (IPropertyMapper<IEntry, EntryHandler>)(object)new PropertyMapper<IEntry, EntryHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Text"] = MapText,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["CharacterSpacing"] = MapCharacterSpacing,
["Placeholder"] = MapPlaceholder,
["PlaceholderColor"] = MapPlaceholderColor,
["IsReadOnly"] = MapIsReadOnly,
["MaxLength"] = MapMaxLength,
["CursorPosition"] = MapCursorPosition,
["SelectionLength"] = MapSelectionLength,
["IsPassword"] = MapIsPassword,
["ReturnType"] = MapReturnType,
["ClearButtonVisibility"] = MapClearButtonVisibility,
["HorizontalTextAlignment"] = MapHorizontalTextAlignment,
["VerticalTextAlignment"] = MapVerticalTextAlignment,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static CommandMapper<IEntry, EntryHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IEntry, EntryHandler> CommandMapper = new CommandMapper<IEntry, EntryHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public EntryHandler() : base(Mapper, CommandMapper)
{
}
public EntryHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public EntryHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public EntryHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaEntry CreatePlatformView()
{
return new SkiaEntry();
}
protected override SkiaEntry CreatePlatformView()
{
return new SkiaEntry();
}
protected override void ConnectHandler(SkiaEntry platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.Completed += OnCompleted;
}
protected override void ConnectHandler(SkiaEntry platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.Completed += OnCompleted;
}
protected override void DisconnectHandler(SkiaEntry platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.Completed -= OnCompleted;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaEntry platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.Completed -= OnCompleted;
base.DisconnectHandler(platformView);
}
private void OnTextChanged(object? sender, Platform.TextChangedEventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnTextChanged(object? sender, TextChangedEventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null && ((ITextInput)base.VirtualView).Text != e.NewTextValue)
{
((ITextInput)base.VirtualView).Text = e.NewTextValue ?? string.Empty;
}
}
if (VirtualView.Text != e.NewTextValue)
{
VirtualView.Text = e.NewTextValue ?? string.Empty;
}
}
private void OnCompleted(object? sender, EventArgs e)
{
IEntry virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Completed();
}
}
private void OnCompleted(object? sender, EventArgs e)
{
VirtualView?.Completed();
}
public static void MapText(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null && ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.Text != ((ITextInput)entry).Text)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.Text = ((ITextInput)entry).Text ?? string.Empty;
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapText(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
public static void MapTextColor(EntryHandler handler, IEntry entry)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null && ((ITextStyle)entry).TextColor != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.TextColor = ((ITextStyle)entry).TextColor.ToSKColor();
}
}
if (handler.PlatformView.Text != entry.Text)
{
handler.PlatformView.Text = entry.Text ?? string.Empty;
handler.PlatformView.Invalidate();
}
}
public static void MapFont(EntryHandler handler, IEntry entry)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Invalid comparison between Unknown and I4
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Invalid comparison between Unknown and I4
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Invalid comparison between Unknown and I4
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)entry).Font;
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.IsBold = (int)((Font)(ref font)).Weight >= 700;
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.IsItalic = (int)((Font)(ref font)).Slant == 1 || (int)((Font)(ref font)).Slant == 2;
}
}
public static void MapTextColor(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
public static void MapCharacterSpacing(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.CharacterSpacing = (float)((ITextStyle)entry).CharacterSpacing;
}
}
if (entry.TextColor is not null)
handler.PlatformView.TextColor = entry.TextColor.ToSKColor();
}
public static void MapPlaceholder(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.Placeholder = ((IPlaceholder)entry).Placeholder ?? string.Empty;
}
}
public static void MapFont(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
public static void MapPlaceholderColor(EntryHandler handler, IEntry entry)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null && ((IPlaceholder)entry).PlaceholderColor != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.PlaceholderColor = ((IPlaceholder)entry).PlaceholderColor.ToSKColor();
}
}
var font = entry.Font;
if (font.Size > 0)
handler.PlatformView.FontSize = (float)font.Size;
public static void MapIsReadOnly(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.IsReadOnly = ((ITextInput)entry).IsReadOnly;
}
}
if (!string.IsNullOrEmpty(font.Family))
handler.PlatformView.FontFamily = font.Family;
public static void MapMaxLength(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.MaxLength = ((ITextInput)entry).MaxLength;
}
}
handler.PlatformView.IsBold = font.Weight >= FontWeight.Bold;
handler.PlatformView.IsItalic = font.Slant == FontSlant.Italic || font.Slant == FontSlant.Oblique;
}
public static void MapCursorPosition(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.CursorPosition = ((ITextInput)entry).CursorPosition;
}
}
public static void MapCharacterSpacing(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CharacterSpacing = (float)entry.CharacterSpacing;
}
public static void MapSelectionLength(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.SelectionLength = ((ITextInput)entry).SelectionLength;
}
}
public static void MapPlaceholder(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Placeholder = entry.Placeholder ?? string.Empty;
}
public static void MapIsPassword(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.IsPassword = entry.IsPassword;
}
}
public static void MapPlaceholderColor(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
public static void MapReturnType(EntryHandler handler, IEntry entry)
{
_ = ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView;
}
if (entry.PlaceholderColor is not null)
handler.PlatformView.PlaceholderColor = entry.PlaceholderColor.ToSKColor();
}
public static void MapClearButtonVisibility(EntryHandler handler, IEntry entry)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Invalid comparison between Unknown and I4
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.ShowClearButton = (int)entry.ClearButtonVisibility == 1;
}
}
public static void MapIsReadOnly(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsReadOnly = entry.IsReadOnly;
}
public static void MapHorizontalTextAlignment(EntryHandler handler, IEntry entry)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
SkiaEntry platformView = ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView;
TextAlignment horizontalTextAlignment = ((ITextAlignment)entry).HorizontalTextAlignment;
platformView.HorizontalTextAlignment = (int)horizontalTextAlignment switch
{
0 => TextAlignment.Start,
1 => TextAlignment.Center,
2 => TextAlignment.End,
_ => TextAlignment.Start,
};
}
}
public static void MapMaxLength(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaxLength = entry.MaxLength;
}
public static void MapVerticalTextAlignment(EntryHandler handler, IEntry entry)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
SkiaEntry platformView = ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView;
TextAlignment verticalTextAlignment = ((ITextAlignment)entry).VerticalTextAlignment;
platformView.VerticalTextAlignment = (int)verticalTextAlignment switch
{
0 => TextAlignment.Start,
1 => TextAlignment.Center,
2 => TextAlignment.End,
_ => TextAlignment.Center,
};
}
}
public static void MapCursorPosition(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CursorPosition = entry.CursorPosition;
}
public static void MapBackground(EntryHandler handler, IEntry entry)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
Paint background = ((IView)entry).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapSelectionLength(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.SelectionLength = entry.SelectionLength;
}
public static void MapIsPassword(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsPassword = entry.IsPassword;
}
public static void MapReturnType(EntryHandler handler, IEntry entry)
{
// ReturnType affects keyboard behavior - stored for virtual keyboard integration
if (handler.PlatformView is null) return;
// handler.PlatformView.ReturnType = entry.ReturnType; // Would need property on SkiaEntry
}
public static void MapClearButtonVisibility(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.ShowClearButton = entry.ClearButtonVisibility == ClearButtonVisibility.WhileEditing;
}
public static void MapHorizontalTextAlignment(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalTextAlignment = entry.HorizontalTextAlignment switch
{
Microsoft.Maui.TextAlignment.Start => Platform.TextAlignment.Start,
Microsoft.Maui.TextAlignment.Center => Platform.TextAlignment.Center,
Microsoft.Maui.TextAlignment.End => Platform.TextAlignment.End,
_ => Platform.TextAlignment.Start
};
}
public static void MapVerticalTextAlignment(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalTextAlignment = entry.VerticalTextAlignment switch
{
Microsoft.Maui.TextAlignment.Start => Platform.TextAlignment.Start,
Microsoft.Maui.TextAlignment.Center => Platform.TextAlignment.Center,
Microsoft.Maui.TextAlignment.End => Platform.TextAlignment.End,
_ => Platform.TextAlignment.Center
};
}
public static void MapBackground(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
if (entry.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackgroundColor(EntryHandler handler, IEntry entry)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView == null)
{
return;
}
Entry val = (Entry)(object)((entry is Entry) ? entry : null);
if (val != null)
{
Console.WriteLine($"[EntryHandler] MapBackgroundColor: {((VisualElement)val).BackgroundColor}");
if (((VisualElement)val).BackgroundColor != null)
{
SKColor val2 = ((VisualElement)val).BackgroundColor.ToSKColor();
Console.WriteLine($"[EntryHandler] Setting EntryBackgroundColor to: {val2}");
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.EntryBackgroundColor = val2;
}
}
}
}

View File

@@ -0,0 +1,139 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Layouts;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class FlexLayoutHandler : LayoutHandler
{
public new static IPropertyMapper<FlexLayout, FlexLayoutHandler> Mapper = (IPropertyMapper<FlexLayout, FlexLayoutHandler>)(object)new PropertyMapper<FlexLayout, FlexLayoutHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)LayoutHandler.Mapper })
{
["Direction"] = MapDirection,
["Wrap"] = MapWrap,
["JustifyContent"] = MapJustifyContent,
["AlignItems"] = MapAlignItems,
["AlignContent"] = MapAlignContent
};
public FlexLayoutHandler()
: base((IPropertyMapper?)(object)Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaFlexLayout();
}
public static void MapDirection(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexDirection direction = layout.Direction;
skiaFlexLayout2.Direction = (int)direction switch
{
0 => FlexDirection.Row,
1 => FlexDirection.RowReverse,
2 => FlexDirection.Column,
3 => FlexDirection.ColumnReverse,
_ => FlexDirection.Row,
};
}
}
public static void MapWrap(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexWrap wrap = layout.Wrap;
skiaFlexLayout2.Wrap = (int)wrap switch
{
0 => FlexWrap.NoWrap,
1 => FlexWrap.Wrap,
2 => FlexWrap.WrapReverse,
_ => FlexWrap.NoWrap,
};
}
}
public static void MapJustifyContent(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexJustify justifyContent = layout.JustifyContent;
skiaFlexLayout2.JustifyContent = (justifyContent - 2) switch
{
1 => FlexJustify.Start,
0 => FlexJustify.Center,
2 => FlexJustify.End,
3 => FlexJustify.SpaceBetween,
4 => FlexJustify.SpaceAround,
5 => FlexJustify.SpaceEvenly,
_ => FlexJustify.Start,
};
}
}
public static void MapAlignItems(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexAlignItems alignItems = layout.AlignItems;
skiaFlexLayout2.AlignItems = (alignItems - 1) switch
{
2 => FlexAlignItems.Start,
1 => FlexAlignItems.Center,
3 => FlexAlignItems.End,
0 => FlexAlignItems.Stretch,
_ => FlexAlignItems.Stretch,
};
}
}
public static void MapAlignContent(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexAlignContent alignContent = layout.AlignContent;
skiaFlexLayout2.AlignContent = (alignContent - 1) switch
{
2 => FlexAlignContent.Start,
1 => FlexAlignContent.Center,
3 => FlexAlignContent.End,
0 => FlexAlignContent.Stretch,
4 => FlexAlignContent.SpaceBetween,
5 => FlexAlignContent.SpaceAround,
6 => FlexAlignContent.SpaceAround,
_ => FlexAlignContent.Stretch,
};
}
}
}

View File

@@ -1,91 +1,94 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for FlyoutPage on Linux using Skia rendering.
/// Maps IFlyoutView interface to SkiaFlyoutPage platform view.
/// </summary>
public partial class FlyoutPageHandler : ViewHandler<IFlyoutView, SkiaFlyoutPage>
public class FlyoutPageHandler : ViewHandler<IFlyoutView, SkiaFlyoutPage>
{
public static IPropertyMapper<IFlyoutView, FlyoutPageHandler> Mapper = new PropertyMapper<IFlyoutView, FlyoutPageHandler>(ViewHandler.ViewMapper)
{
[nameof(IFlyoutView.IsPresented)] = MapIsPresented,
[nameof(IFlyoutView.FlyoutWidth)] = MapFlyoutWidth,
[nameof(IFlyoutView.IsGestureEnabled)] = MapIsGestureEnabled,
[nameof(IFlyoutView.FlyoutBehavior)] = MapFlyoutBehavior,
};
public static IPropertyMapper<IFlyoutView, FlyoutPageHandler> Mapper = (IPropertyMapper<IFlyoutView, FlyoutPageHandler>)(object)new PropertyMapper<IFlyoutView, FlyoutPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsPresented"] = MapIsPresented,
["FlyoutWidth"] = MapFlyoutWidth,
["IsGestureEnabled"] = MapIsGestureEnabled,
["FlyoutBehavior"] = MapFlyoutBehavior
};
public static CommandMapper<IFlyoutView, FlyoutPageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IFlyoutView, FlyoutPageHandler> CommandMapper = new CommandMapper<IFlyoutView, FlyoutPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public FlyoutPageHandler() : base(Mapper, CommandMapper)
{
}
public FlyoutPageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public FlyoutPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public FlyoutPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaFlyoutPage CreatePlatformView()
{
return new SkiaFlyoutPage();
}
protected override SkiaFlyoutPage CreatePlatformView()
{
return new SkiaFlyoutPage();
}
protected override void ConnectHandler(SkiaFlyoutPage platformView)
{
base.ConnectHandler(platformView);
platformView.IsPresentedChanged += OnIsPresentedChanged;
}
protected override void ConnectHandler(SkiaFlyoutPage platformView)
{
base.ConnectHandler(platformView);
platformView.IsPresentedChanged += OnIsPresentedChanged;
}
protected override void DisconnectHandler(SkiaFlyoutPage platformView)
{
platformView.IsPresentedChanged -= OnIsPresentedChanged;
platformView.Flyout = null;
platformView.Detail = null;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaFlyoutPage platformView)
{
platformView.IsPresentedChanged -= OnIsPresentedChanged;
platformView.Flyout = null;
platformView.Detail = null;
base.DisconnectHandler(platformView);
}
private void OnIsPresentedChanged(object? sender, EventArgs e)
{
// Sync back to the virtual view
}
private void OnIsPresentedChanged(object? sender, EventArgs e)
{
}
public static void MapIsPresented(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsPresented = flyoutView.IsPresented;
}
public static void MapIsPresented(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView != null)
{
((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView.IsPresented = flyoutView.IsPresented;
}
}
public static void MapFlyoutWidth(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.FlyoutWidth = (float)flyoutView.FlyoutWidth;
}
public static void MapFlyoutWidth(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView != null)
{
((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView.FlyoutWidth = (float)flyoutView.FlyoutWidth;
}
}
public static void MapIsGestureEnabled(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.GestureEnabled = flyoutView.IsGestureEnabled;
}
public static void MapIsGestureEnabled(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView != null)
{
((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView.GestureEnabled = flyoutView.IsGestureEnabled;
}
}
public static void MapFlyoutBehavior(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.FlyoutLayoutBehavior = flyoutView.FlyoutBehavior switch
{
Microsoft.Maui.FlyoutBehavior.Disabled => FlyoutLayoutBehavior.Default,
Microsoft.Maui.FlyoutBehavior.Flyout => FlyoutLayoutBehavior.Popover,
Microsoft.Maui.FlyoutBehavior.Locked => FlyoutLayoutBehavior.Split,
_ => FlyoutLayoutBehavior.Default
};
}
public static void MapFlyoutBehavior(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView != null)
{
SkiaFlyoutPage platformView = ((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView;
FlyoutBehavior flyoutBehavior = flyoutView.FlyoutBehavior;
platformView.FlyoutLayoutBehavior = (int)flyoutBehavior switch
{
0 => FlyoutLayoutBehavior.Default,
1 => FlyoutLayoutBehavior.Popover,
2 => FlyoutLayoutBehavior.Split,
_ => FlyoutLayoutBehavior.Default,
};
}
}
}

View File

@@ -1,104 +1,134 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Compatibility;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Frame on Linux using SkiaFrame.
/// </summary>
public partial class FrameHandler : ViewHandler<Frame, SkiaFrame>
public class FrameHandler : ViewHandler<Frame, SkiaFrame>
{
public static IPropertyMapper<Frame, FrameHandler> Mapper =
new PropertyMapper<Frame, FrameHandler>(ViewMapper)
{
[nameof(Frame.BorderColor)] = MapBorderColor,
[nameof(Frame.CornerRadius)] = MapCornerRadius,
[nameof(Frame.HasShadow)] = MapHasShadow,
[nameof(Frame.BackgroundColor)] = MapBackgroundColor,
[nameof(Frame.Padding)] = MapPadding,
[nameof(Frame.Content)] = MapContent,
};
public static IPropertyMapper<Frame, FrameHandler> Mapper = (IPropertyMapper<Frame, FrameHandler>)(object)new PropertyMapper<Frame, FrameHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["BorderColor"] = MapBorderColor,
["CornerRadius"] = MapCornerRadius,
["HasShadow"] = MapHasShadow,
["BackgroundColor"] = MapBackgroundColor,
["Padding"] = MapPadding,
["Content"] = MapContent
};
public FrameHandler() : base(Mapper)
{
}
public FrameHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)null)
{
}
public FrameHandler(IPropertyMapper? mapper)
: base(mapper ?? Mapper)
{
}
public FrameHandler(IPropertyMapper? mapper)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)null)
{
}
protected override SkiaFrame CreatePlatformView()
{
return new SkiaFrame();
}
protected override SkiaFrame CreatePlatformView()
{
return new SkiaFrame();
}
public static void MapBorderColor(FrameHandler handler, Frame frame)
{
if (frame.BorderColor != null)
{
handler.PlatformView.Stroke = new SKColor(
(byte)(frame.BorderColor.Red * 255),
(byte)(frame.BorderColor.Green * 255),
(byte)(frame.BorderColor.Blue * 255),
(byte)(frame.BorderColor.Alpha * 255));
}
}
protected override void ConnectHandler(SkiaFrame platformView)
{
base.ConnectHandler(platformView);
View virtualView = (View)(object)base.VirtualView;
if (virtualView != null)
{
platformView.MauiView = virtualView;
}
platformView.Tapped += OnPlatformViewTapped;
}
public static void MapCornerRadius(FrameHandler handler, Frame frame)
{
handler.PlatformView.CornerRadius = frame.CornerRadius;
}
protected override void DisconnectHandler(SkiaFrame platformView)
{
platformView.Tapped -= OnPlatformViewTapped;
platformView.MauiView = null;
base.DisconnectHandler(platformView);
}
public static void MapHasShadow(FrameHandler handler, Frame frame)
{
handler.PlatformView.HasShadow = frame.HasShadow;
}
private void OnPlatformViewTapped(object? sender, EventArgs e)
{
View virtualView = (View)(object)base.VirtualView;
if (virtualView != null)
{
GestureManager.ProcessTap(virtualView, 0.0, 0.0);
}
}
public static void MapBackgroundColor(FrameHandler handler, Frame frame)
{
if (frame.BackgroundColor != null)
{
handler.PlatformView.BackgroundColor = new SKColor(
(byte)(frame.BackgroundColor.Red * 255),
(byte)(frame.BackgroundColor.Green * 255),
(byte)(frame.BackgroundColor.Blue * 255),
(byte)(frame.BackgroundColor.Alpha * 255));
}
}
public static void MapBorderColor(FrameHandler handler, Frame frame)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (frame.BorderColor != null)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.Stroke = new SKColor((byte)(frame.BorderColor.Red * 255f), (byte)(frame.BorderColor.Green * 255f), (byte)(frame.BorderColor.Blue * 255f), (byte)(frame.BorderColor.Alpha * 255f));
}
}
public static void MapPadding(FrameHandler handler, Frame frame)
{
handler.PlatformView.SetPadding(
(float)frame.Padding.Left,
(float)frame.Padding.Top,
(float)frame.Padding.Right,
(float)frame.Padding.Bottom);
}
public static void MapCornerRadius(FrameHandler handler, Frame frame)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.CornerRadius = frame.CornerRadius;
}
public static void MapContent(FrameHandler handler, Frame frame)
{
if (handler.PlatformView is null || handler.MauiContext is null) return;
public static void MapHasShadow(FrameHandler handler, Frame frame)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.HasShadow = frame.HasShadow;
}
handler.PlatformView.ClearChildren();
public static void MapBackgroundColor(FrameHandler handler, Frame frame)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (((VisualElement)frame).BackgroundColor != null)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.BackgroundColor = new SKColor((byte)(((VisualElement)frame).BackgroundColor.Red * 255f), (byte)(((VisualElement)frame).BackgroundColor.Green * 255f), (byte)(((VisualElement)frame).BackgroundColor.Blue * 255f), (byte)(((VisualElement)frame).BackgroundColor.Alpha * 255f));
}
}
var content = frame.Content;
if (content != null)
{
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
content.Handler = content.ToHandler(handler.MauiContext);
}
public static void MapPadding(FrameHandler handler, Frame frame)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
SkiaFrame platformView = ((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView;
Thickness padding = ((Layout)frame).Padding;
float left = (float)((Thickness)(ref padding)).Left;
padding = ((Layout)frame).Padding;
float top = (float)((Thickness)(ref padding)).Top;
padding = ((Layout)frame).Padding;
float right = (float)((Thickness)(ref padding)).Right;
padding = ((Layout)frame).Padding;
platformView.SetPadding(left, top, right, (float)((Thickness)(ref padding)).Bottom);
}
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
handler.PlatformView.AddChild(skiaContent);
}
}
}
public static void MapContent(FrameHandler handler, Frame frame)
{
if (((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.ClearChildren();
View content = ((ContentView)frame).Content;
if (content != null)
{
if (((VisualElement)content).Handler == null)
{
((VisualElement)content).Handler = ((IView)(object)content).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = ((VisualElement)content).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView child)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.AddChild(child);
}
}
}
}

547
Handlers/GestureManager.cs Normal file
View File

@@ -0,0 +1,547 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Input;
using Microsoft.Maui.Controls;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public static class GestureManager
{
private class GestureTrackingState
{
public double StartX { get; set; }
public double StartY { get; set; }
public double CurrentX { get; set; }
public double CurrentY { get; set; }
public DateTime StartTime { get; set; }
public bool IsPanning { get; set; }
public bool IsPressed { get; set; }
}
private enum PointerEventType
{
Entered,
Exited,
Pressed,
Moved,
Released
}
private static MethodInfo? _sendTappedMethod;
private static readonly Dictionary<View, (DateTime lastTap, int tapCount)> _tapTracking = new Dictionary<View, (DateTime, int)>();
private static readonly Dictionary<View, GestureTrackingState> _gestureState = new Dictionary<View, GestureTrackingState>();
private const double SwipeMinDistance = 50.0;
private const double SwipeMaxTime = 500.0;
private const double SwipeDirectionThreshold = 0.5;
private const double PanMinDistance = 10.0;
public static bool ProcessTap(View? view, double x, double y)
{
if (view == null)
{
return false;
}
View val = view;
while (val != null)
{
IList<IGestureRecognizer> gestureRecognizers = val.GestureRecognizers;
if (gestureRecognizers != null && gestureRecognizers.Count > 0 && ProcessTapOnView(val, x, y))
{
return true;
}
Element parent = ((Element)val).Parent;
val = (View)(object)((parent is View) ? parent : null);
}
return false;
}
private static bool ProcessTapOnView(View view, double x, double y)
{
//IL_031f: Unknown result type (might be due to invalid IL or missing references)
//IL_0326: Expected O, but got Unknown
//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
//IL_03d2: Expected O, but got Unknown
//IL_026e: Unknown result type (might be due to invalid IL or missing references)
//IL_0275: Expected O, but got Unknown
IList<IGestureRecognizer> gestureRecognizers = view.GestureRecognizers;
if (gestureRecognizers == null || gestureRecognizers.Count == 0)
{
return false;
}
bool result = false;
foreach (IGestureRecognizer item in gestureRecognizers)
{
TapGestureRecognizer val = (TapGestureRecognizer)(object)((item is TapGestureRecognizer) ? item : null);
if (val == null)
{
continue;
}
Console.WriteLine($"[GestureManager] Processing TapGestureRecognizer on {((object)view).GetType().Name}, CommandParameter={val.CommandParameter}, NumberOfTapsRequired={val.NumberOfTapsRequired}");
int numberOfTapsRequired = val.NumberOfTapsRequired;
if (numberOfTapsRequired > 1)
{
DateTime utcNow = DateTime.UtcNow;
if (!_tapTracking.TryGetValue(view, out (DateTime, int) value))
{
_tapTracking[view] = (utcNow, 1);
Console.WriteLine($"[GestureManager] First tap 1/{numberOfTapsRequired}");
continue;
}
if (!((utcNow - value.Item1).TotalMilliseconds < 300.0))
{
_tapTracking[view] = (utcNow, 1);
Console.WriteLine($"[GestureManager] Tap timeout, reset to 1/{numberOfTapsRequired}");
continue;
}
int num = value.Item2 + 1;
if (num < numberOfTapsRequired)
{
_tapTracking[view] = (utcNow, num);
Console.WriteLine($"[GestureManager] Tap {num}/{numberOfTapsRequired}, waiting for more taps");
continue;
}
_tapTracking.Remove(view);
}
bool flag = false;
try
{
if ((object)_sendTappedMethod == null)
{
_sendTappedMethod = typeof(TapGestureRecognizer).GetMethod("SendTapped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (_sendTappedMethod != null)
{
Console.WriteLine($"[GestureManager] Found SendTapped method with {_sendTappedMethod.GetParameters().Length} params");
TappedEventArgs e = new TappedEventArgs(val.CommandParameter);
_sendTappedMethod.Invoke(val, new object[2] { view, e });
Console.WriteLine("[GestureManager] SendTapped invoked successfully");
flag = true;
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendTapped failed: " + ex.Message);
}
if (!flag)
{
try
{
FieldInfo fieldInfo = typeof(TapGestureRecognizer).GetField("Tapped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(TapGestureRecognizer).GetField("_tapped", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo != null && fieldInfo.GetValue(val) is EventHandler<TappedEventArgs> eventHandler)
{
Console.WriteLine("[GestureManager] Invoking Tapped event directly");
TappedEventArgs e2 = new TappedEventArgs(val.CommandParameter);
eventHandler(val, e2);
flag = true;
}
}
catch (Exception ex2)
{
Console.WriteLine("[GestureManager] Direct event invoke failed: " + ex2.Message);
}
}
if (!flag)
{
try
{
string[] array = new string[3] { "TappedEvent", "_TappedHandler", "<Tapped>k__BackingField" };
foreach (string text in array)
{
FieldInfo field = typeof(TapGestureRecognizer).GetField(text, BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
Console.WriteLine("[GestureManager] Found field: " + text);
if (field.GetValue(val) is EventHandler<TappedEventArgs> eventHandler2)
{
TappedEventArgs e3 = new TappedEventArgs(val.CommandParameter);
eventHandler2(val, e3);
Console.WriteLine("[GestureManager] Event fired via " + text);
flag = true;
break;
}
}
}
}
catch (Exception ex3)
{
Console.WriteLine("[GestureManager] Backing field approach failed: " + ex3.Message);
}
}
if (!flag)
{
Console.WriteLine("[GestureManager] Could not fire event, dumping type info...");
MethodInfo[] methods = typeof(TapGestureRecognizer).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
if (methodInfo.Name.Contains("Tap", StringComparison.OrdinalIgnoreCase) || methodInfo.Name.Contains("Send", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[GestureManager] Method: {methodInfo.Name}({string.Join(", ", from p in methodInfo.GetParameters()
select p.ParameterType.Name)})");
}
}
}
ICommand command = val.Command;
if (command != null && command.CanExecute(val.CommandParameter))
{
Console.WriteLine("[GestureManager] Executing Command");
val.Command.Execute(val.CommandParameter);
}
result = true;
}
return result;
}
public static bool HasGestureRecognizers(View? view)
{
if (view == null)
{
return false;
}
return view.GestureRecognizers?.Count > 0;
}
public static bool HasTapGestureRecognizer(View? view)
{
if (((view != null) ? view.GestureRecognizers : null) == null)
{
return false;
}
foreach (IGestureRecognizer gestureRecognizer in view.GestureRecognizers)
{
if (gestureRecognizer is TapGestureRecognizer)
{
return true;
}
}
return false;
}
public static void ProcessPointerDown(View? view, double x, double y)
{
if (view != null)
{
_gestureState[view] = new GestureTrackingState
{
StartX = x,
StartY = y,
CurrentX = x,
CurrentY = y,
StartTime = DateTime.UtcNow,
IsPanning = false,
IsPressed = true
};
ProcessPointerEvent(view, x, y, PointerEventType.Pressed);
}
}
public static void ProcessPointerMove(View? view, double x, double y)
{
if (view == null)
{
return;
}
if (!_gestureState.TryGetValue(view, out GestureTrackingState value))
{
ProcessPointerEvent(view, x, y, PointerEventType.Moved);
return;
}
value.CurrentX = x;
value.CurrentY = y;
if (!value.IsPressed)
{
ProcessPointerEvent(view, x, y, PointerEventType.Moved);
return;
}
double num = x - value.StartX;
double num2 = y - value.StartY;
if (Math.Sqrt(num * num + num2 * num2) >= 10.0)
{
ProcessPanGesture(view, num, num2, (GestureStatus)(value.IsPanning ? 1 : 0));
value.IsPanning = true;
}
ProcessPointerEvent(view, x, y, PointerEventType.Moved);
}
public static void ProcessPointerUp(View? view, double x, double y)
{
if (view == null)
{
return;
}
if (_gestureState.TryGetValue(view, out GestureTrackingState value))
{
value.CurrentX = x;
value.CurrentY = y;
double num = x - value.StartX;
double num2 = y - value.StartY;
double num3 = Math.Sqrt(num * num + num2 * num2);
double totalMilliseconds = (DateTime.UtcNow - value.StartTime).TotalMilliseconds;
if (num3 >= 50.0 && totalMilliseconds <= 500.0)
{
SwipeDirection swipeDirection = DetermineSwipeDirection(num, num2);
if (swipeDirection != SwipeDirection.Right)
{
ProcessSwipeGesture(view, swipeDirection);
}
else if (Math.Abs(num) > Math.Abs(num2) * 0.5)
{
ProcessSwipeGesture(view, (!(num > 0.0)) ? SwipeDirection.Left : SwipeDirection.Right);
}
}
if (value.IsPanning)
{
ProcessPanGesture(view, num, num2, (GestureStatus)2);
}
else if (num3 < 15.0 && totalMilliseconds < 500.0)
{
Console.WriteLine($"[GestureManager] Detected tap on {((object)view).GetType().Name} (distance={num3:F1}, elapsed={totalMilliseconds:F0}ms)");
ProcessTap(view, x, y);
}
_gestureState.Remove(view);
}
ProcessPointerEvent(view, x, y, PointerEventType.Released);
}
public static void ProcessPointerEntered(View? view, double x, double y)
{
if (view != null)
{
ProcessPointerEvent(view, x, y, PointerEventType.Entered);
}
}
public static void ProcessPointerExited(View? view, double x, double y)
{
if (view != null)
{
ProcessPointerEvent(view, x, y, PointerEventType.Exited);
}
}
private static SwipeDirection DetermineSwipeDirection(double deltaX, double deltaY)
{
double num = Math.Abs(deltaX);
double num2 = Math.Abs(deltaY);
if (num > num2 * 0.5)
{
if (!(deltaX > 0.0))
{
return SwipeDirection.Left;
}
return SwipeDirection.Right;
}
if (num2 > num * 0.5)
{
if (!(deltaY > 0.0))
{
return SwipeDirection.Up;
}
return SwipeDirection.Down;
}
if (!(deltaX > 0.0))
{
return SwipeDirection.Left;
}
return SwipeDirection.Right;
}
private static void ProcessSwipeGesture(View view, SwipeDirection direction)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
IList<IGestureRecognizer> gestureRecognizers = view.GestureRecognizers;
if (gestureRecognizers == null)
{
return;
}
foreach (IGestureRecognizer item in gestureRecognizers)
{
SwipeGestureRecognizer val = (SwipeGestureRecognizer)(object)((item is SwipeGestureRecognizer) ? item : null);
if (val == null || !((Enum)val.Direction).HasFlag((Enum)direction))
{
continue;
}
Console.WriteLine($"[GestureManager] Swipe detected: {direction}");
try
{
MethodInfo method = typeof(SwipeGestureRecognizer).GetMethod("SendSwiped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(val, new object[2] { view, direction });
Console.WriteLine("[GestureManager] SendSwiped invoked successfully");
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendSwiped failed: " + ex.Message);
}
ICommand command = val.Command;
if (command != null && command.CanExecute(val.CommandParameter))
{
val.Command.Execute(val.CommandParameter);
}
}
}
private static void ProcessPanGesture(View view, double totalX, double totalY, GestureStatus status)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Expected I4, but got Unknown
IList<IGestureRecognizer> gestureRecognizers = view.GestureRecognizers;
if (gestureRecognizers == null)
{
return;
}
foreach (IGestureRecognizer item in gestureRecognizers)
{
PanGestureRecognizer val = (PanGestureRecognizer)(object)((item is PanGestureRecognizer) ? item : null);
if (val == null)
{
continue;
}
Console.WriteLine($"[GestureManager] Pan gesture: status={status}, totalX={totalX:F1}, totalY={totalY:F1}");
try
{
MethodInfo method = typeof(PanGestureRecognizer).GetMethod("SendPan", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(val, new object[4]
{
view,
totalX,
totalY,
(int)status
});
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendPan failed: " + ex.Message);
}
}
}
private static void ProcessPointerEvent(View view, double x, double y, PointerEventType eventType)
{
IList<IGestureRecognizer> gestureRecognizers = view.GestureRecognizers;
if (gestureRecognizers == null)
{
return;
}
foreach (IGestureRecognizer item in gestureRecognizers)
{
PointerGestureRecognizer val = (PointerGestureRecognizer)(object)((item is PointerGestureRecognizer) ? item : null);
if (val == null)
{
continue;
}
try
{
string text = eventType switch
{
PointerEventType.Entered => "SendPointerEntered",
PointerEventType.Exited => "SendPointerExited",
PointerEventType.Pressed => "SendPointerPressed",
PointerEventType.Moved => "SendPointerMoved",
PointerEventType.Released => "SendPointerReleased",
_ => null,
};
if (text != null)
{
MethodInfo method = typeof(PointerGestureRecognizer).GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
object obj = CreatePointerEventArgs(view, x, y);
method.Invoke(val, new object[2] { view, obj });
}
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] Pointer event failed: " + ex.Message);
}
}
}
private static object CreatePointerEventArgs(View view, double x, double y)
{
try
{
Type type = typeof(PointerGestureRecognizer).Assembly.GetType("Microsoft.Maui.Controls.PointerEventArgs");
if (type != null)
{
ConstructorInfo constructorInfo = type.GetConstructors().FirstOrDefault();
if (constructorInfo != null)
{
return constructorInfo.Invoke(new object[0]);
}
}
}
catch
{
}
return null;
}
public static bool HasSwipeGestureRecognizer(View? view)
{
if (((view != null) ? view.GestureRecognizers : null) == null)
{
return false;
}
foreach (IGestureRecognizer gestureRecognizer in view.GestureRecognizers)
{
if (gestureRecognizer is SwipeGestureRecognizer)
{
return true;
}
}
return false;
}
public static bool HasPanGestureRecognizer(View? view)
{
if (((view != null) ? view.GestureRecognizers : null) == null)
{
return false;
}
foreach (IGestureRecognizer gestureRecognizer in view.GestureRecognizers)
{
if (gestureRecognizer is PanGestureRecognizer)
{
return true;
}
}
return false;
}
public static bool HasPointerGestureRecognizer(View? view)
{
if (((view != null) ? view.GestureRecognizers : null) == null)
{
return false;
}
foreach (IGestureRecognizer gestureRecognizer in view.GestureRecognizers)
{
if (gestureRecognizer is PointerGestureRecognizer)
{
return true;
}
}
return false;
}
}

View File

@@ -1,62 +1,57 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for GraphicsView on Linux using Skia rendering.
/// Maps IGraphicsView interface to SkiaGraphicsView platform view.
/// IGraphicsView has: Drawable, Invalidate()
/// </summary>
public partial class GraphicsViewHandler : ViewHandler<IGraphicsView, SkiaGraphicsView>
public class GraphicsViewHandler : ViewHandler<IGraphicsView, SkiaGraphicsView>
{
public static IPropertyMapper<IGraphicsView, GraphicsViewHandler> Mapper = new PropertyMapper<IGraphicsView, GraphicsViewHandler>(ViewHandler.ViewMapper)
{
[nameof(IGraphicsView.Drawable)] = MapDrawable,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<IGraphicsView, GraphicsViewHandler> Mapper = (IPropertyMapper<IGraphicsView, GraphicsViewHandler>)(object)new PropertyMapper<IGraphicsView, GraphicsViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Drawable"] = MapDrawable,
["Background"] = MapBackground
};
public static CommandMapper<IGraphicsView, GraphicsViewHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
[nameof(IGraphicsView.Invalidate)] = MapInvalidate,
};
public static CommandMapper<IGraphicsView, GraphicsViewHandler> CommandMapper = new CommandMapper<IGraphicsView, GraphicsViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["Invalidate"] = MapInvalidate };
public GraphicsViewHandler() : base(Mapper, CommandMapper)
{
}
public GraphicsViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public GraphicsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public GraphicsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaGraphicsView CreatePlatformView()
{
return new SkiaGraphicsView();
}
protected override SkiaGraphicsView CreatePlatformView()
{
return new SkiaGraphicsView();
}
public static void MapDrawable(GraphicsViewHandler handler, IGraphicsView graphicsView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Drawable = graphicsView.Drawable;
}
public static void MapDrawable(GraphicsViewHandler handler, IGraphicsView graphicsView)
{
if (((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView != null)
{
((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView.Drawable = graphicsView.Drawable;
}
}
public static void MapBackground(GraphicsViewHandler handler, IGraphicsView graphicsView)
{
if (handler.PlatformView is null) return;
public static void MapBackground(GraphicsViewHandler handler, IGraphicsView graphicsView)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView != null)
{
Paint background = ((IView)graphicsView).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (graphicsView.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapInvalidate(GraphicsViewHandler handler, IGraphicsView graphicsView, object? args)
{
handler.PlatformView?.Invalidate();
}
public static void MapInvalidate(GraphicsViewHandler handler, IGraphicsView graphicsView, object? args)
{
((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView?.Invalidate();
}
}

170
Handlers/GridHandler.cs Normal file
View File

@@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class GridHandler : LayoutHandler
{
public new static IPropertyMapper<IGridLayout, GridHandler> Mapper = (IPropertyMapper<IGridLayout, GridHandler>)(object)new PropertyMapper<IGridLayout, GridHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)LayoutHandler.Mapper })
{
["RowSpacing"] = MapRowSpacing,
["ColumnSpacing"] = MapColumnSpacing,
["RowDefinitions"] = MapRowDefinitions,
["ColumnDefinitions"] = MapColumnDefinitions
};
public GridHandler()
: base((IPropertyMapper?)(object)Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaGrid();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
try
{
ILayout virtualView = ((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView;
IGridLayout val = (IGridLayout)(object)((virtualView is IGridLayout) ? virtualView : null);
if (val == null || ((ElementHandler)this).MauiContext == null || !(platformView is SkiaGrid skiaGrid))
{
return;
}
Console.WriteLine($"[GridHandler] ConnectHandler: {((ICollection<IView>)val).Count} children, {val.RowDefinitions.Count} rows, {val.ColumnDefinitions.Count} cols");
ILayout virtualView2 = ((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView;
VisualElement val2 = (VisualElement)(object)((virtualView2 is VisualElement) ? virtualView2 : null);
if (val2 != null && val2.BackgroundColor != null)
{
platformView.BackgroundColor = val2.BackgroundColor.ToSKColor();
}
IPadding virtualView3 = (IPadding)(object)((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView;
if (virtualView3 != null)
{
Thickness padding = virtualView3.Padding;
platformView.Padding = new SKRect((float)((Thickness)(ref padding)).Left, (float)((Thickness)(ref padding)).Top, (float)((Thickness)(ref padding)).Right, (float)((Thickness)(ref padding)).Bottom);
Console.WriteLine($"[GridHandler] Applied Padding: L={((Thickness)(ref padding)).Left}, T={((Thickness)(ref padding)).Top}, R={((Thickness)(ref padding)).Right}, B={((Thickness)(ref padding)).Bottom}");
}
MapRowDefinitions(this, val);
MapColumnDefinitions(this, val);
for (int i = 0; i < ((ICollection<IView>)val).Count; i++)
{
IView val3 = ((IList<IView>)val)[i];
if (val3 != null)
{
Console.WriteLine($"[GridHandler] Processing child {i}: {((object)val3).GetType().Name}");
if (val3.Handler == null)
{
val3.Handler = val3.ToViewHandler(((ElementHandler)this).MauiContext);
}
int num = 0;
int num2 = 0;
int rowSpan = 1;
int columnSpan = 1;
View val4 = (View)(object)((val3 is View) ? val3 : null);
if (val4 != null)
{
num = Grid.GetRow((BindableObject)(object)val4);
num2 = Grid.GetColumn((BindableObject)(object)val4);
rowSpan = Grid.GetRowSpan((BindableObject)(object)val4);
columnSpan = Grid.GetColumnSpan((BindableObject)(object)val4);
}
Console.WriteLine($"[GridHandler] Child {i} at row={num}, col={num2}, handler={((object)val3.Handler)?.GetType().Name}");
IViewHandler handler = val3.Handler;
if (((handler != null) ? ((IElementHandler)handler).PlatformView : null) is SkiaView child)
{
skiaGrid.AddChild(child, num, num2, rowSpan, columnSpan);
Console.WriteLine($"[GridHandler] Added child {i} to grid");
}
}
}
Console.WriteLine("[GridHandler] ConnectHandler complete");
}
catch (Exception ex)
{
Console.WriteLine("[GridHandler] EXCEPTION in ConnectHandler: " + ex.GetType().Name + ": " + ex.Message);
Console.WriteLine("[GridHandler] Stack trace: " + ex.StackTrace);
throw;
}
}
public static void MapRowSpacing(GridHandler handler, IGridLayout layout)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaGrid skiaGrid)
{
skiaGrid.RowSpacing = (float)layout.RowSpacing;
}
}
public static void MapColumnSpacing(GridHandler handler, IGridLayout layout)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaGrid skiaGrid)
{
skiaGrid.ColumnSpacing = (float)layout.ColumnSpacing;
}
}
public static void MapRowDefinitions(GridHandler handler, IGridLayout layout)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (!(((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaGrid skiaGrid))
{
return;
}
skiaGrid.RowDefinitions.Clear();
foreach (IGridRowDefinition rowDefinition in layout.RowDefinitions)
{
GridLength height = rowDefinition.Height;
if (((GridLength)(ref height)).IsAbsolute)
{
skiaGrid.RowDefinitions.Add(new GridLength((float)((GridLength)(ref height)).Value));
}
else if (((GridLength)(ref height)).IsAuto)
{
skiaGrid.RowDefinitions.Add(GridLength.Auto);
}
else
{
skiaGrid.RowDefinitions.Add(new GridLength((float)((GridLength)(ref height)).Value, GridUnitType.Star));
}
}
}
public static void MapColumnDefinitions(GridHandler handler, IGridLayout layout)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (!(((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaGrid skiaGrid))
{
return;
}
skiaGrid.ColumnDefinitions.Clear();
foreach (IGridColumnDefinition columnDefinition in layout.ColumnDefinitions)
{
GridLength width = columnDefinition.Width;
if (((GridLength)(ref width)).IsAbsolute)
{
skiaGrid.ColumnDefinitions.Add(new GridLength((float)((GridLength)(ref width)).Value));
}
else if (((GridLength)(ref width)).IsAuto)
{
skiaGrid.ColumnDefinitions.Add(GridLength.Auto);
}
else
{
skiaGrid.ColumnDefinitions.Add(new GridLength((float)((GridLength)(ref width)).Value, GridUnitType.Star));
}
}
}
}

View File

@@ -0,0 +1,240 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Native;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
{
private GtkWebViewPlatformView? _platformWebView;
private bool _isRegisteredWithHost;
private SKRect _lastBounds;
public static IPropertyMapper<IWebView, GtkWebViewHandler> Mapper = (IPropertyMapper<IWebView, GtkWebViewHandler>)(object)new PropertyMapper<IWebView, GtkWebViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper }) { ["Source"] = MapSource };
public static CommandMapper<IWebView, GtkWebViewHandler> CommandMapper = new CommandMapper<IWebView, GtkWebViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper)
{
["GoBack"] = MapGoBack,
["GoForward"] = MapGoForward,
["Reload"] = MapReload
};
public GtkWebViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public GtkWebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override GtkWebViewProxy CreatePlatformView()
{
_platformWebView = new GtkWebViewPlatformView();
return new GtkWebViewProxy(this, _platformWebView);
}
protected override void ConnectHandler(GtkWebViewProxy platformView)
{
base.ConnectHandler(platformView);
if (_platformWebView != null)
{
_platformWebView.NavigationStarted += OnNavigationStarted;
_platformWebView.NavigationCompleted += OnNavigationCompleted;
}
Console.WriteLine("[GtkWebViewHandler] ConnectHandler - WebView ready");
}
protected override void DisconnectHandler(GtkWebViewProxy platformView)
{
if (_platformWebView != null)
{
_platformWebView.NavigationStarted -= OnNavigationStarted;
_platformWebView.NavigationCompleted -= OnNavigationCompleted;
UnregisterFromHost();
_platformWebView.Dispose();
_platformWebView = null;
}
base.DisconnectHandler(platformView);
}
private void OnNavigationStarted(object? sender, string uri)
{
Console.WriteLine("[GtkWebViewHandler] Navigation started: " + uri);
try
{
GLibNative.IdleAdd(delegate
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
try
{
IWebView virtualView = base.VirtualView;
IWebViewController val = (IWebViewController)(object)((virtualView is IWebViewController) ? virtualView : null);
if (val != null)
{
WebNavigatingEventArgs e = new WebNavigatingEventArgs((WebNavigationEvent)3, (WebViewSource)null, uri);
val.SendNavigating(e);
Console.WriteLine("[GtkWebViewHandler] Sent Navigating event to VirtualView");
}
}
catch (Exception ex2)
{
Console.WriteLine("[GtkWebViewHandler] Error in SendNavigating: " + ex2.Message);
}
return false;
});
}
catch (Exception ex)
{
Console.WriteLine("[GtkWebViewHandler] Error dispatching navigation started: " + ex.Message);
}
}
private void OnNavigationCompleted(object? sender, (string Url, bool Success) e)
{
Console.WriteLine($"[GtkWebViewHandler] Navigation completed: {e.Url} (Success: {e.Success})");
try
{
GLibNative.IdleAdd(delegate
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
try
{
IWebView virtualView = base.VirtualView;
IWebViewController val = (IWebViewController)(object)((virtualView is IWebViewController) ? virtualView : null);
if (val != null)
{
WebNavigationResult val2 = (WebNavigationResult)(e.Success ? 1 : 4);
WebNavigatedEventArgs e2 = new WebNavigatedEventArgs((WebNavigationEvent)3, (WebViewSource)null, e.Url, val2);
val.SendNavigated(e2);
bool flag = _platformWebView?.CanGoBack() ?? false;
bool flag2 = _platformWebView?.CanGoForward() ?? false;
val.CanGoBack = flag;
val.CanGoForward = flag2;
Console.WriteLine($"[GtkWebViewHandler] Sent Navigated, CanGoBack={flag}, CanGoForward={flag2}");
}
}
catch (Exception ex2)
{
Console.WriteLine("[GtkWebViewHandler] Error in SendNavigated: " + ex2.Message);
}
return false;
});
}
catch (Exception ex)
{
Console.WriteLine("[GtkWebViewHandler] Error dispatching navigation completed: " + ex.Message);
}
}
internal void RegisterWithHost(SKRect bounds)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
if (_platformWebView == null)
{
return;
}
GtkHostService instance = GtkHostService.Instance;
if (instance.HostWindow == null || instance.WebViewManager == null)
{
Console.WriteLine("[GtkWebViewHandler] Warning: GTK host not initialized, cannot register WebView");
return;
}
int num = (int)((SKRect)(ref bounds)).Left;
int num2 = (int)((SKRect)(ref bounds)).Top;
int num3 = (int)((SKRect)(ref bounds)).Width;
int num4 = (int)((SKRect)(ref bounds)).Height;
if (num3 <= 0 || num4 <= 0)
{
Console.WriteLine($"[GtkWebViewHandler] Skipping invalid bounds: {bounds}");
return;
}
if (!_isRegisteredWithHost)
{
instance.HostWindow.AddWebView(_platformWebView.Widget, num, num2, num3, num4);
_isRegisteredWithHost = true;
Console.WriteLine($"[GtkWebViewHandler] Registered WebView at ({num}, {num2}) size {num3}x{num4}");
}
else if (bounds != _lastBounds)
{
instance.HostWindow.MoveResizeWebView(_platformWebView.Widget, num, num2, num3, num4);
Console.WriteLine($"[GtkWebViewHandler] Updated WebView to ({num}, {num2}) size {num3}x{num4}");
}
_lastBounds = bounds;
}
private void UnregisterFromHost()
{
if (_isRegisteredWithHost && _platformWebView != null)
{
GtkHostService instance = GtkHostService.Instance;
if (instance.HostWindow != null)
{
instance.HostWindow.RemoveWebView(_platformWebView.Widget);
Console.WriteLine("[GtkWebViewHandler] Unregistered WebView from host");
}
_isRegisteredWithHost = false;
}
}
public static void MapSource(GtkWebViewHandler handler, IWebView webView)
{
if (handler._platformWebView == null)
{
return;
}
IWebViewSource source = webView.Source;
Console.WriteLine("[GtkWebViewHandler] MapSource: " + (((object)source)?.GetType().Name ?? "null"));
UrlWebViewSource val = (UrlWebViewSource)(object)((source is UrlWebViewSource) ? source : null);
if (val != null)
{
string url = val.Url;
if (!string.IsNullOrEmpty(url))
{
handler._platformWebView.Navigate(url);
}
return;
}
HtmlWebViewSource val2 = (HtmlWebViewSource)(object)((source is HtmlWebViewSource) ? source : null);
if (val2 != null)
{
string html = val2.Html;
if (!string.IsNullOrEmpty(html))
{
handler._platformWebView.LoadHtml(html, val2.BaseUrl);
}
}
}
public static void MapGoBack(GtkWebViewHandler handler, IWebView webView, object? args)
{
Console.WriteLine($"[GtkWebViewHandler] MapGoBack called, CanGoBack={handler._platformWebView?.CanGoBack()}");
handler._platformWebView?.GoBack();
}
public static void MapGoForward(GtkWebViewHandler handler, IWebView webView, object? args)
{
Console.WriteLine($"[GtkWebViewHandler] MapGoForward called, CanGoForward={handler._platformWebView?.CanGoForward()}");
handler._platformWebView?.GoForward();
}
public static void MapReload(GtkWebViewHandler handler, IWebView webView, object? args)
{
Console.WriteLine("[GtkWebViewHandler] MapReload called");
handler._platformWebView?.Reload();
}
}

View File

@@ -0,0 +1,61 @@
using System.Collections.Generic;
using Microsoft.Maui.Platform.Linux.Window;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public sealed class GtkWebViewManager
{
private readonly GtkHostWindow _host;
private readonly Dictionary<object, GtkWebViewPlatformView> _webViews = new Dictionary<object, GtkWebViewPlatformView>();
public GtkWebViewManager(GtkHostWindow host)
{
_host = host;
}
public GtkWebViewPlatformView CreateWebView(object key, int x, int y, int width, int height)
{
GtkWebViewPlatformView gtkWebViewPlatformView = new GtkWebViewPlatformView();
_webViews[key] = gtkWebViewPlatformView;
_host.AddWebView(gtkWebViewPlatformView.Widget, x, y, width, height);
return gtkWebViewPlatformView;
}
public void UpdateLayout(object key, int x, int y, int width, int height)
{
if (_webViews.TryGetValue(key, out GtkWebViewPlatformView value))
{
_host.MoveResizeWebView(value.Widget, x, y, width, height);
}
}
public GtkWebViewPlatformView? GetWebView(object key)
{
if (!_webViews.TryGetValue(key, out GtkWebViewPlatformView value))
{
return null;
}
return value;
}
public void RemoveWebView(object key)
{
if (_webViews.TryGetValue(key, out GtkWebViewPlatformView value))
{
_host.RemoveWebView(value.Widget);
value.Dispose();
_webViews.Remove(key);
}
}
public void Clear()
{
foreach (KeyValuePair<object, GtkWebViewPlatformView> webView in _webViews)
{
_host.RemoveWebView(webView.Value.Widget);
webView.Value.Dispose();
}
_webViews.Clear();
}
}

View File

@@ -0,0 +1,183 @@
using System;
using Microsoft.Maui.Platform.Linux.Native;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public sealed class GtkWebViewPlatformView : IDisposable
{
private IntPtr _widget;
private bool _disposed;
private string? _currentUri;
private ulong _loadChangedSignalId;
private WebKitNative.LoadChangedCallback? _loadChangedCallback;
public IntPtr Widget => _widget;
public string? CurrentUri => _currentUri;
public event EventHandler<string>? NavigationStarted;
public event EventHandler<(string Url, bool Success)>? NavigationCompleted;
public event EventHandler<string>? TitleChanged;
public GtkWebViewPlatformView()
{
if (!WebKitNative.Initialize())
{
throw new InvalidOperationException("Failed to initialize WebKitGTK. Is libwebkit2gtk-4.x installed?");
}
_widget = WebKitNative.WebViewNew();
if (_widget == IntPtr.Zero)
{
throw new InvalidOperationException("Failed to create WebKitWebView widget");
}
WebKitNative.ConfigureSettings(_widget);
_loadChangedCallback = OnLoadChanged;
_loadChangedSignalId = WebKitNative.ConnectLoadChanged(_widget, _loadChangedCallback);
Console.WriteLine("[GtkWebViewPlatformView] Created WebKitWebView widget");
}
private void OnLoadChanged(IntPtr webView, int loadEvent, IntPtr userData)
{
try
{
string text = WebKitNative.GetUri(webView) ?? _currentUri ?? "";
switch ((WebKitNative.WebKitLoadEvent)loadEvent)
{
case WebKitNative.WebKitLoadEvent.Started:
Console.WriteLine("[GtkWebViewPlatformView] Load started: " + text);
this.NavigationStarted?.Invoke(this, text);
break;
case WebKitNative.WebKitLoadEvent.Finished:
_currentUri = text;
Console.WriteLine("[GtkWebViewPlatformView] Load finished: " + text);
this.NavigationCompleted?.Invoke(this, (text, true));
break;
case WebKitNative.WebKitLoadEvent.Committed:
_currentUri = text;
Console.WriteLine("[GtkWebViewPlatformView] Load committed: " + text);
break;
case WebKitNative.WebKitLoadEvent.Redirected:
break;
}
}
catch (Exception ex)
{
Console.WriteLine("[GtkWebViewPlatformView] Error in OnLoadChanged: " + ex.Message);
Console.WriteLine("[GtkWebViewPlatformView] Stack trace: " + ex.StackTrace);
}
}
public void Navigate(string uri)
{
if (_widget != IntPtr.Zero)
{
WebKitNative.LoadUri(_widget, uri);
Console.WriteLine("[GtkWebViewPlatformView] Navigate to: " + uri);
}
}
public void LoadHtml(string html, string? baseUri = null)
{
if (_widget != IntPtr.Zero)
{
WebKitNative.LoadHtml(_widget, html, baseUri);
Console.WriteLine("[GtkWebViewPlatformView] Load HTML content");
}
}
public void GoBack()
{
if (_widget != IntPtr.Zero)
{
WebKitNative.GoBack(_widget);
}
}
public void GoForward()
{
if (_widget != IntPtr.Zero)
{
WebKitNative.GoForward(_widget);
}
}
public bool CanGoBack()
{
if (_widget == IntPtr.Zero)
{
return false;
}
return WebKitNative.CanGoBack(_widget);
}
public bool CanGoForward()
{
if (_widget == IntPtr.Zero)
{
return false;
}
return WebKitNative.CanGoForward(_widget);
}
public void Reload()
{
if (_widget != IntPtr.Zero)
{
WebKitNative.Reload(_widget);
}
}
public void Stop()
{
if (_widget != IntPtr.Zero)
{
WebKitNative.StopLoading(_widget);
}
}
public string? GetTitle()
{
if (_widget == IntPtr.Zero)
{
return null;
}
return WebKitNative.GetTitle(_widget);
}
public string? GetUri()
{
if (_widget == IntPtr.Zero)
{
return null;
}
return WebKitNative.GetUri(_widget);
}
public void SetJavascriptEnabled(bool enabled)
{
if (_widget != IntPtr.Zero)
{
WebKitNative.SetJavascriptEnabled(_widget, enabled);
}
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
if (_widget != IntPtr.Zero)
{
WebKitNative.DisconnectLoadChanged(_widget);
}
_widget = IntPtr.Zero;
_loadChangedCallback = null;
}
}
}

104
Handlers/GtkWebViewProxy.cs Normal file
View File

@@ -0,0 +1,104 @@
using System;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class GtkWebViewProxy : SkiaView
{
private readonly GtkWebViewHandler _handler;
private readonly GtkWebViewPlatformView _platformView;
public GtkWebViewPlatformView PlatformView => _platformView;
public bool CanGoBack => _platformView.CanGoBack();
public bool CanGoForward => _platformView.CanGoForward();
public GtkWebViewProxy(GtkWebViewHandler handler, GtkWebViewPlatformView platformView)
{
_handler = handler;
_platformView = platformView;
}
public override void Arrange(SKRect bounds)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
base.Arrange(bounds);
SKRect bounds2 = TransformToWindow(bounds);
_handler.RegisterWithHost(bounds2);
}
private SKRect TransformToWindow(SKRect localBounds)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
float num = ((SKRect)(ref localBounds)).Left;
float num2 = ((SKRect)(ref localBounds)).Top;
for (SkiaView parent = base.Parent; parent != null; parent = parent.Parent)
{
float num3 = num;
SKRect bounds = parent.Bounds;
num = num3 + ((SKRect)(ref bounds)).Left;
float num4 = num2;
bounds = parent.Bounds;
num2 = num4 + ((SKRect)(ref bounds)).Top;
}
return new SKRect(num, num2, num + ((SKRect)(ref localBounds)).Width, num2 + ((SKRect)(ref localBounds)).Height);
}
public override void Draw(SKCanvas canvas)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
SKPaint val = new SKPaint
{
Color = new SKColor((byte)0, (byte)0, (byte)0, (byte)0),
Style = (SKPaintStyle)0
};
try
{
canvas.DrawRect(base.Bounds, val);
}
finally
{
((IDisposable)val)?.Dispose();
}
}
public void Navigate(string url)
{
_platformView.Navigate(url);
}
public void LoadHtml(string html, string? baseUrl = null)
{
_platformView.LoadHtml(html, baseUrl);
}
public void GoBack()
{
_platformView.GoBack();
}
public void GoForward()
{
_platformView.GoForward();
}
public void Reload()
{
_platformView.Reload();
}
}

View File

@@ -1,233 +1,275 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using System.IO;
using System.Threading;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using SkiaSharp;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for ImageButton on Linux using Skia rendering.
/// Maps IImageButton interface to SkiaImageButton platform view.
/// IImageButton extends: IImage, IView, IButtonStroke, IPadding
/// </summary>
public partial class ImageButtonHandler : ViewHandler<IImageButton, SkiaImageButton>
public class ImageButtonHandler : ViewHandler<IImageButton, SkiaImageButton>
{
public static IPropertyMapper<IImageButton, ImageButtonHandler> Mapper = new PropertyMapper<IImageButton, ImageButtonHandler>(ViewHandler.ViewMapper)
{
[nameof(IImage.Aspect)] = MapAspect,
[nameof(IImage.IsOpaque)] = MapIsOpaque,
[nameof(IImageSourcePart.Source)] = MapSource,
[nameof(IButtonStroke.StrokeColor)] = MapStrokeColor,
[nameof(IButtonStroke.StrokeThickness)] = MapStrokeThickness,
[nameof(IButtonStroke.CornerRadius)] = MapCornerRadius,
[nameof(IPadding.Padding)] = MapPadding,
[nameof(IView.Background)] = MapBackground,
};
internal class ImageSourceServiceResultManager
{
private readonly ImageButtonHandler _handler;
public static CommandMapper<IImageButton, ImageButtonHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
private CancellationTokenSource? _cts;
public ImageButtonHandler() : base(Mapper, CommandMapper)
{
}
public ImageSourceServiceResultManager(ImageButtonHandler handler)
{
_handler = handler;
}
public ImageButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public async void UpdateImageSourceAsync()
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
CancellationToken token = _cts.Token;
try
{
IImageButton virtualView = ((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).VirtualView;
IImageSource val = ((virtualView != null) ? ((IImageSourcePart)virtualView).Source : null);
if (val == null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).PlatformView?.LoadFromData(Array.Empty<byte>());
return;
}
IImageSourcePart virtualView2 = (IImageSourcePart)(object)((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).VirtualView;
if (virtualView2 != null)
{
virtualView2.UpdateIsLoading(true);
}
IFileImageSource val2 = (IFileImageSource)(object)((val is IFileImageSource) ? val : null);
if (val2 != null)
{
string file = val2.File;
if (!string.IsNullOrEmpty(file))
{
await ((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).PlatformView.LoadFromFileAsync(file);
}
return;
}
IUriImageSource val3 = (IUriImageSource)(object)((val is IUriImageSource) ? val : null);
if (val3 != null)
{
Uri uri = val3.Uri;
if (uri != null)
{
await ((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).PlatformView.LoadFromUriAsync(uri);
}
return;
}
IStreamImageSource val4 = (IStreamImageSource)(object)((val is IStreamImageSource) ? val : null);
if (val4 != null)
{
Stream stream = await val4.GetStreamAsync(token);
if (stream != null)
{
await ((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).PlatformView.LoadFromStreamAsync(stream);
}
}
}
catch (OperationCanceledException)
{
}
catch (Exception)
{
IImageSourcePart virtualView3 = (IImageSourcePart)(object)((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).VirtualView;
if (virtualView3 != null)
{
virtualView3.UpdateIsLoading(false);
}
}
}
}
protected override SkiaImageButton CreatePlatformView()
{
return new SkiaImageButton();
}
public static IPropertyMapper<IImageButton, ImageButtonHandler> Mapper = (IPropertyMapper<IImageButton, ImageButtonHandler>)(object)new PropertyMapper<IImageButton, ImageButtonHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Aspect"] = MapAspect,
["IsOpaque"] = MapIsOpaque,
["Source"] = MapSource,
["StrokeColor"] = MapStrokeColor,
["StrokeThickness"] = MapStrokeThickness,
["CornerRadius"] = MapCornerRadius,
["Padding"] = MapPadding,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
protected override void ConnectHandler(SkiaImageButton platformView)
{
base.ConnectHandler(platformView);
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
platformView.ImageLoaded += OnImageLoaded;
platformView.ImageLoadingError += OnImageLoadingError;
}
public static CommandMapper<IImageButton, ImageButtonHandler> CommandMapper = new CommandMapper<IImageButton, ImageButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
protected override void DisconnectHandler(SkiaImageButton platformView)
{
platformView.Clicked -= OnClicked;
platformView.Pressed -= OnPressed;
platformView.Released -= OnReleased;
platformView.ImageLoaded -= OnImageLoaded;
platformView.ImageLoadingError -= OnImageLoadingError;
base.DisconnectHandler(platformView);
}
private ImageSourceServiceResultManager _sourceLoader;
private void OnClicked(object? sender, EventArgs e)
{
VirtualView?.Clicked();
}
private ImageSourceServiceResultManager SourceLoader => _sourceLoader ?? (_sourceLoader = new ImageSourceServiceResultManager(this));
private void OnPressed(object? sender, EventArgs e)
{
VirtualView?.Pressed();
}
public ImageButtonHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
private void OnReleased(object? sender, EventArgs e)
{
VirtualView?.Released();
}
public ImageButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
private void OnImageLoaded(object? sender, EventArgs e)
{
if (VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
protected override SkiaImageButton CreatePlatformView()
{
return new SkiaImageButton();
}
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
{
if (VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
protected override void ConnectHandler(SkiaImageButton platformView)
{
base.ConnectHandler(platformView);
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
platformView.ImageLoaded += OnImageLoaded;
platformView.ImageLoadingError += OnImageLoadingError;
}
public static void MapAspect(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Aspect = imageButton.Aspect;
}
protected override void DisconnectHandler(SkiaImageButton platformView)
{
platformView.Clicked -= OnClicked;
platformView.Pressed -= OnPressed;
platformView.Released -= OnReleased;
platformView.ImageLoaded -= OnImageLoaded;
platformView.ImageLoadingError -= OnImageLoadingError;
base.DisconnectHandler(platformView);
}
public static void MapIsOpaque(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsOpaque = imageButton.IsOpaque;
}
private void OnClicked(object? sender, EventArgs e)
{
IImageButton virtualView = base.VirtualView;
if (virtualView != null)
{
((IButton)virtualView).Clicked();
}
}
public static void MapSource(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.SourceLoader.UpdateImageSourceAsync();
}
private void OnPressed(object? sender, EventArgs e)
{
IImageButton virtualView = base.VirtualView;
if (virtualView != null)
{
((IButton)virtualView).Pressed();
}
}
public static void MapStrokeColor(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
private void OnReleased(object? sender, EventArgs e)
{
IImageButton virtualView = base.VirtualView;
if (virtualView != null)
{
((IButton)virtualView).Released();
}
}
if (imageButton.StrokeColor is not null)
handler.PlatformView.StrokeColor = imageButton.StrokeColor.ToSKColor();
}
private void OnImageLoaded(object? sender, EventArgs e)
{
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
if (virtualView != null)
{
virtualView.UpdateIsLoading(false);
}
}
public static void MapStrokeThickness(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.StrokeThickness = (float)imageButton.StrokeThickness;
}
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
{
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
if (virtualView != null)
{
virtualView.UpdateIsLoading(false);
}
}
public static void MapCornerRadius(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CornerRadius = imageButton.CornerRadius;
}
public static void MapAspect(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.Aspect = ((IImage)imageButton).Aspect;
}
}
public static void MapPadding(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
public static void MapIsOpaque(ImageButtonHandler handler, IImageButton imageButton)
{
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.IsOpaque = ((IImage)imageButton).IsOpaque;
}
}
var padding = imageButton.Padding;
handler.PlatformView.PaddingLeft = (float)padding.Left;
handler.PlatformView.PaddingTop = (float)padding.Top;
handler.PlatformView.PaddingRight = (float)padding.Right;
handler.PlatformView.PaddingBottom = (float)padding.Bottom;
}
public static void MapSource(ImageButtonHandler handler, IImageButton imageButton)
{
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
handler.SourceLoader.UpdateImageSourceAsync();
}
}
public static void MapBackground(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
public static void MapStrokeColor(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null && ((IButtonStroke)imageButton).StrokeColor != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.StrokeColor = ((IButtonStroke)imageButton).StrokeColor.ToSKColor();
}
}
if (imageButton.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapStrokeThickness(ImageButtonHandler handler, IImageButton imageButton)
{
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.StrokeThickness = (float)((IButtonStroke)imageButton).StrokeThickness;
}
}
// Image source loading helper
private ImageSourceServiceResultManager _sourceLoader = null!;
public static void MapCornerRadius(ImageButtonHandler handler, IImageButton imageButton)
{
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.CornerRadius = ((IButtonStroke)imageButton).CornerRadius;
}
}
private ImageSourceServiceResultManager SourceLoader =>
_sourceLoader ??= new ImageSourceServiceResultManager(this);
public static void MapPadding(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
Thickness padding = ((IPadding)imageButton).Padding;
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.PaddingLeft = (float)((Thickness)(ref padding)).Left;
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.PaddingTop = (float)((Thickness)(ref padding)).Top;
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.PaddingRight = (float)((Thickness)(ref padding)).Right;
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.PaddingBottom = (float)((Thickness)(ref padding)).Bottom;
}
}
internal class ImageSourceServiceResultManager
{
private readonly ImageButtonHandler _handler;
private CancellationTokenSource? _cts;
public static void MapBackground(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
Paint background = ((IView)imageButton).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public ImageSourceServiceResultManager(ImageButtonHandler handler)
{
_handler = handler;
}
public async void UpdateImageSourceAsync()
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
var token = _cts.Token;
try
{
var source = _handler.VirtualView?.Source;
if (source == null)
{
_handler.PlatformView?.LoadFromData(Array.Empty<byte>());
return;
}
if (_handler.VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(true);
}
// Handle different image source types
if (source is IFileImageSource fileSource)
{
var file = fileSource.File;
if (!string.IsNullOrEmpty(file))
{
await _handler.PlatformView!.LoadFromFileAsync(file);
}
}
else if (source is IUriImageSource uriSource)
{
var uri = uriSource.Uri;
if (uri != null)
{
await _handler.PlatformView!.LoadFromUriAsync(uri);
}
}
else if (source is IStreamImageSource streamSource)
{
var stream = await streamSource.GetStreamAsync(token);
if (stream != null)
{
await _handler.PlatformView!.LoadFromStreamAsync(stream);
}
}
}
catch (OperationCanceledException)
{
// Loading was cancelled
}
catch (Exception)
{
// Handle error
if (_handler.VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
}
}
public static void MapBackgroundColor(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
ImageButton val = (ImageButton)(object)((imageButton is ImageButton) ? imageButton : null);
if (val != null && ((VisualElement)val).BackgroundColor != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.BackgroundColor = ((VisualElement)val).BackgroundColor.ToSKColor();
}
}
}
}

View File

@@ -1,180 +1,342 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using System.IO;
using System.Threading;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Image on Linux using Skia rendering.
/// Maps IImage interface to SkiaImage platform view.
/// IImage has: Aspect, IsOpaque (inherits from IImageSourcePart)
/// </summary>
public partial class ImageHandler : ViewHandler<IImage, SkiaImage>
public class ImageHandler : ViewHandler<IImage, SkiaImage>
{
public static IPropertyMapper<IImage, ImageHandler> Mapper = new PropertyMapper<IImage, ImageHandler>(ViewHandler.ViewMapper)
{
[nameof(IImage.Aspect)] = MapAspect,
[nameof(IImage.IsOpaque)] = MapIsOpaque,
[nameof(IImageSourcePart.Source)] = MapSource,
[nameof(IView.Background)] = MapBackground,
};
internal class ImageSourceServiceResultManager
{
private readonly ImageHandler _handler;
public static CommandMapper<IImage, ImageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
private CancellationTokenSource? _cts;
public ImageHandler() : base(Mapper, CommandMapper)
{
}
public ImageSourceServiceResultManager(ImageHandler handler)
{
_handler = handler;
}
public ImageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public async void UpdateImageSourceAsync()
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
CancellationToken token = _cts.Token;
try
{
IImage virtualView = ((ViewHandler<IImage, SkiaImage>)(object)_handler).VirtualView;
IImageSource val = ((virtualView != null) ? ((IImageSourcePart)virtualView).Source : null);
if (val == null)
{
((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView?.LoadFromData(Array.Empty<byte>());
return;
}
IImageSourcePart virtualView2 = (IImageSourcePart)(object)((ViewHandler<IImage, SkiaImage>)(object)_handler).VirtualView;
if (virtualView2 != null)
{
virtualView2.UpdateIsLoading(true);
}
IFileImageSource val2 = (IFileImageSource)(object)((val is IFileImageSource) ? val : null);
if (val2 != null)
{
string file = val2.File;
if (!string.IsNullOrEmpty(file))
{
await ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.LoadFromFileAsync(file);
}
return;
}
IUriImageSource val3 = (IUriImageSource)(object)((val is IUriImageSource) ? val : null);
if (val3 != null)
{
Uri uri = val3.Uri;
if (uri != null)
{
await ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.LoadFromUriAsync(uri);
}
return;
}
IStreamImageSource val4 = (IStreamImageSource)(object)((val is IStreamImageSource) ? val : null);
if (val4 != null)
{
Stream stream = await val4.GetStreamAsync(token);
if (stream != null)
{
await ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.LoadFromStreamAsync(stream);
}
return;
}
FontImageSource val5 = (FontImageSource)(object)((val is FontImageSource) ? val : null);
if (val5 != null)
{
SKBitmap val6 = RenderFontImageSource(val5, ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.WidthRequest, ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.HeightRequest);
if (val6 != null)
{
((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.LoadFromBitmap(val6);
}
}
}
catch (OperationCanceledException)
{
}
catch (Exception)
{
IImageSourcePart virtualView3 = (IImageSourcePart)(object)((ViewHandler<IImage, SkiaImage>)(object)_handler).VirtualView;
if (virtualView3 != null)
{
virtualView3.UpdateIsLoading(false);
}
}
}
protected override SkiaImage CreatePlatformView()
{
return new SkiaImage();
}
private static SKBitmap? RenderFontImageSource(FontImageSource fontSource, double requestedWidth, double requestedHeight)
{
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Expected O, but got Unknown
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Expected O, but got Unknown
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
string glyph = fontSource.Glyph;
if (string.IsNullOrEmpty(glyph))
{
return null;
}
int val = (int)Math.Max((requestedWidth > 0.0) ? requestedWidth : 24.0, (requestedHeight > 0.0) ? requestedHeight : 24.0);
val = Math.Max(val, 16);
SKColor color = fontSource.Color?.ToSKColor() ?? SKColors.Black;
SKBitmap val2 = new SKBitmap(val, val, false);
SKCanvas val3 = new SKCanvas(val2);
try
{
val3.Clear(SKColors.Transparent);
SKTypeface val4 = null;
if (!string.IsNullOrEmpty(fontSource.FontFamily))
{
string[] array = new string[4]
{
"/usr/share/fonts/truetype/" + fontSource.FontFamily + ".ttf",
"/usr/share/fonts/opentype/" + fontSource.FontFamily + ".otf",
"/usr/local/share/fonts/" + fontSource.FontFamily + ".ttf",
Path.Combine(AppContext.BaseDirectory, fontSource.FontFamily + ".ttf")
};
foreach (string text in array)
{
if (File.Exists(text))
{
val4 = SKTypeface.FromFile(text, 0);
if (val4 != null)
{
break;
}
}
}
if (val4 == null)
{
val4 = SKTypeface.FromFamilyName(fontSource.FontFamily);
}
}
if (val4 == null)
{
val4 = SKTypeface.Default;
}
float num = (float)val * 0.8f;
SKFont val5 = new SKFont(val4, num, 1f, 0f);
try
{
SKPaint val6 = new SKPaint(val5)
{
Color = color,
IsAntialias = true,
TextAlign = (SKTextAlign)1
};
try
{
SKRect val7 = default(SKRect);
val6.MeasureText(glyph, ref val7);
float num2 = (float)val / 2f;
float num3 = ((float)val - ((SKRect)(ref val7)).Top - ((SKRect)(ref val7)).Bottom) / 2f;
val3.DrawText(glyph, num2, num3, val6);
return val2;
}
finally
{
((IDisposable)val6)?.Dispose();
}
}
finally
{
((IDisposable)val5)?.Dispose();
}
}
finally
{
((IDisposable)val3)?.Dispose();
}
}
}
protected override void ConnectHandler(SkiaImage platformView)
{
base.ConnectHandler(platformView);
platformView.ImageLoaded += OnImageLoaded;
platformView.ImageLoadingError += OnImageLoadingError;
}
public static IPropertyMapper<IImage, ImageHandler> Mapper = (IPropertyMapper<IImage, ImageHandler>)(object)new PropertyMapper<IImage, ImageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Aspect"] = MapAspect,
["IsOpaque"] = MapIsOpaque,
["Source"] = MapSource,
["Background"] = MapBackground,
["Width"] = MapWidth,
["Height"] = MapHeight
};
protected override void DisconnectHandler(SkiaImage platformView)
{
platformView.ImageLoaded -= OnImageLoaded;
platformView.ImageLoadingError -= OnImageLoadingError;
base.DisconnectHandler(platformView);
}
public static CommandMapper<IImage, ImageHandler> CommandMapper = new CommandMapper<IImage, ImageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
private void OnImageLoaded(object? sender, EventArgs e)
{
// Notify that the image has been loaded
if (VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
private ImageSourceServiceResultManager _sourceLoader;
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
{
// Handle loading error
if (VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
private ImageSourceServiceResultManager SourceLoader => _sourceLoader ?? (_sourceLoader = new ImageSourceServiceResultManager(this));
public static void MapAspect(ImageHandler handler, IImage image)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Aspect = image.Aspect;
}
public ImageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public static void MapIsOpaque(ImageHandler handler, IImage image)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsOpaque = image.IsOpaque;
}
public ImageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public static void MapSource(ImageHandler handler, IImage image)
{
if (handler.PlatformView is null) return;
protected override SkiaImage CreatePlatformView()
{
return new SkiaImage();
}
handler.SourceLoader.UpdateImageSourceAsync();
}
protected override void ConnectHandler(SkiaImage platformView)
{
base.ConnectHandler(platformView);
platformView.ImageLoaded += OnImageLoaded;
platformView.ImageLoadingError += OnImageLoadingError;
}
public static void MapBackground(ImageHandler handler, IImage image)
{
if (handler.PlatformView is null) return;
protected override void DisconnectHandler(SkiaImage platformView)
{
platformView.ImageLoaded -= OnImageLoaded;
platformView.ImageLoadingError -= OnImageLoadingError;
base.DisconnectHandler(platformView);
}
if (image.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
private void OnImageLoaded(object? sender, EventArgs e)
{
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
if (virtualView != null)
{
virtualView.UpdateIsLoading(false);
}
}
// Image source loading helper
private ImageSourceServiceResultManager _sourceLoader = null!;
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
{
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
if (virtualView != null)
{
virtualView.UpdateIsLoading(false);
}
}
private ImageSourceServiceResultManager SourceLoader =>
_sourceLoader ??= new ImageSourceServiceResultManager(this);
public static void MapAspect(ImageHandler handler, IImage image)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.Aspect = image.Aspect;
}
}
internal class ImageSourceServiceResultManager
{
private readonly ImageHandler _handler;
private CancellationTokenSource? _cts;
public static void MapIsOpaque(ImageHandler handler, IImage image)
{
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.IsOpaque = image.IsOpaque;
}
}
public ImageSourceServiceResultManager(ImageHandler handler)
{
_handler = handler;
}
public static void MapSource(ImageHandler handler, IImage image)
{
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView == null)
{
return;
}
Image val = (Image)(object)((image is Image) ? image : null);
if (val != null)
{
if (((VisualElement)val).WidthRequest > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.WidthRequest = ((VisualElement)val).WidthRequest;
}
if (((VisualElement)val).HeightRequest > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.HeightRequest = ((VisualElement)val).HeightRequest;
}
}
handler.SourceLoader.UpdateImageSourceAsync();
}
public async void UpdateImageSourceAsync()
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
var token = _cts.Token;
public static void MapBackground(ImageHandler handler, IImage image)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
Paint background = ((IView)image).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
try
{
var source = _handler.VirtualView?.Source;
if (source == null)
{
_handler.PlatformView?.LoadFromData(Array.Empty<byte>());
return;
}
public static void MapWidth(ImageHandler handler, IImage image)
{
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
Image val = (Image)(object)((image is Image) ? image : null);
if (val != null && ((VisualElement)val).WidthRequest > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.WidthRequest = ((VisualElement)val).WidthRequest;
Console.WriteLine($"[ImageHandler] MapWidth: {((VisualElement)val).WidthRequest}");
}
else if (((IView)image).Width > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.WidthRequest = ((IView)image).Width;
}
}
}
if (_handler.VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(true);
}
// Handle different image source types
if (source is IFileImageSource fileSource)
{
var file = fileSource.File;
if (!string.IsNullOrEmpty(file))
{
await _handler.PlatformView!.LoadFromFileAsync(file);
}
}
else if (source is IUriImageSource uriSource)
{
var uri = uriSource.Uri;
if (uri != null)
{
await _handler.PlatformView!.LoadFromUriAsync(uri);
}
}
else if (source is IStreamImageSource streamSource)
{
var stream = await streamSource.GetStreamAsync(token);
if (stream != null)
{
await _handler.PlatformView!.LoadFromStreamAsync(stream);
}
}
}
catch (OperationCanceledException)
{
// Loading was cancelled
}
catch (Exception)
{
// Handle error
if (_handler.VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
}
}
public static void MapHeight(ImageHandler handler, IImage image)
{
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
Image val = (Image)(object)((image is Image) ? image : null);
if (val != null && ((VisualElement)val).HeightRequest > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.HeightRequest = ((VisualElement)val).HeightRequest;
Console.WriteLine($"[ImageHandler] MapHeight: {((VisualElement)val).HeightRequest}");
}
else if (((IView)image).Height > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.HeightRequest = ((IView)image).Height;
}
}
}
}

View File

@@ -1,164 +1,175 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Base handler for ItemsView on Linux using Skia rendering.
/// Maps ItemsView to SkiaItemsView platform view.
/// </summary>
public partial class ItemsViewHandler<TItemsView> : ViewHandler<TItemsView, SkiaItemsView>
where TItemsView : ItemsView
public class ItemsViewHandler<TItemsView> : ViewHandler<TItemsView, SkiaItemsView> where TItemsView : ItemsView
{
public static IPropertyMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewMapper =
new PropertyMapper<TItemsView, ItemsViewHandler<TItemsView>>(ViewHandler.ViewMapper)
{
[nameof(ItemsView.ItemsSource)] = MapItemsSource,
[nameof(ItemsView.ItemTemplate)] = MapItemTemplate,
[nameof(ItemsView.EmptyView)] = MapEmptyView,
[nameof(ItemsView.EmptyViewTemplate)] = MapEmptyViewTemplate,
[nameof(ItemsView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
[nameof(ItemsView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewMapper = (IPropertyMapper<TItemsView, ItemsViewHandler<TItemsView>>)(object)new PropertyMapper<TItemsView, ItemsViewHandler<TItemsView>>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["ItemsSource"] = MapItemsSource,
["ItemTemplate"] = MapItemTemplate,
["EmptyView"] = MapEmptyView,
["EmptyViewTemplate"] = MapEmptyViewTemplate,
["HorizontalScrollBarVisibility"] = MapHorizontalScrollBarVisibility,
["VerticalScrollBarVisibility"] = MapVerticalScrollBarVisibility,
["Background"] = MapBackground
};
public static CommandMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewCommandMapper =
new(ViewHandler.ViewCommandMapper)
{
["ScrollTo"] = MapScrollTo,
};
public static CommandMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewCommandMapper = new CommandMapper<TItemsView, ItemsViewHandler<TItemsView>>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["ScrollTo"] = MapScrollTo };
public ItemsViewHandler() : base(ItemsViewMapper, ItemsViewCommandMapper)
{
}
public ItemsViewHandler()
: base((IPropertyMapper)(object)ItemsViewMapper, (CommandMapper)(object)ItemsViewCommandMapper)
{
}
public ItemsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? ItemsViewMapper, commandMapper ?? ItemsViewCommandMapper)
{
}
public ItemsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)ItemsViewMapper)), (CommandMapper)(((object)commandMapper) ?? ((object)ItemsViewCommandMapper)))
{
}
protected override SkiaItemsView CreatePlatformView()
{
return new SkiaItemsView();
}
protected override SkiaItemsView CreatePlatformView()
{
return new SkiaItemsView();
}
protected override void ConnectHandler(SkiaItemsView platformView)
{
base.ConnectHandler(platformView);
platformView.Scrolled += OnScrolled;
platformView.ItemTapped += OnItemTapped;
protected override void ConnectHandler(SkiaItemsView platformView)
{
base.ConnectHandler(platformView);
platformView.Scrolled += OnScrolled;
platformView.ItemTapped += OnItemTapped;
platformView.ItemRenderer = RenderItem;
}
// Set up item renderer
platformView.ItemRenderer = RenderItem;
}
protected override void DisconnectHandler(SkiaItemsView platformView)
{
platformView.Scrolled -= OnScrolled;
platformView.ItemTapped -= OnItemTapped;
platformView.ItemRenderer = null;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaItemsView platformView)
{
platformView.Scrolled -= OnScrolled;
platformView.ItemTapped -= OnItemTapped;
platformView.ItemRenderer = null;
base.DisconnectHandler(platformView);
}
private void OnScrolled(object? sender, ItemsScrolledEventArgs e)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
object obj = base.VirtualView;
if (obj != null)
{
((ItemsView)obj).SendScrolled(new ItemsViewScrolledEventArgs
{
VerticalOffset = e.ScrollOffset,
VerticalDelta = 0.0,
HorizontalOffset = 0.0,
HorizontalDelta = 0.0
});
}
}
private void OnScrolled(object? sender, ItemsScrolledEventArgs e)
{
// Fire scrolled event on virtual view
VirtualView?.SendScrolled(new ItemsViewScrolledEventArgs
{
VerticalOffset = e.ScrollOffset,
VerticalDelta = 0,
HorizontalOffset = 0,
HorizontalDelta = 0
});
}
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
{
}
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
{
// Item tap handling - can be extended for selection
}
protected virtual bool RenderItem(object item, int index, SKRect bounds, SKCanvas canvas, SKPaint paint)
{
object obj = base.VirtualView;
if (obj != null)
{
_ = ((ItemsView)obj).ItemTemplate;
}
else
_ = null;
return false;
}
protected virtual bool RenderItem(object item, int index, SKRect bounds, SKCanvas canvas, SKPaint paint)
{
// Check if we have an ItemTemplate
var template = VirtualView?.ItemTemplate;
if (template == null)
return false; // Use default rendering
public static void MapItemsSource(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.ItemsSource = ((ItemsView)itemsView).ItemsSource;
}
}
// For now, render based on item ToString
// Full DataTemplate support would require creating actual views
return false;
}
public static void MapItemTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView?.Invalidate();
}
public static void MapItemsSource(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.ItemsSource = itemsView.ItemsSource;
}
public static void MapEmptyView(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.EmptyView = ((ItemsView)itemsView).EmptyView;
if (((ItemsView)itemsView).EmptyView is string emptyViewText)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.EmptyViewText = emptyViewText;
}
}
}
public static void MapItemTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
// ItemTemplate affects how items are rendered
// The renderer will check this when drawing items
handler.PlatformView?.Invalidate();
}
public static void MapEmptyViewTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView?.Invalidate();
}
public static void MapEmptyView(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
public static void MapHorizontalScrollBarVisibility(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected I4, but got Unknown
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.HorizontalScrollBarVisibility = (ScrollBarVisibility)((ItemsView)itemsView).HorizontalScrollBarVisibility;
}
}
handler.PlatformView.EmptyView = itemsView.EmptyView;
if (itemsView.EmptyView is string text)
{
handler.PlatformView.EmptyViewText = text;
}
}
public static void MapVerticalScrollBarVisibility(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected I4, but got Unknown
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.VerticalScrollBarVisibility = (ScrollBarVisibility)((ItemsView)itemsView).VerticalScrollBarVisibility;
}
}
public static void MapEmptyViewTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
// EmptyViewTemplate would be used to render custom empty view
handler.PlatformView?.Invalidate();
}
public static void MapBackground(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
Brush background = ((VisualElement)(object)itemsView).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapHorizontalScrollBarVisibility(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalScrollBarVisibility = (ScrollBarVisibility)itemsView.HorizontalScrollBarVisibility;
}
public static void MapVerticalScrollBarVisibility(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalScrollBarVisibility = (ScrollBarVisibility)itemsView.VerticalScrollBarVisibility;
}
public static void MapBackground(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
if (itemsView.Background is SolidColorBrush solidBrush)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
}
}
public static void MapScrollTo(ItemsViewHandler<TItemsView> handler, TItemsView itemsView, object? args)
{
if (handler.PlatformView is null || args is not ScrollToRequestEventArgs scrollArgs)
return;
if (scrollArgs.Mode == ScrollToMode.Position)
{
handler.PlatformView.ScrollToIndex(scrollArgs.Index, scrollArgs.IsAnimated);
}
else if (scrollArgs.Item != null)
{
handler.PlatformView.ScrollToItem(scrollArgs.Item, scrollArgs.IsAnimated);
}
}
public static void MapScrollTo(ItemsViewHandler<TItemsView> handler, TItemsView itemsView, object? args)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView == null)
{
return;
}
ScrollToRequestEventArgs e = (ScrollToRequestEventArgs)((args is ScrollToRequestEventArgs) ? args : null);
if (e != null)
{
if ((int)e.Mode == 1)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.ScrollToIndex(e.Index, e.IsAnimated);
}
else if (e.Item != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.ScrollToItem(e.Item, e.IsAnimated);
}
}
}
}

View File

@@ -1,208 +1,388 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Window;
using Microsoft.Maui.Primitives;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Label on Linux using Skia rendering.
/// Maps ILabel interface to SkiaLabel platform view.
/// </summary>
public partial class LabelHandler : ViewHandler<ILabel, SkiaLabel>
public class LabelHandler : ViewHandler<ILabel, SkiaLabel>
{
public static IPropertyMapper<ILabel, LabelHandler> Mapper = new PropertyMapper<ILabel, LabelHandler>(ViewHandler.ViewMapper)
{
[nameof(IText.Text)] = MapText,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(ITextStyle.CharacterSpacing)] = MapCharacterSpacing,
[nameof(ITextAlignment.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(ITextAlignment.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(ILabel.TextDecorations)] = MapTextDecorations,
[nameof(ILabel.LineHeight)] = MapLineHeight,
["LineBreakMode"] = MapLineBreakMode,
["MaxLines"] = MapMaxLines,
[nameof(IPadding.Padding)] = MapPadding,
[nameof(IView.Background)] = MapBackground,
[nameof(IView.VerticalLayoutAlignment)] = MapVerticalLayoutAlignment,
[nameof(IView.HorizontalLayoutAlignment)] = MapHorizontalLayoutAlignment,
};
public static IPropertyMapper<ILabel, LabelHandler> Mapper = (IPropertyMapper<ILabel, LabelHandler>)(object)new PropertyMapper<ILabel, LabelHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Text"] = MapText,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["CharacterSpacing"] = MapCharacterSpacing,
["HorizontalTextAlignment"] = MapHorizontalTextAlignment,
["VerticalTextAlignment"] = MapVerticalTextAlignment,
["TextDecorations"] = MapTextDecorations,
["LineHeight"] = MapLineHeight,
["LineBreakMode"] = MapLineBreakMode,
["MaxLines"] = MapMaxLines,
["Padding"] = MapPadding,
["Background"] = MapBackground,
["VerticalLayoutAlignment"] = MapVerticalLayoutAlignment,
["HorizontalLayoutAlignment"] = MapHorizontalLayoutAlignment,
["FormattedText"] = MapFormattedText
};
public static CommandMapper<ILabel, LabelHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<ILabel, LabelHandler> CommandMapper = new CommandMapper<ILabel, LabelHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public LabelHandler() : base(Mapper, CommandMapper)
{
}
public LabelHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public LabelHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public LabelHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaLabel CreatePlatformView()
{
return new SkiaLabel();
}
protected override SkiaLabel CreatePlatformView()
{
return new SkiaLabel();
}
public static void MapText(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Text = label.Text ?? string.Empty;
}
protected override void ConnectHandler(SkiaLabel platformView)
{
base.ConnectHandler(platformView);
ILabel virtualView = base.VirtualView;
View val = (View)(object)((virtualView is View) ? virtualView : null);
if (val != null)
{
platformView.MauiView = val;
if (val.GestureRecognizers.OfType<TapGestureRecognizer>().Any())
{
platformView.CursorType = CursorType.Hand;
}
}
platformView.Tapped += OnPlatformViewTapped;
}
public static void MapTextColor(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
protected override void DisconnectHandler(SkiaLabel platformView)
{
platformView.Tapped -= OnPlatformViewTapped;
platformView.MauiView = null;
base.DisconnectHandler(platformView);
}
if (label.TextColor is not null)
handler.PlatformView.TextColor = label.TextColor.ToSKColor();
}
private void OnPlatformViewTapped(object? sender, EventArgs e)
{
ILabel virtualView = base.VirtualView;
View val = (View)(object)((virtualView is View) ? virtualView : null);
if (val != null)
{
GestureManager.ProcessTap(val, 0.0, 0.0);
}
}
public static void MapFont(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapText(LabelHandler handler, ILabel label)
{
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.Text = ((IText)label).Text ?? string.Empty;
}
}
var font = label.Font;
if (font.Size > 0)
handler.PlatformView.FontSize = (float)font.Size;
public static void MapTextColor(LabelHandler handler, ILabel label)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null && ((ITextStyle)label).TextColor != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.TextColor = ((ITextStyle)label).TextColor.ToSKColor();
}
}
if (!string.IsNullOrEmpty(font.Family))
handler.PlatformView.FontFamily = font.Family;
public static void MapFont(LabelHandler handler, ILabel label)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Invalid comparison between Unknown and I4
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Invalid comparison between Unknown and I4
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Invalid comparison between Unknown and I4
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)label).Font;
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.IsBold = (int)((Font)(ref font)).Weight >= 700;
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.IsItalic = (int)((Font)(ref font)).Slant == 1 || (int)((Font)(ref font)).Slant == 2;
}
}
handler.PlatformView.IsBold = font.Weight >= FontWeight.Bold;
handler.PlatformView.IsItalic = font.Slant == FontSlant.Italic || font.Slant == FontSlant.Oblique;
}
public static void MapCharacterSpacing(LabelHandler handler, ILabel label)
{
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.CharacterSpacing = (float)((ITextStyle)label).CharacterSpacing;
}
}
public static void MapCharacterSpacing(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CharacterSpacing = (float)label.CharacterSpacing;
}
public static void MapHorizontalTextAlignment(LabelHandler handler, ILabel label)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
TextAlignment horizontalTextAlignment = ((ITextAlignment)label).HorizontalTextAlignment;
platformView.HorizontalTextAlignment = (int)horizontalTextAlignment switch
{
0 => TextAlignment.Start,
1 => TextAlignment.Center,
2 => TextAlignment.End,
_ => TextAlignment.Start,
};
}
}
public static void MapHorizontalTextAlignment(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapVerticalTextAlignment(LabelHandler handler, ILabel label)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
TextAlignment verticalTextAlignment = ((ITextAlignment)label).VerticalTextAlignment;
platformView.VerticalTextAlignment = (int)verticalTextAlignment switch
{
0 => TextAlignment.Start,
1 => TextAlignment.Center,
2 => TextAlignment.End,
_ => TextAlignment.Center,
};
}
}
// Map MAUI TextAlignment to our internal TextAlignment
handler.PlatformView.HorizontalTextAlignment = label.HorizontalTextAlignment switch
{
Microsoft.Maui.TextAlignment.Start => Platform.TextAlignment.Start,
Microsoft.Maui.TextAlignment.Center => Platform.TextAlignment.Center,
Microsoft.Maui.TextAlignment.End => Platform.TextAlignment.End,
_ => Platform.TextAlignment.Start
};
}
public static void MapTextDecorations(LabelHandler handler, ILabel label)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Invalid comparison between Unknown and I4
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Invalid comparison between Unknown and I4
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.IsUnderline = (label.TextDecorations & 1) > 0;
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.IsStrikethrough = (label.TextDecorations & 2) > 0;
}
}
public static void MapVerticalTextAlignment(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapLineHeight(LabelHandler handler, ILabel label)
{
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.LineHeight = (float)label.LineHeight;
}
}
handler.PlatformView.VerticalTextAlignment = label.VerticalTextAlignment switch
{
Microsoft.Maui.TextAlignment.Start => Platform.TextAlignment.Start,
Microsoft.Maui.TextAlignment.Center => Platform.TextAlignment.Center,
Microsoft.Maui.TextAlignment.End => Platform.TextAlignment.End,
_ => Platform.TextAlignment.Center
};
}
public static void MapLineBreakMode(LabelHandler handler, ILabel label)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected I4, but got Unknown
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Label val = (Label)(object)((label is Label) ? label : null);
if (val != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
LineBreakMode lineBreakMode = val.LineBreakMode;
platformView.LineBreakMode = (int)lineBreakMode switch
{
0 => LineBreakMode.NoWrap,
1 => LineBreakMode.WordWrap,
2 => LineBreakMode.CharacterWrap,
3 => LineBreakMode.HeadTruncation,
4 => LineBreakMode.TailTruncation,
5 => LineBreakMode.MiddleTruncation,
_ => LineBreakMode.TailTruncation,
};
}
}
}
public static void MapTextDecorations(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapMaxLines(LabelHandler handler, ILabel label)
{
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Label val = (Label)(object)((label is Label) ? label : null);
if (val != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.MaxLines = val.MaxLines;
}
}
}
handler.PlatformView.IsUnderline = (label.TextDecorations & TextDecorations.Underline) != 0;
handler.PlatformView.IsStrikethrough = (label.TextDecorations & TextDecorations.Strikethrough) != 0;
}
public static void MapPadding(LabelHandler handler, ILabel label)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Thickness padding = ((IPadding)label).Padding;
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.Padding = new SKRect((float)((Thickness)(ref padding)).Left, (float)((Thickness)(ref padding)).Top, (float)((Thickness)(ref padding)).Right, (float)((Thickness)(ref padding)).Bottom);
}
}
public static void MapLineHeight(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.LineHeight = (float)label.LineHeight;
}
public static void MapBackground(LabelHandler handler, ILabel label)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Paint background = ((IView)label).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapLineBreakMode(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapVerticalLayoutAlignment(LabelHandler handler, ILabel label)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
LayoutAlignment verticalLayoutAlignment = ((IView)label).VerticalLayoutAlignment;
platformView.VerticalOptions = (LayoutOptions)((int)verticalLayoutAlignment switch
{
1 => LayoutOptions.Start,
2 => LayoutOptions.Center,
3 => LayoutOptions.End,
0 => LayoutOptions.Fill,
_ => LayoutOptions.Start,
});
}
}
// LineBreakMode is on Label control, not ILabel interface
if (label is Microsoft.Maui.Controls.Label mauiLabel)
{
handler.PlatformView.LineBreakMode = mauiLabel.LineBreakMode switch
{
Microsoft.Maui.LineBreakMode.NoWrap => Platform.LineBreakMode.NoWrap,
Microsoft.Maui.LineBreakMode.WordWrap => Platform.LineBreakMode.WordWrap,
Microsoft.Maui.LineBreakMode.CharacterWrap => Platform.LineBreakMode.CharacterWrap,
Microsoft.Maui.LineBreakMode.HeadTruncation => Platform.LineBreakMode.HeadTruncation,
Microsoft.Maui.LineBreakMode.TailTruncation => Platform.LineBreakMode.TailTruncation,
Microsoft.Maui.LineBreakMode.MiddleTruncation => Platform.LineBreakMode.MiddleTruncation,
_ => Platform.LineBreakMode.TailTruncation
};
}
}
public static void MapHorizontalLayoutAlignment(LabelHandler handler, ILabel label)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
LayoutAlignment horizontalLayoutAlignment = ((IView)label).HorizontalLayoutAlignment;
platformView.HorizontalOptions = (LayoutOptions)((int)horizontalLayoutAlignment switch
{
1 => LayoutOptions.Start,
2 => LayoutOptions.Center,
3 => LayoutOptions.End,
0 => LayoutOptions.Fill,
_ => LayoutOptions.Start,
});
}
}
public static void MapMaxLines(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
// MaxLines is on Label control, not ILabel interface
if (label is Microsoft.Maui.Controls.Label mauiLabel)
{
handler.PlatformView.MaxLines = mauiLabel.MaxLines;
}
}
public static void MapPadding(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
var padding = label.Padding;
handler.PlatformView.Padding = new SKRect(
(float)padding.Left,
(float)padding.Top,
(float)padding.Right,
(float)padding.Bottom);
}
public static void MapBackground(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
if (label.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapVerticalLayoutAlignment(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalOptions = label.VerticalLayoutAlignment switch
{
Primitives.LayoutAlignment.Start => LayoutOptions.Start,
Primitives.LayoutAlignment.Center => LayoutOptions.Center,
Primitives.LayoutAlignment.End => LayoutOptions.End,
Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
_ => LayoutOptions.Start
};
}
public static void MapHorizontalLayoutAlignment(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalOptions = label.HorizontalLayoutAlignment switch
{
Primitives.LayoutAlignment.Start => LayoutOptions.Start,
Primitives.LayoutAlignment.Center => LayoutOptions.Center,
Primitives.LayoutAlignment.End => LayoutOptions.End,
Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
_ => LayoutOptions.Start
};
}
public static void MapFormattedText(LabelHandler handler, ILabel label)
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Invalid comparison between Unknown and I4
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Invalid comparison between Unknown and I4
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView == null)
{
return;
}
Label val = (Label)(object)((label is Label) ? label : null);
if (val == null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FormattedSpans = null;
return;
}
FormattedString formattedText = val.FormattedText;
if (formattedText == null || formattedText.Spans.Count == 0)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FormattedSpans = null;
return;
}
List<SkiaTextSpan> list = new List<SkiaTextSpan>();
foreach (Span span in formattedText.Spans)
{
SkiaTextSpan skiaTextSpan = new SkiaTextSpan
{
Text = (span.Text ?? ""),
IsBold = ((Enum)span.FontAttributes).HasFlag((Enum)(object)(FontAttributes)1),
IsItalic = ((Enum)span.FontAttributes).HasFlag((Enum)(object)(FontAttributes)2),
IsUnderline = ((span.TextDecorations & 1) > 0),
IsStrikethrough = ((span.TextDecorations & 2) > 0),
CharacterSpacing = (float)span.CharacterSpacing,
LineHeight = (float)span.LineHeight
};
if (span.TextColor != null)
{
skiaTextSpan.TextColor = span.TextColor.ToSKColor();
}
if (span.BackgroundColor != null)
{
skiaTextSpan.BackgroundColor = span.BackgroundColor.ToSKColor();
}
if (!string.IsNullOrEmpty(span.FontFamily))
{
skiaTextSpan.FontFamily = span.FontFamily;
}
if (span.FontSize > 0.0)
{
skiaTextSpan.FontSize = (float)span.FontSize;
}
list.Add(skiaTextSpan);
}
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FormattedSpans = list;
}
}

View File

@@ -1,368 +1,166 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System.Collections.Generic;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Layout on Linux using Skia rendering.
/// Maps ILayout interface to SkiaLayoutView platform view.
/// </summary>
public partial class LayoutHandler : ViewHandler<ILayout, SkiaLayoutView>
public class LayoutHandler : ViewHandler<ILayout, SkiaLayoutView>
{
public static IPropertyMapper<ILayout, LayoutHandler> Mapper = new PropertyMapper<ILayout, LayoutHandler>(ViewHandler.ViewMapper)
{
[nameof(ILayout.ClipsToBounds)] = MapClipsToBounds,
[nameof(IView.Background)] = MapBackground,
[nameof(IPadding.Padding)] = MapPadding,
};
public static IPropertyMapper<ILayout, LayoutHandler> Mapper = (IPropertyMapper<ILayout, LayoutHandler>)(object)new PropertyMapper<ILayout, LayoutHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["ClipsToBounds"] = MapClipsToBounds,
["Background"] = MapBackground,
["Padding"] = MapPadding
};
public static CommandMapper<ILayout, LayoutHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
["Add"] = MapAdd,
["Remove"] = MapRemove,
["Clear"] = MapClear,
["Insert"] = MapInsert,
["Update"] = MapUpdate,
};
public static CommandMapper<ILayout, LayoutHandler> CommandMapper = new CommandMapper<ILayout, LayoutHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper)
{
["Add"] = MapAdd,
["Remove"] = MapRemove,
["Clear"] = MapClear,
["Insert"] = MapInsert,
["Update"] = MapUpdate
};
public LayoutHandler() : base(Mapper, CommandMapper)
{
}
public LayoutHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public LayoutHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public LayoutHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaStackLayout();
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaStackLayout();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
base.ConnectHandler(platformView);
protected override void ConnectHandler(SkiaLayoutView platformView)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
base.ConnectHandler(platformView);
if (base.VirtualView == null || ((ElementHandler)this).MauiContext == null)
{
return;
}
ILayout virtualView = base.VirtualView;
VisualElement val = (VisualElement)(object)((virtualView is VisualElement) ? virtualView : null);
if (val != null && val.BackgroundColor != null)
{
platformView.BackgroundColor = val.BackgroundColor.ToSKColor();
}
for (int i = 0; i < ((ICollection<IView>)base.VirtualView).Count; i++)
{
IView val2 = ((IList<IView>)base.VirtualView)[i];
if (val2 != null)
{
if (val2.Handler == null)
{
val2.Handler = val2.ToViewHandler(((ElementHandler)this).MauiContext);
}
IViewHandler handler = val2.Handler;
if (((handler != null) ? ((IElementHandler)handler).PlatformView : null) is SkiaView child)
{
platformView.AddChild(child);
}
}
}
}
// Create handlers for all children and add them to the platform view
if (VirtualView == null || MauiContext == null) return;
public static void MapClipsToBounds(LayoutHandler handler, ILayout layout)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView != null)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.ClipToBounds = layout.ClipsToBounds;
}
}
// Explicitly map BackgroundColor since it may be set before handler creation
if (VirtualView is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
{
platformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
}
public static void MapBackground(LayoutHandler handler, ILayout layout)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView != null)
{
Paint background = ((IView)layout).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
for (int i = 0; i < VirtualView.Count; i++)
{
var child = VirtualView[i];
if (child == null) continue;
public static void MapAdd(LayoutHandler handler, ILayout layout, object? arg)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView == null || !(arg is LayoutHandlerUpdate { Index: var index } layoutHandlerUpdate))
{
return;
}
IView? view = layoutHandlerUpdate.View;
object obj;
if (view == null)
{
obj = null;
}
else
{
IViewHandler handler2 = view.Handler;
obj = ((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null);
}
if (obj is SkiaView child)
{
if (index >= 0 && index < ((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.Children.Count)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.InsertChild(index, child);
}
else
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.AddChild(child);
}
}
}
// Create handler for child if it doesn't exist
if (child.Handler == null)
{
child.Handler = child.ToHandler(MauiContext);
}
public static void MapRemove(LayoutHandler handler, ILayout layout, object? arg)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView != null && arg is LayoutHandlerUpdate { Index: var index } && index >= 0 && index < ((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.Children.Count)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.RemoveChildAt(index);
}
}
// Add child's platform view to our layout
if (child.Handler?.PlatformView is SkiaView skiaChild)
{
platformView.AddChild(skiaChild);
}
}
}
public static void MapClear(LayoutHandler handler, ILayout layout, object? arg)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView?.ClearChildren();
}
public static void MapClipsToBounds(LayoutHandler handler, ILayout layout)
{
if (handler.PlatformView == null) return;
handler.PlatformView.ClipToBounds = layout.ClipsToBounds;
}
public static void MapInsert(LayoutHandler handler, ILayout layout, object? arg)
{
MapAdd(handler, layout, arg);
}
public static void MapBackground(LayoutHandler handler, ILayout layout)
{
if (handler.PlatformView is null) return;
public static void MapUpdate(LayoutHandler handler, ILayout layout, object? arg)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView?.InvalidateMeasure();
}
if (layout.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapAdd(LayoutHandler handler, ILayout layout, object? arg)
{
if (handler.PlatformView == null || arg is not LayoutHandlerUpdate update)
return;
var index = update.Index;
var child = update.View;
if (child?.Handler?.PlatformView is SkiaView skiaView)
{
if (index >= 0 && index < handler.PlatformView.Children.Count)
handler.PlatformView.InsertChild(index, skiaView);
else
handler.PlatformView.AddChild(skiaView);
}
}
public static void MapRemove(LayoutHandler handler, ILayout layout, object? arg)
{
if (handler.PlatformView == null || arg is not LayoutHandlerUpdate update)
return;
var index = update.Index;
if (index >= 0 && index < handler.PlatformView.Children.Count)
{
handler.PlatformView.RemoveChildAt(index);
}
}
public static void MapClear(LayoutHandler handler, ILayout layout, object? arg)
{
handler.PlatformView?.ClearChildren();
}
public static void MapInsert(LayoutHandler handler, ILayout layout, object? arg)
{
MapAdd(handler, layout, arg);
}
public static void MapUpdate(LayoutHandler handler, ILayout layout, object? arg)
{
// Force re-layout
handler.PlatformView?.InvalidateMeasure();
}
public static void MapPadding(LayoutHandler handler, ILayout layout)
{
if (handler.PlatformView == null) return;
if (layout is IPadding paddable)
{
var padding = paddable.Padding;
handler.PlatformView.Padding = new SKRect(
(float)padding.Left,
(float)padding.Top,
(float)padding.Right,
(float)padding.Bottom);
handler.PlatformView.InvalidateMeasure();
handler.PlatformView.Invalidate();
}
}
}
/// <summary>
/// Update payload for layout changes.
/// </summary>
public class LayoutHandlerUpdate
{
public int Index { get; }
public IView? View { get; }
public LayoutHandlerUpdate(int index, IView? view)
{
Index = index;
View = view;
}
}
/// <summary>
/// Handler for StackLayout on Linux.
/// </summary>
public partial class StackLayoutHandler : LayoutHandler
{
public static new IPropertyMapper<IStackLayout, StackLayoutHandler> Mapper = new PropertyMapper<IStackLayout, StackLayoutHandler>(LayoutHandler.Mapper)
{
[nameof(IStackLayout.Spacing)] = MapSpacing,
};
public StackLayoutHandler() : base(Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaStackLayout();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
// Set orientation first
if (platformView is SkiaStackLayout stackLayout && VirtualView is IStackLayout stackView)
{
// Determine orientation based on view type
if (VirtualView is Microsoft.Maui.Controls.HorizontalStackLayout)
{
stackLayout.Orientation = StackOrientation.Horizontal;
}
else if (VirtualView is Microsoft.Maui.Controls.VerticalStackLayout ||
VirtualView is Microsoft.Maui.Controls.StackLayout)
{
stackLayout.Orientation = StackOrientation.Vertical;
}
stackLayout.Spacing = (float)stackView.Spacing;
}
// Let base handle children
base.ConnectHandler(platformView);
}
public static void MapSpacing(StackLayoutHandler handler, IStackLayout layout)
{
if (handler.PlatformView is SkiaStackLayout stackLayout)
{
stackLayout.Spacing = (float)layout.Spacing;
}
}
}
/// <summary>
/// Handler for Grid on Linux.
/// </summary>
public partial class GridHandler : LayoutHandler
{
public static new IPropertyMapper<IGridLayout, GridHandler> Mapper = new PropertyMapper<IGridLayout, GridHandler>(LayoutHandler.Mapper)
{
[nameof(IGridLayout.RowSpacing)] = MapRowSpacing,
[nameof(IGridLayout.ColumnSpacing)] = MapColumnSpacing,
[nameof(IGridLayout.RowDefinitions)] = MapRowDefinitions,
[nameof(IGridLayout.ColumnDefinitions)] = MapColumnDefinitions,
};
public GridHandler() : base(Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaGrid();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
try
{
// Don't call base - we handle children specially for Grid
if (VirtualView is not IGridLayout gridLayout || MauiContext == null || platformView is not SkiaGrid grid) return;
Console.WriteLine($"[GridHandler] ConnectHandler: {gridLayout.Count} children, {gridLayout.RowDefinitions.Count} rows, {gridLayout.ColumnDefinitions.Count} cols");
// Explicitly map BackgroundColor since it may be set before handler creation
if (VirtualView is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
{
platformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
}
// Explicitly map Padding since it may be set before handler creation
if (VirtualView is IPadding paddable)
{
var padding = paddable.Padding;
platformView.Padding = new SKRect(
(float)padding.Left,
(float)padding.Top,
(float)padding.Right,
(float)padding.Bottom);
Console.WriteLine($"[GridHandler] Applied Padding: L={padding.Left}, T={padding.Top}, R={padding.Right}, B={padding.Bottom}");
}
// Map row/column definitions first
MapRowDefinitions(this, gridLayout);
MapColumnDefinitions(this, gridLayout);
// Add each child with its row/column position
for (int i = 0; i < gridLayout.Count; i++)
{
var child = gridLayout[i];
if (child == null) continue;
Console.WriteLine($"[GridHandler] Processing child {i}: {child.GetType().Name}");
// Create handler for child if it doesn't exist
if (child.Handler == null)
{
child.Handler = child.ToHandler(MauiContext);
}
// Get grid position from attached properties
int row = 0, column = 0, rowSpan = 1, columnSpan = 1;
if (child is Microsoft.Maui.Controls.View mauiView)
{
row = Microsoft.Maui.Controls.Grid.GetRow(mauiView);
column = Microsoft.Maui.Controls.Grid.GetColumn(mauiView);
rowSpan = Microsoft.Maui.Controls.Grid.GetRowSpan(mauiView);
columnSpan = Microsoft.Maui.Controls.Grid.GetColumnSpan(mauiView);
}
Console.WriteLine($"[GridHandler] Child {i} at row={row}, col={column}, handler={child.Handler?.GetType().Name}");
// Add child's platform view to our grid
if (child.Handler?.PlatformView is SkiaView skiaChild)
{
grid.AddChild(skiaChild, row, column, rowSpan, columnSpan);
Console.WriteLine($"[GridHandler] Added child {i} to grid");
}
}
Console.WriteLine($"[GridHandler] ConnectHandler complete");
}
catch (Exception ex)
{
Console.WriteLine($"[GridHandler] EXCEPTION in ConnectHandler: {ex.GetType().Name}: {ex.Message}");
Console.WriteLine($"[GridHandler] Stack trace: {ex.StackTrace}");
throw;
}
}
public static void MapRowSpacing(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is SkiaGrid grid)
{
grid.RowSpacing = (float)layout.RowSpacing;
}
}
public static void MapColumnSpacing(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is SkiaGrid grid)
{
grid.ColumnSpacing = (float)layout.ColumnSpacing;
}
}
public static void MapRowDefinitions(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is not SkiaGrid grid) return;
grid.RowDefinitions.Clear();
foreach (var rowDef in layout.RowDefinitions)
{
var height = rowDef.Height;
if (height.IsAbsolute)
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)height.Value, Microsoft.Maui.Platform.GridUnitType.Absolute));
else if (height.IsAuto)
grid.RowDefinitions.Add(Microsoft.Maui.Platform.GridLength.Auto);
else // Star
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)height.Value, Microsoft.Maui.Platform.GridUnitType.Star));
}
}
public static void MapColumnDefinitions(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is not SkiaGrid grid) return;
grid.ColumnDefinitions.Clear();
foreach (var colDef in layout.ColumnDefinitions)
{
var width = colDef.Width;
if (width.IsAbsolute)
grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)width.Value, Microsoft.Maui.Platform.GridUnitType.Absolute));
else if (width.IsAuto)
grid.ColumnDefinitions.Add(Microsoft.Maui.Platform.GridLength.Auto);
else // Star
grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)width.Value, Microsoft.Maui.Platform.GridUnitType.Star));
}
}
public static void MapPadding(LayoutHandler handler, ILayout layout)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView != null)
{
if (layout != null)
{
Thickness padding = ((IPadding)layout).Padding;
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.Padding = new SKRect((float)((Thickness)(ref padding)).Left, (float)((Thickness)(ref padding)).Top, (float)((Thickness)(ref padding)).Right, (float)((Thickness)(ref padding)).Bottom);
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.InvalidateMeasure();
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.Invalidate();
}
}
}
}

View File

@@ -0,0 +1,14 @@
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class LayoutHandlerUpdate
{
public int Index { get; }
public IView? View { get; }
public LayoutHandlerUpdate(int index, IView? view)
{
Index = index;
View = view;
}
}

View File

@@ -0,0 +1,64 @@
using System.Collections.Generic;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class LinuxApplicationContext
{
private readonly List<IWindow> _windows = new List<IWindow>();
private IApplication? _application;
public IApplication? Application
{
get
{
return _application;
}
set
{
_application = value;
if (_application == null)
{
return;
}
foreach (IWindow window in _application.Windows)
{
if (!_windows.Contains(window))
{
_windows.Add(window);
}
}
}
}
public IReadOnlyList<IWindow> Windows => _windows;
public IWindow? MainWindow
{
get
{
if (_windows.Count <= 0)
{
return null;
}
return _windows[0];
}
}
public void OpenWindow(IWindow window)
{
if (!_windows.Contains(window))
{
_windows.Add(window);
}
}
public void CloseWindow(IWindow window)
{
_windows.Remove(window);
if (_windows.Count == 0)
{
LinuxApplication.Current?.MainWindow?.Stop();
}
}
}

View File

@@ -1,381 +1,448 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using SkiaSharp;
using Svg.Skia;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for NavigationPage on Linux using Skia rendering.
/// </summary>
public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNavigationPage>
public class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNavigationPage>
{
public static IPropertyMapper<NavigationPage, NavigationPageHandler> Mapper =
new PropertyMapper<NavigationPage, NavigationPageHandler>(ViewHandler.ViewMapper)
{
[nameof(NavigationPage.BarBackgroundColor)] = MapBarBackgroundColor,
[nameof(NavigationPage.BarBackground)] = MapBarBackground,
[nameof(NavigationPage.BarTextColor)] = MapBarTextColor,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<NavigationPage, NavigationPageHandler> Mapper = (IPropertyMapper<NavigationPage, NavigationPageHandler>)(object)new PropertyMapper<NavigationPage, NavigationPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["BarBackgroundColor"] = MapBarBackgroundColor,
["BarBackground"] = MapBarBackground,
["BarTextColor"] = MapBarTextColor,
["Background"] = MapBackground
};
public static CommandMapper<NavigationPage, NavigationPageHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
[nameof(IStackNavigationView.RequestNavigation)] = MapRequestNavigation,
};
public static CommandMapper<NavigationPage, NavigationPageHandler> CommandMapper = new CommandMapper<NavigationPage, NavigationPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["RequestNavigation"] = MapRequestNavigation };
public NavigationPageHandler() : base(Mapper, CommandMapper)
{
}
private readonly Dictionary<Page, (SkiaPage, INotifyCollectionChanged)> _toolbarSubscriptions = new Dictionary<Page, (SkiaPage, INotifyCollectionChanged)>();
public NavigationPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public NavigationPageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
protected override SkiaNavigationPage CreatePlatformView()
{
return new SkiaNavigationPage();
}
public NavigationPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override void ConnectHandler(SkiaNavigationPage platformView)
{
base.ConnectHandler(platformView);
platformView.Pushed += OnPushed;
platformView.Popped += OnPopped;
platformView.PoppedToRoot += OnPoppedToRoot;
protected override SkiaNavigationPage CreatePlatformView()
{
return new SkiaNavigationPage();
}
// Subscribe to navigation events from virtual view
if (VirtualView != null)
{
VirtualView.Pushed += OnVirtualViewPushed;
VirtualView.Popped += OnVirtualViewPopped;
VirtualView.PoppedToRoot += OnVirtualViewPoppedToRoot;
protected override void ConnectHandler(SkiaNavigationPage platformView)
{
base.ConnectHandler(platformView);
platformView.Pushed += OnPushed;
platformView.Popped += OnPopped;
platformView.PoppedToRoot += OnPoppedToRoot;
if (base.VirtualView != null)
{
base.VirtualView.Pushed += OnVirtualViewPushed;
base.VirtualView.Popped += OnVirtualViewPopped;
base.VirtualView.PoppedToRoot += OnVirtualViewPoppedToRoot;
SetupNavigationStack();
}
}
// Set up initial navigation stack
SetupNavigationStack();
}
}
protected override void DisconnectHandler(SkiaNavigationPage platformView)
{
platformView.Pushed -= OnPushed;
platformView.Popped -= OnPopped;
platformView.PoppedToRoot -= OnPoppedToRoot;
if (base.VirtualView != null)
{
base.VirtualView.Pushed -= OnVirtualViewPushed;
base.VirtualView.Popped -= OnVirtualViewPopped;
base.VirtualView.PoppedToRoot -= OnVirtualViewPoppedToRoot;
}
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaNavigationPage platformView)
{
platformView.Pushed -= OnPushed;
platformView.Popped -= OnPopped;
platformView.PoppedToRoot -= OnPoppedToRoot;
private void SetupNavigationStack()
{
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
if (base.VirtualView == null || base.PlatformView == null || ((ElementHandler)this).MauiContext == null)
{
return;
}
List<Page> list = ((NavigableElement)base.VirtualView).Navigation.NavigationStack.ToList();
Console.WriteLine($"[NavigationPageHandler] Setting up {list.Count} pages");
if (list.Count == 0 && base.VirtualView.CurrentPage != null)
{
Console.WriteLine("[NavigationPageHandler] No pages in stack, using CurrentPage: " + base.VirtualView.CurrentPage.Title);
list.Add(base.VirtualView.CurrentPage);
}
foreach (Page item in list)
{
if (((VisualElement)item).Handler == null)
{
Console.WriteLine("[NavigationPageHandler] Creating handler for: " + item.Title);
((VisualElement)item).Handler = ((IView)(object)item).ToViewHandler(((ElementHandler)this).MauiContext);
}
Console.WriteLine("[NavigationPageHandler] Page handler type: " + ((object)((VisualElement)item).Handler)?.GetType().Name);
IViewHandler handler = ((VisualElement)item).Handler;
Console.WriteLine("[NavigationPageHandler] Page PlatformView type: " + ((handler == null) ? null : ((IElementHandler)handler).PlatformView?.GetType().Name));
IViewHandler handler2 = ((VisualElement)item).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaPage skiaPage)
{
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = base.PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = base.PlatformView.BarTextColor;
skiaPage.Title = item.Title ?? "";
Console.WriteLine("[NavigationPageHandler] SkiaPage content: " + (((object)skiaPage.Content)?.GetType().Name ?? "null"));
if (skiaPage.Content == null)
{
ContentPage val = (ContentPage)(object)((item is ContentPage) ? item : null);
if (val != null && val.Content != null)
{
Console.WriteLine("[NavigationPageHandler] Content is null, manually creating handler for: " + ((object)val.Content).GetType().Name);
if (((VisualElement)val.Content).Handler == null)
{
((VisualElement)val.Content).Handler = ((IView)(object)val.Content).ToViewHandler(((ElementHandler)this).MauiContext);
}
IViewHandler handler3 = ((VisualElement)val.Content).Handler;
if (((handler3 != null) ? ((IElementHandler)handler3).PlatformView : null) is SkiaView skiaView)
{
skiaPage.Content = skiaView;
Console.WriteLine("[NavigationPageHandler] Set content to: " + ((object)skiaView).GetType().Name);
}
}
}
MapToolbarItems(skiaPage, item);
if (base.PlatformView.StackDepth == 0)
{
Console.WriteLine("[NavigationPageHandler] Setting root page: " + item.Title);
base.PlatformView.SetRootPage(skiaPage);
}
else
{
Console.WriteLine("[NavigationPageHandler] Pushing page: " + item.Title);
base.PlatformView.Push(skiaPage, animated: false);
}
}
else
{
Console.WriteLine("[NavigationPageHandler] Failed to get SkiaPage for: " + item.Title);
}
}
}
if (VirtualView != null)
{
VirtualView.Pushed -= OnVirtualViewPushed;
VirtualView.Popped -= OnVirtualViewPopped;
VirtualView.PoppedToRoot -= OnVirtualViewPoppedToRoot;
}
private void MapToolbarItems(SkiaPage skiaPage, Page page)
{
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Invalid comparison between Unknown and I4
if (!(skiaPage is SkiaContentPage skiaContentPage))
{
return;
}
Console.WriteLine($"[NavigationPageHandler] MapToolbarItems for '{page.Title}', count={page.ToolbarItems.Count}");
skiaContentPage.ToolbarItems.Clear();
foreach (ToolbarItem toolbarItem2 in page.ToolbarItems)
{
Console.WriteLine($"[NavigationPageHandler] Adding toolbar item: '{((MenuItem)toolbarItem2).Text}', IconImageSource={((MenuItem)toolbarItem2).IconImageSource}, Order={toolbarItem2.Order}");
SkiaToolbarItemOrder order = (((int)toolbarItem2.Order == 2) ? SkiaToolbarItemOrder.Secondary : SkiaToolbarItemOrder.Primary);
ToolbarItem toolbarItem = toolbarItem2;
RelayCommand command = new RelayCommand(delegate
{
Console.WriteLine("[NavigationPageHandler] ToolbarItem '" + ((MenuItem)toolbarItem).Text + "' clicked, invoking...");
IMenuItemController val2 = (IMenuItemController)(object)toolbarItem;
if (val2 != null)
{
val2.Activate();
}
else
{
((MenuItem)toolbarItem).Command?.Execute(((MenuItem)toolbarItem).CommandParameter);
}
});
SKBitmap icon = null;
ImageSource iconImageSource = ((MenuItem)toolbarItem2).IconImageSource;
FileImageSource val = (FileImageSource)(object)((iconImageSource is FileImageSource) ? iconImageSource : null);
if (val != null && !string.IsNullOrEmpty(val.File))
{
icon = LoadToolbarIcon(val.File);
}
skiaContentPage.ToolbarItems.Add(new SkiaToolbarItem
{
Text = (((MenuItem)toolbarItem2).Text ?? ""),
Icon = icon,
Order = order,
Command = command
});
}
if (page.ToolbarItems is INotifyCollectionChanged notifyCollectionChanged && !_toolbarSubscriptions.ContainsKey(page))
{
Console.WriteLine("[NavigationPageHandler] Subscribing to ToolbarItems changes for '" + page.Title + "'");
notifyCollectionChanged.CollectionChanged += delegate(object? s, NotifyCollectionChangedEventArgs e)
{
Console.WriteLine($"[NavigationPageHandler] ToolbarItems changed for '{page.Title}', action={e.Action}");
MapToolbarItems(skiaPage, page);
skiaPage.Invalidate();
};
_toolbarSubscriptions[page] = (skiaPage, notifyCollectionChanged);
}
}
base.DisconnectHandler(platformView);
}
private SKBitmap? LoadToolbarIcon(string fileName)
{
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Expected O, but got Unknown
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Expected O, but got Unknown
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Expected O, but got Unknown
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
try
{
string baseDirectory = AppContext.BaseDirectory;
string text = Path.Combine(baseDirectory, fileName);
string text2 = Path.Combine(baseDirectory, Path.ChangeExtension(fileName, ".svg"));
Console.WriteLine("[NavigationPageHandler] LoadToolbarIcon: Looking for " + fileName);
Console.WriteLine($"[NavigationPageHandler] Trying PNG: {text} (exists: {File.Exists(text)})");
Console.WriteLine($"[NavigationPageHandler] Trying SVG: {text2} (exists: {File.Exists(text2)})");
if (File.Exists(text2))
{
SKSvg val = new SKSvg();
try
{
val.Load(text2);
if (val.Picture != null)
{
SKRect cullRect = val.Picture.CullRect;
float num = 24f / Math.Max(((SKRect)(ref cullRect)).Width, ((SKRect)(ref cullRect)).Height);
SKBitmap val2 = new SKBitmap(24, 24, false);
SKCanvas val3 = new SKCanvas(val2);
try
{
val3.Clear(SKColors.Transparent);
val3.Scale(num);
val3.DrawPicture(val.Picture, (SKPaint)null);
Console.WriteLine("[NavigationPageHandler] Loaded SVG icon: " + text2);
return val2;
}
finally
{
((IDisposable)val3)?.Dispose();
}
}
}
finally
{
((IDisposable)val)?.Dispose();
}
}
if (File.Exists(text))
{
using (FileStream fileStream = File.OpenRead(text))
{
SKBitmap result = SKBitmap.Decode((Stream)fileStream);
Console.WriteLine("[NavigationPageHandler] Loaded PNG icon: " + text);
return result;
}
}
Console.WriteLine("[NavigationPageHandler] Icon not found: " + fileName);
return null;
}
catch (Exception ex)
{
Console.WriteLine("[NavigationPageHandler] Error loading icon " + fileName + ": " + ex.Message);
return null;
}
}
private void SetupNavigationStack()
{
if (VirtualView == null || PlatformView == null || MauiContext == null) return;
private void OnVirtualViewPushed(object? sender, NavigationEventArgs e)
{
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
try
{
Page page = e.Page;
Console.WriteLine("[NavigationPageHandler] VirtualView Pushed: " + ((page != null) ? page.Title : null));
if (e.Page == null || base.PlatformView == null || ((ElementHandler)this).MauiContext == null)
{
return;
}
if (((VisualElement)e.Page).Handler == null)
{
Console.WriteLine("[NavigationPageHandler] Creating handler for page: " + ((object)e.Page).GetType().Name);
((VisualElement)e.Page).Handler = ((IView)(object)e.Page).ToViewHandler(((ElementHandler)this).MauiContext);
Console.WriteLine("[NavigationPageHandler] Handler created: " + ((object)((VisualElement)e.Page).Handler)?.GetType().Name);
}
IViewHandler handler = ((VisualElement)e.Page).Handler;
if (((handler != null) ? ((IElementHandler)handler).PlatformView : null) is SkiaPage skiaPage)
{
Console.WriteLine("[NavigationPageHandler] Setting up skiaPage, content: " + (((object)skiaPage.Content)?.GetType().Name ?? "null"));
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = base.PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = base.PlatformView.BarTextColor;
skiaPage.Title = e.Page.Title ?? "";
if (skiaPage.Content == null)
{
Page page2 = e.Page;
ContentPage val = (ContentPage)(object)((page2 is ContentPage) ? page2 : null);
if (val != null && val.Content != null)
{
Console.WriteLine("[NavigationPageHandler] Content is null, creating handler for: " + ((object)val.Content).GetType().Name);
if (((VisualElement)val.Content).Handler == null)
{
((VisualElement)val.Content).Handler = ((IView)(object)val.Content).ToViewHandler(((ElementHandler)this).MauiContext);
}
IViewHandler handler2 = ((VisualElement)val.Content).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
skiaPage.Content = skiaView;
Console.WriteLine("[NavigationPageHandler] Set content to: " + ((object)skiaView).GetType().Name);
}
}
}
Console.WriteLine("[NavigationPageHandler] Mapping toolbar items");
MapToolbarItems(skiaPage, e.Page);
Console.WriteLine("[NavigationPageHandler] Pushing page to platform");
base.PlatformView.Push(skiaPage, animated: false);
Console.WriteLine($"[NavigationPageHandler] Push complete, thread={Environment.CurrentManagedThreadId}");
}
Console.WriteLine("[NavigationPageHandler] OnVirtualViewPushed returning");
}
catch (Exception ex)
{
Console.WriteLine("[NavigationPageHandler] EXCEPTION in OnVirtualViewPushed: " + ex.GetType().Name + ": " + ex.Message);
Console.WriteLine("[NavigationPageHandler] Stack trace: " + ex.StackTrace);
throw;
}
}
// Get all pages in the navigation stack
var pages = VirtualView.Navigation.NavigationStack.ToList();
Console.WriteLine($"[NavigationPageHandler] Setting up {pages.Count} pages");
private void OnVirtualViewPopped(object? sender, NavigationEventArgs e)
{
Page page = e.Page;
Console.WriteLine("[NavigationPageHandler] VirtualView Popped: " + ((page != null) ? page.Title : null));
base.PlatformView?.Pop();
}
// If no pages in stack, check CurrentPage
if (pages.Count == 0 && VirtualView.CurrentPage != null)
{
Console.WriteLine($"[NavigationPageHandler] No pages in stack, using CurrentPage: {VirtualView.CurrentPage.Title}");
pages.Add(VirtualView.CurrentPage);
}
private void OnVirtualViewPoppedToRoot(object? sender, NavigationEventArgs e)
{
Console.WriteLine("[NavigationPageHandler] VirtualView PoppedToRoot");
base.PlatformView?.PopToRoot();
}
foreach (var page in pages)
{
// Ensure the page has a handler
if (page.Handler == null)
{
Console.WriteLine($"[NavigationPageHandler] Creating handler for: {page.Title}");
page.Handler = page.ToHandler(MauiContext);
}
private void OnPushed(object? sender, NavigationEventArgs e)
{
}
Console.WriteLine($"[NavigationPageHandler] Page handler type: {page.Handler?.GetType().Name}");
Console.WriteLine($"[NavigationPageHandler] Page PlatformView type: {page.Handler?.PlatformView?.GetType().Name}");
private void OnPopped(object? sender, NavigationEventArgs e)
{
NavigationPage virtualView = base.VirtualView;
if (virtualView != null && ((NavigableElement)virtualView).Navigation.NavigationStack.Count > 1)
{
((NavigableElement)base.VirtualView).Navigation.RemovePage(((NavigableElement)base.VirtualView).Navigation.NavigationStack.Last());
}
}
if (page.Handler?.PlatformView is SkiaPage skiaPage)
{
// Set navigation bar properties
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = PlatformView.BarTextColor;
skiaPage.Title = page.Title ?? "";
private void OnPoppedToRoot(object? sender, NavigationEventArgs e)
{
}
Console.WriteLine($"[NavigationPageHandler] SkiaPage content: {skiaPage.Content?.GetType().Name ?? "null"}");
public static void MapBarBackgroundColor(NavigationPageHandler handler, NavigationPage navigationPage)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView != null && navigationPage.BarBackgroundColor != null)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarBackgroundColor = navigationPage.BarBackgroundColor.ToSKColor();
}
}
// If content is null, try to get it from ContentPage
if (skiaPage.Content == null && page is ContentPage contentPage && contentPage.Content != null)
{
Console.WriteLine($"[NavigationPageHandler] Content is null, manually creating handler for: {contentPage.Content.GetType().Name}");
if (contentPage.Content.Handler == null)
{
contentPage.Content.Handler = contentPage.Content.ToHandler(MauiContext);
}
if (contentPage.Content.Handler?.PlatformView is SkiaView skiaContent)
{
skiaPage.Content = skiaContent;
Console.WriteLine($"[NavigationPageHandler] Set content to: {skiaContent.GetType().Name}");
}
}
public static void MapBarBackground(NavigationPageHandler handler, NavigationPage navigationPage)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView != null)
{
Brush barBackground = navigationPage.BarBackground;
SolidColorBrush val = (SolidColorBrush)(object)((barBackground is SolidColorBrush) ? barBackground : null);
if (val != null)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarBackgroundColor = val.Color.ToSKColor();
}
}
}
// Map toolbar items
MapToolbarItems(skiaPage, page);
public static void MapBarTextColor(NavigationPageHandler handler, NavigationPage navigationPage)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView != null && navigationPage.BarTextColor != null)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarTextColor = navigationPage.BarTextColor.ToSKColor();
}
}
if (PlatformView.StackDepth == 0)
{
Console.WriteLine($"[NavigationPageHandler] Setting root page: {page.Title}");
PlatformView.SetRootPage(skiaPage);
}
else
{
Console.WriteLine($"[NavigationPageHandler] Pushing page: {page.Title}");
PlatformView.Push(skiaPage, false);
}
}
else
{
Console.WriteLine($"[NavigationPageHandler] Failed to get SkiaPage for: {page.Title}");
}
}
}
public static void MapBackground(NavigationPageHandler handler, NavigationPage navigationPage)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView != null)
{
Brush background = ((VisualElement)navigationPage).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
private readonly Dictionary<Page, (SkiaPage, INotifyCollectionChanged)> _toolbarSubscriptions = new();
private void MapToolbarItems(SkiaPage skiaPage, Page page)
{
if (skiaPage is SkiaContentPage contentPage)
{
Console.WriteLine($"[NavigationPageHandler] MapToolbarItems for '{page.Title}', count={page.ToolbarItems.Count}");
contentPage.ToolbarItems.Clear();
foreach (var item in page.ToolbarItems)
{
Console.WriteLine($"[NavigationPageHandler] Adding toolbar item: '{item.Text}', Order={item.Order}");
// Default and Primary should both be treated as Primary (shown in toolbar)
// Only Secondary goes to overflow menu
var order = item.Order == ToolbarItemOrder.Secondary
? SkiaToolbarItemOrder.Secondary
: SkiaToolbarItemOrder.Primary;
// Create a command that invokes the Clicked event
var toolbarItem = item; // Capture for closure
var clickCommand = new RelayCommand(() =>
{
Console.WriteLine($"[NavigationPageHandler] ToolbarItem '{toolbarItem.Text}' clicked, invoking...");
// Use IMenuItemController to send the click
if (toolbarItem is IMenuItemController menuController)
{
menuController.Activate();
}
else
{
// Fallback: invoke Command if set
toolbarItem.Command?.Execute(toolbarItem.CommandParameter);
}
});
contentPage.ToolbarItems.Add(new SkiaToolbarItem
{
Text = item.Text ?? "",
Order = order,
Command = clickCommand
});
}
// Subscribe to ToolbarItems changes if not already subscribed
if (page.ToolbarItems is INotifyCollectionChanged notifyCollection && !_toolbarSubscriptions.ContainsKey(page))
{
Console.WriteLine($"[NavigationPageHandler] Subscribing to ToolbarItems changes for '{page.Title}'");
notifyCollection.CollectionChanged += (s, e) =>
{
Console.WriteLine($"[NavigationPageHandler] ToolbarItems changed for '{page.Title}', action={e.Action}");
MapToolbarItems(skiaPage, page);
skiaPage.Invalidate();
};
_toolbarSubscriptions[page] = (skiaPage, notifyCollection);
}
}
}
private void OnVirtualViewPushed(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
{
try
{
Console.WriteLine($"[NavigationPageHandler] VirtualView Pushed: {e.Page?.Title}");
if (e.Page == null || PlatformView == null || MauiContext == null) return;
// Ensure the page has a handler
if (e.Page.Handler == null)
{
Console.WriteLine($"[NavigationPageHandler] Creating handler for page: {e.Page.GetType().Name}");
e.Page.Handler = e.Page.ToHandler(MauiContext);
Console.WriteLine($"[NavigationPageHandler] Handler created: {e.Page.Handler?.GetType().Name}");
}
if (e.Page.Handler?.PlatformView is SkiaPage skiaPage)
{
Console.WriteLine($"[NavigationPageHandler] Setting up skiaPage, content: {skiaPage.Content?.GetType().Name ?? "null"}");
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = PlatformView.BarTextColor;
Console.WriteLine($"[NavigationPageHandler] Mapping toolbar items");
MapToolbarItems(skiaPage, e.Page);
Console.WriteLine($"[NavigationPageHandler] Pushing page to platform");
PlatformView.Push(skiaPage, true);
Console.WriteLine($"[NavigationPageHandler] Push complete");
}
}
catch (Exception ex)
{
Console.WriteLine($"[NavigationPageHandler] EXCEPTION in OnVirtualViewPushed: {ex.GetType().Name}: {ex.Message}");
Console.WriteLine($"[NavigationPageHandler] Stack trace: {ex.StackTrace}");
throw;
}
}
private void OnVirtualViewPopped(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
{
Console.WriteLine($"[NavigationPageHandler] VirtualView Popped: {e.Page?.Title}");
// Pop on the platform side to sync with MAUI navigation
PlatformView?.Pop(true);
}
private void OnVirtualViewPoppedToRoot(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
{
Console.WriteLine($"[NavigationPageHandler] VirtualView PoppedToRoot");
PlatformView?.PopToRoot(true);
}
private void OnPushed(object? sender, NavigationEventArgs e)
{
// Navigation was completed on platform side
}
private void OnPopped(object? sender, NavigationEventArgs e)
{
// Sync back to virtual view - pop from MAUI navigation stack
if (VirtualView?.Navigation.NavigationStack.Count > 1)
{
// Don't trigger another pop on platform side
VirtualView.Navigation.RemovePage(VirtualView.Navigation.NavigationStack.Last());
}
}
private void OnPoppedToRoot(object? sender, NavigationEventArgs e)
{
// Navigation was reset
}
public static void MapBarBackgroundColor(NavigationPageHandler handler, NavigationPage navigationPage)
{
if (handler.PlatformView is null) return;
if (navigationPage.BarBackgroundColor is not null)
{
handler.PlatformView.BarBackgroundColor = navigationPage.BarBackgroundColor.ToSKColor();
}
}
public static void MapBarBackground(NavigationPageHandler handler, NavigationPage navigationPage)
{
if (handler.PlatformView is null) return;
if (navigationPage.BarBackground is SolidColorBrush solidBrush)
{
handler.PlatformView.BarBackgroundColor = solidBrush.Color.ToSKColor();
}
}
public static void MapBarTextColor(NavigationPageHandler handler, NavigationPage navigationPage)
{
if (handler.PlatformView is null) return;
if (navigationPage.BarTextColor is not null)
{
handler.PlatformView.BarTextColor = navigationPage.BarTextColor.ToSKColor();
}
}
public static void MapBackground(NavigationPageHandler handler, NavigationPage navigationPage)
{
if (handler.PlatformView is null) return;
if (navigationPage.Background is SolidColorBrush solidBrush)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
}
}
public static void MapRequestNavigation(NavigationPageHandler handler, NavigationPage navigationPage, object? args)
{
if (handler.PlatformView is null || handler.MauiContext is null || args is not NavigationRequest request)
return;
Console.WriteLine($"[NavigationPageHandler] MapRequestNavigation: {request.NavigationStack.Count} pages");
// Handle navigation request
foreach (var view in request.NavigationStack)
{
if (view is not Page page) continue;
// Ensure handler exists
if (page.Handler == null)
{
page.Handler = page.ToHandler(handler.MauiContext);
}
if (page.Handler?.PlatformView is SkiaPage skiaPage)
{
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = handler.PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = handler.PlatformView.BarTextColor;
handler.MapToolbarItems(skiaPage, page);
if (handler.PlatformView.StackDepth == 0)
{
handler.PlatformView.SetRootPage(skiaPage);
}
else
{
handler.PlatformView.Push(skiaPage, request.Animated);
}
}
}
}
}
/// <summary>
/// Simple relay command for invoking actions.
/// </summary>
internal class RelayCommand : System.Windows.Input.ICommand
{
private readonly Action _execute;
private readonly Func<bool>? _canExecute;
public RelayCommand(Action execute, Func<bool>? canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public event EventHandler? CanExecuteChanged;
public bool CanExecute(object? parameter) => _canExecute?.Invoke() ?? true;
public void Execute(object? parameter) => _execute();
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
public static void MapRequestNavigation(NavigationPageHandler handler, NavigationPage navigationPage, object? args)
{
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
NavigationRequest val = (NavigationRequest)((args is NavigationRequest) ? args : null);
if (val == null)
{
return;
}
Console.WriteLine($"[NavigationPageHandler] MapRequestNavigation: {val.NavigationStack.Count} pages");
foreach (IView item in val.NavigationStack)
{
Page val2 = (Page)(object)((item is Page) ? item : null);
if (val2 == null)
{
continue;
}
if (((VisualElement)val2).Handler == null)
{
((VisualElement)val2).Handler = ((IView)(object)val2).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = ((VisualElement)val2).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaPage skiaPage)
{
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = ((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = ((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarTextColor;
handler.MapToolbarItems(skiaPage, val2);
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.StackDepth == 0)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.SetRootPage(skiaPage);
}
else
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.Push(skiaPage, val.Animated);
}
}
}
}
}

View File

@@ -1,166 +1,124 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Base handler for Page on Linux using Skia rendering.
/// </summary>
public partial class PageHandler : ViewHandler<Page, SkiaPage>
public class PageHandler : ViewHandler<Page, SkiaPage>
{
public static IPropertyMapper<Page, PageHandler> Mapper =
new PropertyMapper<Page, PageHandler>(ViewHandler.ViewMapper)
{
[nameof(Page.Title)] = MapTitle,
[nameof(Page.BackgroundImageSource)] = MapBackgroundImageSource,
[nameof(Page.Padding)] = MapPadding,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<Page, PageHandler> Mapper = (IPropertyMapper<Page, PageHandler>)(object)new PropertyMapper<Page, PageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Title"] = MapTitle,
["BackgroundImageSource"] = MapBackgroundImageSource,
["Padding"] = MapPadding,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static CommandMapper<Page, PageHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<Page, PageHandler> CommandMapper = new CommandMapper<Page, PageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public PageHandler() : base(Mapper, CommandMapper)
{
}
public PageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public PageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public PageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaPage CreatePlatformView()
{
return new SkiaPage();
}
protected override SkiaPage CreatePlatformView()
{
return new SkiaPage();
}
protected override void ConnectHandler(SkiaPage platformView)
{
base.ConnectHandler(platformView);
platformView.Appearing += OnAppearing;
platformView.Disappearing += OnDisappearing;
}
protected override void ConnectHandler(SkiaPage platformView)
{
base.ConnectHandler(platformView);
platformView.Appearing += OnAppearing;
platformView.Disappearing += OnDisappearing;
}
protected override void DisconnectHandler(SkiaPage platformView)
{
platformView.Appearing -= OnAppearing;
platformView.Disappearing -= OnDisappearing;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaPage platformView)
{
platformView.Appearing -= OnAppearing;
platformView.Disappearing -= OnDisappearing;
base.DisconnectHandler(platformView);
}
private void OnAppearing(object? sender, EventArgs e)
{
Console.WriteLine($"[PageHandler] OnAppearing received for: {VirtualView?.Title}");
(VirtualView as IPageController)?.SendAppearing();
}
private void OnAppearing(object? sender, EventArgs e)
{
Page virtualView = base.VirtualView;
Console.WriteLine("[PageHandler] OnAppearing received for: " + ((virtualView != null) ? virtualView.Title : null));
Page virtualView2 = base.VirtualView;
if (virtualView2 != null)
{
((IPageController)virtualView2).SendAppearing();
}
}
private void OnDisappearing(object? sender, EventArgs e)
{
(VirtualView as IPageController)?.SendDisappearing();
}
private void OnDisappearing(object? sender, EventArgs e)
{
Page virtualView = base.VirtualView;
if (virtualView != null)
{
((IPageController)virtualView).SendDisappearing();
}
}
public static void MapTitle(PageHandler handler, Page page)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Title = page.Title ?? "";
}
public static void MapTitle(PageHandler handler, Page page)
{
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView != null)
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.Title = page.Title ?? "";
}
}
public static void MapBackgroundImageSource(PageHandler handler, Page page)
{
// Background image would be loaded and set here
// For now, we just invalidate
handler.PlatformView?.Invalidate();
}
public static void MapBackgroundImageSource(PageHandler handler, Page page)
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView?.Invalidate();
}
public static void MapPadding(PageHandler handler, Page page)
{
if (handler.PlatformView is null) return;
public static void MapPadding(PageHandler handler, Page page)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView != null)
{
Thickness padding = page.Padding;
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.PaddingLeft = (float)((Thickness)(ref padding)).Left;
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.PaddingTop = (float)((Thickness)(ref padding)).Top;
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.PaddingRight = (float)((Thickness)(ref padding)).Right;
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.PaddingBottom = (float)((Thickness)(ref padding)).Bottom;
}
}
var padding = page.Padding;
handler.PlatformView.PaddingLeft = (float)padding.Left;
handler.PlatformView.PaddingTop = (float)padding.Top;
handler.PlatformView.PaddingRight = (float)padding.Right;
handler.PlatformView.PaddingBottom = (float)padding.Bottom;
}
public static void MapBackground(PageHandler handler, Page page)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView != null)
{
Brush background = ((VisualElement)page).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null)
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapBackground(PageHandler handler, Page page)
{
if (handler.PlatformView is null) return;
if (page.Background is SolidColorBrush solidBrush)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
}
}
}
/// <summary>
/// Handler for ContentPage on Linux using Skia rendering.
/// </summary>
public partial class ContentPageHandler : PageHandler
{
public static new IPropertyMapper<ContentPage, ContentPageHandler> Mapper =
new PropertyMapper<ContentPage, ContentPageHandler>(PageHandler.Mapper)
{
[nameof(ContentPage.Content)] = MapContent,
};
public static new CommandMapper<ContentPage, ContentPageHandler> CommandMapper =
new(PageHandler.CommandMapper)
{
};
public ContentPageHandler() : base(Mapper, CommandMapper)
{
}
public ContentPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaPage CreatePlatformView()
{
return new SkiaContentPage();
}
public static void MapContent(ContentPageHandler handler, ContentPage page)
{
if (handler.PlatformView is null || handler.MauiContext is null) return;
// Get the platform view for the content
var content = page.Content;
if (content != null)
{
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
Console.WriteLine($"[ContentPageHandler] Creating handler for content: {content.GetType().Name}");
content.Handler = content.ToHandler(handler.MauiContext);
}
// The content's handler should provide the platform view
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
Console.WriteLine($"[ContentPageHandler] Setting content: {skiaContent.GetType().Name}");
handler.PlatformView.Content = skiaContent;
}
else
{
Console.WriteLine($"[ContentPageHandler] Content handler PlatformView is not SkiaView: {content.Handler?.PlatformView?.GetType().Name ?? "null"}");
}
}
else
{
handler.PlatformView.Content = null;
}
}
public static void MapBackgroundColor(PageHandler handler, Page page)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView != null)
{
Color backgroundColor = ((VisualElement)page).BackgroundColor;
if (backgroundColor != null && backgroundColor != Colors.Transparent)
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.BackgroundColor = backgroundColor.ToSKColor();
Console.WriteLine($"[PageHandler] MapBackgroundColor: {backgroundColor}");
}
}
}
}

View File

@@ -1,161 +1,175 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using System;
using System.Collections.Specialized;
using System.Linq;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Picker on Linux using Skia rendering.
/// </summary>
public partial class PickerHandler : ViewHandler<IPicker, SkiaPicker>
public class PickerHandler : ViewHandler<IPicker, SkiaPicker>
{
public static IPropertyMapper<IPicker, PickerHandler> Mapper =
new PropertyMapper<IPicker, PickerHandler>(ViewHandler.ViewMapper)
{
[nameof(IPicker.Title)] = MapTitle,
[nameof(IPicker.TitleColor)] = MapTitleColor,
[nameof(IPicker.SelectedIndex)] = MapSelectedIndex,
[nameof(IPicker.TextColor)] = MapTextColor,
[nameof(IPicker.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IPicker.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(IPicker.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(IView.Background)] = MapBackground,
[nameof(Picker.ItemsSource)] = MapItemsSource,
};
public static IPropertyMapper<IPicker, PickerHandler> Mapper = (IPropertyMapper<IPicker, PickerHandler>)(object)new PropertyMapper<IPicker, PickerHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Title"] = MapTitle,
["TitleColor"] = MapTitleColor,
["SelectedIndex"] = MapSelectedIndex,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["CharacterSpacing"] = MapCharacterSpacing,
["HorizontalTextAlignment"] = MapHorizontalTextAlignment,
["VerticalTextAlignment"] = MapVerticalTextAlignment,
["Background"] = MapBackground,
["ItemsSource"] = MapItemsSource
};
public static CommandMapper<IPicker, PickerHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IPicker, PickerHandler> CommandMapper = new CommandMapper<IPicker, PickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
private INotifyCollectionChanged? _itemsCollection;
private INotifyCollectionChanged? _itemsCollection;
public PickerHandler() : base(Mapper, CommandMapper)
{
}
public PickerHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public PickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public PickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaPicker CreatePlatformView()
{
return new SkiaPicker();
}
protected override SkiaPicker CreatePlatformView()
{
return new SkiaPicker();
}
protected override void ConnectHandler(SkiaPicker platformView)
{
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
protected override void ConnectHandler(SkiaPicker platformView)
{
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
IPicker virtualView = base.VirtualView;
Picker val = (Picker)(object)((virtualView is Picker) ? virtualView : null);
if (val != null && val.Items is INotifyCollectionChanged itemsCollection)
{
_itemsCollection = itemsCollection;
_itemsCollection.CollectionChanged += OnItemsCollectionChanged;
}
ReloadItems();
}
// Subscribe to items collection changes
if (VirtualView is Picker picker && picker.Items is INotifyCollectionChanged items)
{
_itemsCollection = items;
_itemsCollection.CollectionChanged += OnItemsCollectionChanged;
}
protected override void DisconnectHandler(SkiaPicker platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
if (_itemsCollection != null)
{
_itemsCollection.CollectionChanged -= OnItemsCollectionChanged;
_itemsCollection = null;
}
base.DisconnectHandler(platformView);
}
// Load items
ReloadItems();
}
private void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
ReloadItems();
}
protected override void DisconnectHandler(SkiaPicker platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
base.VirtualView.SelectedIndex = base.PlatformView.SelectedIndex;
}
}
if (_itemsCollection != null)
{
_itemsCollection.CollectionChanged -= OnItemsCollectionChanged;
_itemsCollection = null;
}
private void ReloadItems()
{
if (base.PlatformView != null && base.VirtualView != null)
{
string[] itemsAsArray = IPickerExtension.GetItemsAsArray(base.VirtualView);
base.PlatformView.SetItems(itemsAsArray.Select((string i) => i?.ToString() ?? ""));
}
}
base.DisconnectHandler(platformView);
}
public static void MapTitle(PickerHandler handler, IPicker picker)
{
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.Title = picker.Title ?? "";
}
}
private void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
ReloadItems();
}
public static void MapTitleColor(PickerHandler handler, IPicker picker)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null && picker.TitleColor != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.TitleColor = picker.TitleColor.ToSKColor();
}
}
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
public static void MapSelectedIndex(PickerHandler handler, IPicker picker)
{
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.SelectedIndex = picker.SelectedIndex;
}
}
VirtualView.SelectedIndex = PlatformView.SelectedIndex;
}
public static void MapTextColor(PickerHandler handler, IPicker picker)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null && ((ITextStyle)picker).TextColor != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.TextColor = ((ITextStyle)picker).TextColor.ToSKColor();
}
}
private void ReloadItems()
{
if (PlatformView is null || VirtualView is null) return;
public static void MapFont(PickerHandler handler, IPicker picker)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)picker).Font;
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.Invalidate();
}
}
var items = VirtualView.GetItemsAsArray();
PlatformView.SetItems(items.Select(i => i?.ToString() ?? ""));
}
public static void MapCharacterSpacing(PickerHandler handler, IPicker picker)
{
}
public static void MapTitle(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Title = picker.Title ?? "";
}
public static void MapHorizontalTextAlignment(PickerHandler handler, IPicker picker)
{
}
public static void MapTitleColor(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
if (picker.TitleColor is not null)
{
handler.PlatformView.TitleColor = picker.TitleColor.ToSKColor();
}
}
public static void MapVerticalTextAlignment(PickerHandler handler, IPicker picker)
{
}
public static void MapSelectedIndex(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.SelectedIndex = picker.SelectedIndex;
}
public static void MapBackground(PickerHandler handler, IPicker picker)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null)
{
Paint background = ((IView)picker).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapTextColor(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
if (picker.TextColor is not null)
{
handler.PlatformView.TextColor = picker.TextColor.ToSKColor();
}
}
public static void MapCharacterSpacing(PickerHandler handler, IPicker picker)
{
// Character spacing could be implemented with custom text rendering
}
public static void MapHorizontalTextAlignment(PickerHandler handler, IPicker picker)
{
// Text alignment would require changes to SkiaPicker drawing
}
public static void MapVerticalTextAlignment(PickerHandler handler, IPicker picker)
{
// Text alignment would require changes to SkiaPicker drawing
}
public static void MapBackground(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
if (picker.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapItemsSource(PickerHandler handler, IPicker picker)
{
handler.ReloadItems();
}
public static void MapItemsSource(PickerHandler handler, IPicker picker)
{
handler.ReloadItems();
}
}

View File

@@ -1,65 +1,113 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System.ComponentModel;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using SkiaSharp;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for ProgressBar on Linux using Skia rendering.
/// Maps IProgress interface to SkiaProgressBar platform view.
/// IProgress has: Progress (0-1), ProgressColor
/// </summary>
public partial class ProgressBarHandler : ViewHandler<IProgress, SkiaProgressBar>
public class ProgressBarHandler : ViewHandler<IProgress, SkiaProgressBar>
{
public static IPropertyMapper<IProgress, ProgressBarHandler> Mapper = new PropertyMapper<IProgress, ProgressBarHandler>(ViewHandler.ViewMapper)
{
[nameof(IProgress.Progress)] = MapProgress,
[nameof(IProgress.ProgressColor)] = MapProgressColor,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<IProgress, ProgressBarHandler> Mapper = (IPropertyMapper<IProgress, ProgressBarHandler>)(object)new PropertyMapper<IProgress, ProgressBarHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Progress"] = MapProgress,
["ProgressColor"] = MapProgressColor,
["IsEnabled"] = MapIsEnabled,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static CommandMapper<IProgress, ProgressBarHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IProgress, ProgressBarHandler> CommandMapper = new CommandMapper<IProgress, ProgressBarHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public ProgressBarHandler() : base(Mapper, CommandMapper)
{
}
public ProgressBarHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ProgressBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaProgressBar CreatePlatformView()
{
return new SkiaProgressBar();
}
protected override SkiaProgressBar CreatePlatformView()
{
return new SkiaProgressBar();
}
protected override void ConnectHandler(SkiaProgressBar platformView)
{
base.ConnectHandler(platformView);
IProgress virtualView = base.VirtualView;
BindableObject val = (BindableObject)(object)((virtualView is BindableObject) ? virtualView : null);
if (val != null)
{
val.PropertyChanged += OnVirtualViewPropertyChanged;
}
IProgress virtualView2 = base.VirtualView;
VisualElement val2 = (VisualElement)(object)((virtualView2 is VisualElement) ? virtualView2 : null);
if (val2 != null)
{
platformView.IsVisible = val2.IsVisible;
}
}
public static void MapProgress(ProgressBarHandler handler, IProgress progress)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Progress = Math.Clamp(progress.Progress, 0.0, 1.0);
}
protected override void DisconnectHandler(SkiaProgressBar platformView)
{
IProgress virtualView = base.VirtualView;
BindableObject val = (BindableObject)(object)((virtualView is BindableObject) ? virtualView : null);
if (val != null)
{
val.PropertyChanged -= OnVirtualViewPropertyChanged;
}
base.DisconnectHandler(platformView);
}
public static void MapProgressColor(ProgressBarHandler handler, IProgress progress)
{
if (handler.PlatformView is null) return;
private void OnVirtualViewPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
IProgress virtualView = base.VirtualView;
VisualElement val = (VisualElement)(object)((virtualView is VisualElement) ? virtualView : null);
if (val != null && e.PropertyName == "IsVisible")
{
base.PlatformView.IsVisible = val.IsVisible;
base.PlatformView.Invalidate();
}
}
if (progress.ProgressColor is not null)
handler.PlatformView.ProgressColor = progress.ProgressColor.ToSKColor();
}
public static void MapProgress(ProgressBarHandler handler, IProgress progress)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Progress = progress.Progress;
}
public static void MapBackground(ProgressBarHandler handler, IProgress progress)
{
if (handler.PlatformView is null) return;
public static void MapProgressColor(ProgressBarHandler handler, IProgress progress)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
if (progress.ProgressColor != null)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.ProgressColor = progress.ProgressColor.ToSKColor();
}
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Invalidate();
}
if (progress.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapIsEnabled(ProgressBarHandler handler, IProgress progress)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.IsEnabled = ((IView)progress).IsEnabled;
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Invalidate();
}
public static void MapBackground(ProgressBarHandler handler, IProgress progress)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
Paint background = ((IView)progress).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapBackgroundColor(ProgressBarHandler handler, IProgress progress)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
VisualElement val = (VisualElement)(object)((progress is VisualElement) ? progress : null);
if (val != null && val.BackgroundColor != null)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.BackgroundColor = val.BackgroundColor.ToSKColor();
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Invalidate();
}
}
}

View File

@@ -1,106 +1,111 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for RadioButton on Linux using Skia rendering.
/// </summary>
public partial class RadioButtonHandler : ViewHandler<IRadioButton, SkiaRadioButton>
public class RadioButtonHandler : ViewHandler<IRadioButton, SkiaRadioButton>
{
public static IPropertyMapper<IRadioButton, RadioButtonHandler> Mapper =
new PropertyMapper<IRadioButton, RadioButtonHandler>(ViewHandler.ViewMapper)
{
[nameof(IRadioButton.IsChecked)] = MapIsChecked,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<IRadioButton, RadioButtonHandler> Mapper = (IPropertyMapper<IRadioButton, RadioButtonHandler>)(object)new PropertyMapper<IRadioButton, RadioButtonHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsChecked"] = MapIsChecked,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["Background"] = MapBackground
};
public static CommandMapper<IRadioButton, RadioButtonHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IRadioButton, RadioButtonHandler> CommandMapper = new CommandMapper<IRadioButton, RadioButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public RadioButtonHandler() : base(Mapper, CommandMapper)
{
}
public RadioButtonHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public RadioButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public RadioButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaRadioButton CreatePlatformView()
{
return new SkiaRadioButton();
}
protected override SkiaRadioButton CreatePlatformView()
{
return new SkiaRadioButton();
}
protected override void ConnectHandler(SkiaRadioButton platformView)
{
base.ConnectHandler(platformView);
platformView.CheckedChanged += OnCheckedChanged;
protected override void ConnectHandler(SkiaRadioButton platformView)
{
base.ConnectHandler(platformView);
platformView.CheckedChanged += OnCheckedChanged;
IRadioButton virtualView = base.VirtualView;
RadioButton val = (RadioButton)(object)((virtualView is RadioButton) ? virtualView : null);
if (val != null)
{
platformView.Content = val.Content?.ToString() ?? "";
platformView.GroupName = val.GroupName;
platformView.Value = val.Value;
}
}
// Set content if available
if (VirtualView is RadioButton rb)
{
platformView.Content = rb.Content?.ToString() ?? "";
platformView.GroupName = rb.GroupName;
platformView.Value = rb.Value;
}
}
protected override void DisconnectHandler(SkiaRadioButton platformView)
{
platformView.CheckedChanged -= OnCheckedChanged;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaRadioButton platformView)
{
platformView.CheckedChanged -= OnCheckedChanged;
base.DisconnectHandler(platformView);
}
private void OnCheckedChanged(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
base.VirtualView.IsChecked = base.PlatformView.IsChecked;
}
}
private void OnCheckedChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
VirtualView.IsChecked = PlatformView.IsChecked;
}
public static void MapIsChecked(RadioButtonHandler handler, IRadioButton radioButton)
{
if (((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView.IsChecked = radioButton.IsChecked;
}
}
public static void MapIsChecked(RadioButtonHandler handler, IRadioButton radioButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsChecked = radioButton.IsChecked;
}
public static void MapTextColor(RadioButtonHandler handler, IRadioButton radioButton)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView != null && ((ITextStyle)radioButton).TextColor != null)
{
((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView.TextColor = ((ITextStyle)radioButton).TextColor.ToSKColor();
}
}
public static void MapTextColor(RadioButtonHandler handler, IRadioButton radioButton)
{
if (handler.PlatformView is null) return;
public static void MapFont(RadioButtonHandler handler, IRadioButton radioButton)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)radioButton).Font;
if (((Font)(ref font)).Size > 0.0)
{
SkiaRadioButton platformView = ((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView;
font = ((ITextStyle)radioButton).Font;
platformView.FontSize = (float)((Font)(ref font)).Size;
}
}
}
if (radioButton.TextColor is not null)
{
handler.PlatformView.TextColor = radioButton.TextColor.ToSKColor();
}
}
public static void MapFont(RadioButtonHandler handler, IRadioButton radioButton)
{
if (handler.PlatformView is null) return;
if (radioButton.Font.Size > 0)
{
handler.PlatformView.FontSize = (float)radioButton.Font.Size;
}
}
public static void MapBackground(RadioButtonHandler handler, IRadioButton radioButton)
{
if (handler.PlatformView is null) return;
if (radioButton.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackground(RadioButtonHandler handler, IRadioButton radioButton)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView != null)
{
Paint background = ((IView)radioButton).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
}

34
Handlers/RelayCommand.cs Normal file
View File

@@ -0,0 +1,34 @@
using System;
using System.Windows.Input;
namespace Microsoft.Maui.Platform.Linux.Handlers;
internal class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool>? _canExecute;
public event EventHandler? CanExecuteChanged;
public RelayCommand(Action execute, Func<bool>? canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
public bool CanExecute(object? parameter)
{
return _canExecute?.Invoke() ?? true;
}
public void Execute(object? parameter)
{
_execute();
}
public void RaiseCanExecuteChanged()
{
this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

View File

@@ -1,109 +1,115 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for ScrollView on Linux using SkiaScrollView.
/// </summary>
public partial class ScrollViewHandler : ViewHandler<IScrollView, SkiaScrollView>
public class ScrollViewHandler : ViewHandler<IScrollView, SkiaScrollView>
{
public static IPropertyMapper<IScrollView, ScrollViewHandler> Mapper =
new PropertyMapper<IScrollView, ScrollViewHandler>(ViewMapper)
{
[nameof(IScrollView.Content)] = MapContent,
[nameof(IScrollView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
[nameof(IScrollView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
[nameof(IScrollView.Orientation)] = MapOrientation,
};
public static IPropertyMapper<IScrollView, ScrollViewHandler> Mapper = (IPropertyMapper<IScrollView, ScrollViewHandler>)(object)new PropertyMapper<IScrollView, ScrollViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Content"] = MapContent,
["HorizontalScrollBarVisibility"] = MapHorizontalScrollBarVisibility,
["VerticalScrollBarVisibility"] = MapVerticalScrollBarVisibility,
["Orientation"] = MapOrientation
};
public static CommandMapper<IScrollView, ScrollViewHandler> CommandMapper =
new(ViewCommandMapper)
{
[nameof(IScrollView.RequestScrollTo)] = MapRequestScrollTo
};
public static CommandMapper<IScrollView, ScrollViewHandler> CommandMapper = new CommandMapper<IScrollView, ScrollViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["RequestScrollTo"] = MapRequestScrollTo };
public ScrollViewHandler() : base(Mapper, CommandMapper)
{
}
public ScrollViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ScrollViewHandler(IPropertyMapper? mapper)
: base(mapper ?? Mapper, CommandMapper)
{
}
public ScrollViewHandler(IPropertyMapper? mapper)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(object)CommandMapper)
{
}
protected override SkiaScrollView CreatePlatformView()
{
return new SkiaScrollView();
}
protected override SkiaScrollView CreatePlatformView()
{
return new SkiaScrollView();
}
public static void MapContent(ScrollViewHandler handler, IScrollView scrollView)
{
if (handler.PlatformView == null || handler.MauiContext == null)
return;
public static void MapContent(ScrollViewHandler handler, IScrollView scrollView)
{
if (((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
IView presentedContent = ((IContentView)scrollView).PresentedContent;
if (presentedContent != null)
{
Console.WriteLine("[ScrollViewHandler] MapContent: " + ((object)presentedContent).GetType().Name);
if (presentedContent.Handler == null)
{
presentedContent.Handler = presentedContent.ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = presentedContent.Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
Console.WriteLine("[ScrollViewHandler] Setting content: " + ((object)skiaView).GetType().Name);
((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView.Content = skiaView;
}
}
else
{
((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView.Content = null;
}
}
var content = scrollView.PresentedContent;
if (content != null)
{
Console.WriteLine($"[ScrollViewHandler] MapContent: {content.GetType().Name}");
public static void MapHorizontalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
SkiaScrollView platformView = ((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView;
ScrollBarVisibility horizontalScrollBarVisibility = scrollView.HorizontalScrollBarVisibility;
ScrollBarVisibility horizontalScrollBarVisibility2 = (((int)horizontalScrollBarVisibility == 1) ? ScrollBarVisibility.Always : (((int)horizontalScrollBarVisibility == 2) ? ScrollBarVisibility.Never : ScrollBarVisibility.Default));
platformView.HorizontalScrollBarVisibility = horizontalScrollBarVisibility2;
}
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
content.Handler = content.ToHandler(handler.MauiContext);
}
public static void MapVerticalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
SkiaScrollView platformView = ((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView;
ScrollBarVisibility verticalScrollBarVisibility = scrollView.VerticalScrollBarVisibility;
ScrollBarVisibility verticalScrollBarVisibility2 = (((int)verticalScrollBarVisibility == 1) ? ScrollBarVisibility.Always : (((int)verticalScrollBarVisibility == 2) ? ScrollBarVisibility.Never : ScrollBarVisibility.Default));
platformView.VerticalScrollBarVisibility = verticalScrollBarVisibility2;
}
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
Console.WriteLine($"[ScrollViewHandler] Setting content: {skiaContent.GetType().Name}");
handler.PlatformView.Content = skiaContent;
}
}
else
{
handler.PlatformView.Content = null;
}
}
public static void MapOrientation(ScrollViewHandler handler, IScrollView scrollView)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected I4, but got Unknown
SkiaScrollView platformView = ((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView;
ScrollOrientation orientation = scrollView.Orientation;
platformView.Orientation = (orientation - 1) switch
{
0 => ScrollOrientation.Horizontal,
1 => ScrollOrientation.Both,
2 => ScrollOrientation.Neither,
_ => ScrollOrientation.Vertical,
};
}
public static void MapHorizontalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
handler.PlatformView.HorizontalScrollBarVisibility = scrollView.HorizontalScrollBarVisibility switch
{
Microsoft.Maui.ScrollBarVisibility.Always => ScrollBarVisibility.Always,
Microsoft.Maui.ScrollBarVisibility.Never => ScrollBarVisibility.Never,
_ => ScrollBarVisibility.Default
};
}
public static void MapVerticalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
handler.PlatformView.VerticalScrollBarVisibility = scrollView.VerticalScrollBarVisibility switch
{
Microsoft.Maui.ScrollBarVisibility.Always => ScrollBarVisibility.Always,
Microsoft.Maui.ScrollBarVisibility.Never => ScrollBarVisibility.Never,
_ => ScrollBarVisibility.Default
};
}
public static void MapOrientation(ScrollViewHandler handler, IScrollView scrollView)
{
handler.PlatformView.Orientation = scrollView.Orientation switch
{
Microsoft.Maui.ScrollOrientation.Horizontal => ScrollOrientation.Horizontal,
Microsoft.Maui.ScrollOrientation.Both => ScrollOrientation.Both,
Microsoft.Maui.ScrollOrientation.Neither => ScrollOrientation.Neither,
_ => ScrollOrientation.Vertical
};
}
public static void MapRequestScrollTo(ScrollViewHandler handler, IScrollView scrollView, object? args)
{
if (args is ScrollToRequest request)
{
// Instant means no animation, so we pass !Instant for animated parameter
handler.PlatformView.ScrollTo((float)request.HorizontalOffset, (float)request.VerticalOffset, !request.Instant);
}
}
public static void MapRequestScrollTo(ScrollViewHandler handler, IScrollView scrollView, object? args)
{
ScrollToRequest val = (ScrollToRequest)((args is ScrollToRequest) ? args : null);
if (val != null)
{
((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView.ScrollTo((float)val.HorizontalOffset, (float)val.VerticalOffset, !val.Instant);
}
}
}

View File

@@ -1,135 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using Microsoft.Maui.Graphics;
using SkiaSharp;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for SearchBar on Linux using Skia rendering.
/// Maps ISearchBar interface to SkiaSearchBar platform view.
/// </summary>
public partial class SearchBarHandler : ViewHandler<ISearchBar, SkiaSearchBar>
public class SearchBarHandler : ViewHandler<ISearchBar, SkiaSearchBar>
{
public static IPropertyMapper<ISearchBar, SearchBarHandler> Mapper = new PropertyMapper<ISearchBar, SearchBarHandler>(ViewHandler.ViewMapper)
{
[nameof(ITextInput.Text)] = MapText,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(IPlaceholder.Placeholder)] = MapPlaceholder,
[nameof(IPlaceholder.PlaceholderColor)] = MapPlaceholderColor,
[nameof(ISearchBar.CancelButtonColor)] = MapCancelButtonColor,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<ISearchBar, SearchBarHandler> Mapper = (IPropertyMapper<ISearchBar, SearchBarHandler>)(object)new PropertyMapper<ISearchBar, SearchBarHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Text"] = MapText,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["Placeholder"] = MapPlaceholder,
["PlaceholderColor"] = MapPlaceholderColor,
["CancelButtonColor"] = MapCancelButtonColor,
["Background"] = MapBackground
};
public static CommandMapper<ISearchBar, SearchBarHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<ISearchBar, SearchBarHandler> CommandMapper = new CommandMapper<ISearchBar, SearchBarHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public SearchBarHandler() : base(Mapper, CommandMapper)
{
}
public SearchBarHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public SearchBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public SearchBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaSearchBar CreatePlatformView()
{
return new SkiaSearchBar();
}
protected override SkiaSearchBar CreatePlatformView()
{
return new SkiaSearchBar();
}
protected override void ConnectHandler(SkiaSearchBar platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.SearchButtonPressed += OnSearchButtonPressed;
}
protected override void ConnectHandler(SkiaSearchBar platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.SearchButtonPressed += OnSearchButtonPressed;
}
protected override void DisconnectHandler(SkiaSearchBar platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.SearchButtonPressed -= OnSearchButtonPressed;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaSearchBar platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.SearchButtonPressed -= OnSearchButtonPressed;
base.DisconnectHandler(platformView);
}
private void OnTextChanged(object? sender, TextChangedEventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnTextChanged(object? sender, TextChangedEventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null && ((ITextInput)base.VirtualView).Text != e.NewTextValue)
{
((ITextInput)base.VirtualView).Text = e.NewTextValue ?? string.Empty;
}
}
if (VirtualView.Text != e.NewTextValue)
{
VirtualView.Text = e.NewTextValue ?? string.Empty;
}
}
private void OnSearchButtonPressed(object? sender, EventArgs e)
{
ISearchBar virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.SearchButtonPressed();
}
}
private void OnSearchButtonPressed(object? sender, EventArgs e)
{
VirtualView?.SearchButtonPressed();
}
public static void MapText(SearchBarHandler handler, ISearchBar searchBar)
{
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null && ((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.Text != ((ITextInput)searchBar).Text)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.Text = ((ITextInput)searchBar).Text ?? string.Empty;
}
}
public static void MapText(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
public static void MapTextColor(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null && ((ITextStyle)searchBar).TextColor != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.TextColor = ((ITextStyle)searchBar).TextColor.ToSKColor();
}
}
if (handler.PlatformView.Text != searchBar.Text)
handler.PlatformView.Text = searchBar.Text ?? string.Empty;
}
public static void MapFont(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)searchBar).Font;
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
}
}
public static void MapTextColor(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
public static void MapPlaceholder(SearchBarHandler handler, ISearchBar searchBar)
{
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.Placeholder = ((IPlaceholder)searchBar).Placeholder ?? string.Empty;
}
}
if (searchBar.TextColor is not null)
handler.PlatformView.TextColor = searchBar.TextColor.ToSKColor();
}
public static void MapPlaceholderColor(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null && ((IPlaceholder)searchBar).PlaceholderColor != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.PlaceholderColor = ((IPlaceholder)searchBar).PlaceholderColor.ToSKColor();
}
}
public static void MapFont(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
public static void MapCancelButtonColor(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null && searchBar.CancelButtonColor != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.ClearButtonColor = searchBar.CancelButtonColor.ToSKColor();
}
}
var font = searchBar.Font;
if (font.Size > 0)
handler.PlatformView.FontSize = (float)font.Size;
if (!string.IsNullOrEmpty(font.Family))
handler.PlatformView.FontFamily = font.Family;
}
public static void MapPlaceholder(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Placeholder = searchBar.Placeholder ?? string.Empty;
}
public static void MapPlaceholderColor(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
if (searchBar.PlaceholderColor is not null)
handler.PlatformView.PlaceholderColor = searchBar.PlaceholderColor.ToSKColor();
}
public static void MapCancelButtonColor(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
// CancelButtonColor maps to ClearButtonColor
if (searchBar.CancelButtonColor is not null)
handler.PlatformView.ClearButtonColor = searchBar.CancelButtonColor.ToSKColor();
}
public static void MapBackground(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
if (searchBar.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackground(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null)
{
Paint background = ((IView)searchBar).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
}

View File

@@ -1,93 +1,88 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Runtime.CompilerServices;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Shell on Linux using Skia rendering.
/// </summary>
public partial class ShellHandler : ViewHandler<Shell, SkiaShell>
public class ShellHandler : ViewHandler<Shell, SkiaShell>
{
public static IPropertyMapper<Shell, ShellHandler> Mapper = new PropertyMapper<Shell, ShellHandler>(ViewHandler.ViewMapper)
{
};
public static IPropertyMapper<Shell, ShellHandler> Mapper = (IPropertyMapper<Shell, ShellHandler>)(object)new PropertyMapper<Shell, ShellHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper });
public static CommandMapper<Shell, ShellHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<Shell, ShellHandler> CommandMapper = new CommandMapper<Shell, ShellHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public ShellHandler() : base(Mapper, CommandMapper)
{
}
public ShellHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ShellHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public ShellHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaShell CreatePlatformView()
{
return new SkiaShell();
}
protected override SkiaShell CreatePlatformView()
{
return new SkiaShell();
}
protected override void ConnectHandler(SkiaShell platformView)
{
base.ConnectHandler(platformView);
platformView.FlyoutIsPresentedChanged += OnFlyoutIsPresentedChanged;
platformView.Navigated += OnNavigated;
protected override void ConnectHandler(SkiaShell platformView)
{
base.ConnectHandler(platformView);
platformView.FlyoutIsPresentedChanged += OnFlyoutIsPresentedChanged;
platformView.Navigated += OnNavigated;
if (base.VirtualView != null)
{
base.VirtualView.Navigating += OnShellNavigating;
base.VirtualView.Navigated += OnShellNavigated;
}
}
// Subscribe to Shell navigation events
if (VirtualView != null)
{
VirtualView.Navigating += OnShellNavigating;
VirtualView.Navigated += OnShellNavigated;
}
}
protected override void DisconnectHandler(SkiaShell platformView)
{
platformView.FlyoutIsPresentedChanged -= OnFlyoutIsPresentedChanged;
platformView.Navigated -= OnNavigated;
if (base.VirtualView != null)
{
base.VirtualView.Navigating -= OnShellNavigating;
base.VirtualView.Navigated -= OnShellNavigated;
}
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaShell platformView)
{
platformView.FlyoutIsPresentedChanged -= OnFlyoutIsPresentedChanged;
platformView.Navigated -= OnNavigated;
private void OnFlyoutIsPresentedChanged(object? sender, EventArgs e)
{
}
if (VirtualView != null)
{
VirtualView.Navigating -= OnShellNavigating;
VirtualView.Navigated -= OnShellNavigated;
}
private void OnNavigated(object? sender, ShellNavigationEventArgs e)
{
}
base.DisconnectHandler(platformView);
}
private void OnShellNavigating(object? sender, ShellNavigatingEventArgs e)
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(36, 1);
defaultInterpolatedStringHandler.AppendLiteral("[ShellHandler] Shell Navigating to: ");
ShellNavigationState target = e.Target;
defaultInterpolatedStringHandler.AppendFormatted((target != null) ? target.Location : null);
Console.WriteLine(defaultInterpolatedStringHandler.ToStringAndClear());
if (base.PlatformView != null)
{
ShellNavigationState target2 = e.Target;
if (((target2 != null) ? target2.Location : null) != null)
{
string text = e.Target.Location.ToString().TrimStart('/');
Console.WriteLine("[ShellHandler] Routing to: " + text);
base.PlatformView.GoToAsync(text);
}
}
}
private void OnFlyoutIsPresentedChanged(object? sender, EventArgs e)
{
// Sync flyout state to virtual view
}
private void OnNavigated(object? sender, ShellNavigationEventArgs e)
{
// Handle platform navigation events
}
private void OnShellNavigating(object? sender, ShellNavigatingEventArgs e)
{
Console.WriteLine($"[ShellHandler] Shell Navigating to: {e.Target?.Location}");
// Route to platform view
if (PlatformView != null && e.Target?.Location != null)
{
var route = e.Target.Location.ToString().TrimStart('/');
Console.WriteLine($"[ShellHandler] Routing to: {route}");
PlatformView.GoToAsync(route);
}
}
private void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
{
Console.WriteLine($"[ShellHandler] Shell Navigated to: {e.Current?.Location}");
}
private void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(35, 1);
defaultInterpolatedStringHandler.AppendLiteral("[ShellHandler] Shell Navigated to: ");
ShellNavigationState current = e.Current;
defaultInterpolatedStringHandler.AppendFormatted((current != null) ? current.Location : null);
Console.WriteLine(defaultInterpolatedStringHandler.ToStringAndClear());
}
}

View File

@@ -0,0 +1,16 @@
using System;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class SizeChangedEventArgs : EventArgs
{
public int Width { get; }
public int Height { get; }
public SizeChangedEventArgs(int width, int height)
{
Width = width;
Height = height;
}
}

184
Handlers/SkiaWindow.cs Normal file
View File

@@ -0,0 +1,184 @@
using System;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class SkiaWindow
{
private SkiaView? _content;
private string _title = "MAUI Application";
private int _x;
private int _y;
private int _width = 800;
private int _height = 600;
private int _minWidth = 100;
private int _minHeight = 100;
private int _maxWidth = int.MaxValue;
private int _maxHeight = int.MaxValue;
public SkiaView? Content
{
get
{
return _content;
}
set
{
_content = value;
this.ContentChanged?.Invoke(this, EventArgs.Empty);
}
}
public string Title
{
get
{
return _title;
}
set
{
_title = value;
this.TitleChanged?.Invoke(this, EventArgs.Empty);
}
}
public int X
{
get
{
return _x;
}
set
{
_x = value;
this.PositionChanged?.Invoke(this, EventArgs.Empty);
}
}
public int Y
{
get
{
return _y;
}
set
{
_y = value;
this.PositionChanged?.Invoke(this, EventArgs.Empty);
}
}
public int Width
{
get
{
return _width;
}
set
{
_width = Math.Clamp(value, _minWidth, _maxWidth);
this.SizeChanged?.Invoke(this, new SizeChangedEventArgs(_width, _height));
}
}
public int Height
{
get
{
return _height;
}
set
{
_height = Math.Clamp(value, _minHeight, _maxHeight);
this.SizeChanged?.Invoke(this, new SizeChangedEventArgs(_width, _height));
}
}
public int MinWidth
{
get
{
return _minWidth;
}
set
{
_minWidth = value;
}
}
public int MinHeight
{
get
{
return _minHeight;
}
set
{
_minHeight = value;
}
}
public int MaxWidth
{
get
{
return _maxWidth;
}
set
{
_maxWidth = value;
}
}
public int MaxHeight
{
get
{
return _maxHeight;
}
set
{
_maxHeight = value;
}
}
public event EventHandler? ContentChanged;
public event EventHandler? TitleChanged;
public event EventHandler? PositionChanged;
public event EventHandler<SizeChangedEventArgs>? SizeChanged;
public event EventHandler? CloseRequested;
public void Render(SKCanvas canvas)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
canvas.Clear(SKColors.White);
if (_content != null)
{
_content.Measure(new SKSize((float)_width, (float)_height));
_content.Arrange(new SKRect(0f, 0f, (float)_width, (float)_height));
_content.Draw(canvas);
}
SkiaView.DrawPopupOverlays(canvas);
}
public void Close()
{
this.CloseRequested?.Invoke(this, EventArgs.Empty);
}
}

View File

@@ -1,153 +1,160 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using Microsoft.Maui.Graphics;
using SkiaSharp;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Slider on Linux using Skia rendering.
/// Maps ISlider interface to SkiaSlider platform view.
/// </summary>
public partial class SliderHandler : ViewHandler<ISlider, SkiaSlider>
public class SliderHandler : ViewHandler<ISlider, SkiaSlider>
{
public static IPropertyMapper<ISlider, SliderHandler> Mapper = new PropertyMapper<ISlider, SliderHandler>(ViewHandler.ViewMapper)
{
[nameof(IRange.Minimum)] = MapMinimum,
[nameof(IRange.Maximum)] = MapMaximum,
[nameof(IRange.Value)] = MapValue,
[nameof(ISlider.MinimumTrackColor)] = MapMinimumTrackColor,
[nameof(ISlider.MaximumTrackColor)] = MapMaximumTrackColor,
[nameof(ISlider.ThumbColor)] = MapThumbColor,
[nameof(IView.Background)] = MapBackground,
[nameof(IView.IsEnabled)] = MapIsEnabled,
};
public static IPropertyMapper<ISlider, SliderHandler> Mapper = (IPropertyMapper<ISlider, SliderHandler>)(object)new PropertyMapper<ISlider, SliderHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Minimum"] = MapMinimum,
["Maximum"] = MapMaximum,
["Value"] = MapValue,
["MinimumTrackColor"] = MapMinimumTrackColor,
["MaximumTrackColor"] = MapMaximumTrackColor,
["ThumbColor"] = MapThumbColor,
["Background"] = MapBackground,
["IsEnabled"] = MapIsEnabled
};
public static CommandMapper<ISlider, SliderHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<ISlider, SliderHandler> CommandMapper = new CommandMapper<ISlider, SliderHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public SliderHandler() : base(Mapper, CommandMapper)
{
}
public SliderHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public SliderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public SliderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaSlider CreatePlatformView()
{
return new SkiaSlider();
}
protected override SkiaSlider CreatePlatformView()
{
return new SkiaSlider();
}
protected override void ConnectHandler(SkiaSlider platformView)
{
base.ConnectHandler(platformView);
platformView.ValueChanged += OnValueChanged;
platformView.DragStarted += OnDragStarted;
platformView.DragCompleted += OnDragCompleted;
protected override void ConnectHandler(SkiaSlider platformView)
{
base.ConnectHandler(platformView);
platformView.ValueChanged += OnValueChanged;
platformView.DragStarted += OnDragStarted;
platformView.DragCompleted += OnDragCompleted;
if (base.VirtualView != null)
{
MapMinimum(this, base.VirtualView);
MapMaximum(this, base.VirtualView);
MapValue(this, base.VirtualView);
MapIsEnabled(this, base.VirtualView);
}
}
// Sync properties that may have been set before handler connection
if (VirtualView != null)
{
MapMinimum(this, VirtualView);
MapMaximum(this, VirtualView);
MapValue(this, VirtualView);
MapIsEnabled(this, VirtualView);
}
}
protected override void DisconnectHandler(SkiaSlider platformView)
{
platformView.ValueChanged -= OnValueChanged;
platformView.DragStarted -= OnDragStarted;
platformView.DragCompleted -= OnDragCompleted;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaSlider platformView)
{
platformView.ValueChanged -= OnValueChanged;
platformView.DragStarted -= OnDragStarted;
platformView.DragCompleted -= OnDragCompleted;
base.DisconnectHandler(platformView);
}
private void OnValueChanged(object? sender, SliderValueChangedEventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null && Math.Abs(((IRange)base.VirtualView).Value - e.NewValue) > 0.0001)
{
((IRange)base.VirtualView).Value = e.NewValue;
}
}
private void OnValueChanged(object? sender, SliderValueChangedEventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnDragStarted(object? sender, EventArgs e)
{
ISlider virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.DragStarted();
}
}
if (Math.Abs(VirtualView.Value - e.NewValue) > 0.0001)
{
VirtualView.Value = e.NewValue;
}
}
private void OnDragCompleted(object? sender, EventArgs e)
{
ISlider virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.DragCompleted();
}
}
private void OnDragStarted(object? sender, EventArgs e)
{
VirtualView?.DragStarted();
}
public static void MapMinimum(SliderHandler handler, ISlider slider)
{
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Minimum = ((IRange)slider).Minimum;
}
}
private void OnDragCompleted(object? sender, EventArgs e)
{
VirtualView?.DragCompleted();
}
public static void MapMaximum(SliderHandler handler, ISlider slider)
{
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Maximum = ((IRange)slider).Maximum;
}
}
public static void MapMinimum(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Minimum = slider.Minimum;
}
public static void MapValue(SliderHandler handler, ISlider slider)
{
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null && Math.Abs(((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Value - ((IRange)slider).Value) > 0.0001)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Value = ((IRange)slider).Value;
}
}
public static void MapMaximum(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Maximum = slider.Maximum;
}
public static void MapMinimumTrackColor(SliderHandler handler, ISlider slider)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null && slider.MinimumTrackColor != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.ActiveTrackColor = slider.MinimumTrackColor.ToSKColor();
}
}
public static void MapValue(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
public static void MapMaximumTrackColor(SliderHandler handler, ISlider slider)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null && slider.MaximumTrackColor != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.TrackColor = slider.MaximumTrackColor.ToSKColor();
}
}
if (Math.Abs(handler.PlatformView.Value - slider.Value) > 0.0001)
handler.PlatformView.Value = slider.Value;
}
public static void MapThumbColor(SliderHandler handler, ISlider slider)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null && slider.ThumbColor != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.ThumbColor = slider.ThumbColor.ToSKColor();
}
}
public static void MapMinimumTrackColor(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
public static void MapBackground(SliderHandler handler, ISlider slider)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null)
{
Paint background = ((IView)slider).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
// MinimumTrackColor maps to ActiveTrackColor (the filled portion)
if (slider.MinimumTrackColor is not null)
handler.PlatformView.ActiveTrackColor = slider.MinimumTrackColor.ToSKColor();
}
public static void MapMaximumTrackColor(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
// MaximumTrackColor maps to TrackColor (the unfilled portion)
if (slider.MaximumTrackColor is not null)
handler.PlatformView.TrackColor = slider.MaximumTrackColor.ToSKColor();
}
public static void MapThumbColor(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
if (slider.ThumbColor is not null)
handler.PlatformView.ThumbColor = slider.ThumbColor.ToSKColor();
}
public static void MapBackground(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
if (slider.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapIsEnabled(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsEnabled = slider.IsEnabled;
handler.PlatformView.Invalidate();
}
public static void MapIsEnabled(SliderHandler handler, ISlider slider)
{
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.IsEnabled = ((IView)slider).IsEnabled;
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Invalidate();
}
}
}

View File

@@ -0,0 +1,49 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class StackLayoutHandler : LayoutHandler
{
public new static IPropertyMapper<IStackLayout, StackLayoutHandler> Mapper = (IPropertyMapper<IStackLayout, StackLayoutHandler>)(object)new PropertyMapper<IStackLayout, StackLayoutHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)LayoutHandler.Mapper }) { ["Spacing"] = MapSpacing };
public StackLayoutHandler()
: base((IPropertyMapper?)(object)Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaStackLayout();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
if (platformView is SkiaStackLayout skiaStackLayout)
{
ILayout virtualView = ((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView;
IStackLayout val = (IStackLayout)(object)((virtualView is IStackLayout) ? virtualView : null);
if (val != null)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView is HorizontalStackLayout)
{
skiaStackLayout.Orientation = StackOrientation.Horizontal;
}
else if (((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView is VerticalStackLayout || ((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView is StackLayout)
{
skiaStackLayout.Orientation = StackOrientation.Vertical;
}
skiaStackLayout.Spacing = (float)val.Spacing;
}
}
base.ConnectHandler(platformView);
}
public static void MapSpacing(StackLayoutHandler handler, IStackLayout layout)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaStackLayout skiaStackLayout)
{
skiaStackLayout.Spacing = (float)layout.Spacing;
}
}
}

View File

@@ -1,89 +1,133 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Stepper on Linux using Skia rendering.
/// </summary>
public partial class StepperHandler : ViewHandler<IStepper, SkiaStepper>
public class StepperHandler : ViewHandler<IStepper, SkiaStepper>
{
public static IPropertyMapper<IStepper, StepperHandler> Mapper =
new PropertyMapper<IStepper, StepperHandler>(ViewHandler.ViewMapper)
{
[nameof(IStepper.Value)] = MapValue,
[nameof(IStepper.Minimum)] = MapMinimum,
[nameof(IStepper.Maximum)] = MapMaximum,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<IStepper, StepperHandler> Mapper = (IPropertyMapper<IStepper, StepperHandler>)(object)new PropertyMapper<IStepper, StepperHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Value"] = MapValue,
["Minimum"] = MapMinimum,
["Maximum"] = MapMaximum,
["Increment"] = MapIncrement,
["Background"] = MapBackground,
["IsEnabled"] = MapIsEnabled
};
public static CommandMapper<IStepper, StepperHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<IStepper, StepperHandler> CommandMapper = new CommandMapper<IStepper, StepperHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public StepperHandler() : base(Mapper, CommandMapper)
{
}
public StepperHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public StepperHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public StepperHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaStepper CreatePlatformView()
{
return new SkiaStepper();
}
protected override SkiaStepper CreatePlatformView()
{
return new SkiaStepper();
}
protected override void ConnectHandler(SkiaStepper platformView)
{
base.ConnectHandler(platformView);
platformView.ValueChanged += OnValueChanged;
}
protected override void ConnectHandler(SkiaStepper platformView)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
base.ConnectHandler(platformView);
platformView.ValueChanged += OnValueChanged;
Application current = Application.Current;
if (current != null && (int)current.UserAppTheme == 2)
{
platformView.ButtonBackgroundColor = new SKColor((byte)66, (byte)66, (byte)66);
platformView.ButtonPressedColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.ButtonDisabledColor = new SKColor((byte)48, (byte)48, (byte)48);
platformView.SymbolColor = new SKColor((byte)224, (byte)224, (byte)224);
platformView.SymbolDisabledColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.BorderColor = new SKColor((byte)97, (byte)97, (byte)97);
}
}
protected override void DisconnectHandler(SkiaStepper platformView)
{
platformView.ValueChanged -= OnValueChanged;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaStepper platformView)
{
platformView.ValueChanged -= OnValueChanged;
base.DisconnectHandler(platformView);
}
private void OnValueChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
VirtualView.Value = PlatformView.Value;
}
private void OnValueChanged(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
((IRange)base.VirtualView).Value = base.PlatformView.Value;
}
}
public static void MapValue(StepperHandler handler, IStepper stepper)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Value = stepper.Value;
}
public static void MapValue(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.Value = ((IRange)stepper).Value;
}
}
public static void MapMinimum(StepperHandler handler, IStepper stepper)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Minimum = stepper.Minimum;
}
public static void MapMinimum(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.Minimum = ((IRange)stepper).Minimum;
}
}
public static void MapMaximum(StepperHandler handler, IStepper stepper)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Maximum = stepper.Maximum;
}
public static void MapMaximum(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.Maximum = ((IRange)stepper).Maximum;
}
}
public static void MapBackground(StepperHandler handler, IStepper stepper)
{
if (handler.PlatformView is null) return;
public static void MapBackground(StepperHandler handler, IStepper stepper)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
Paint background = ((IView)stepper).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (stepper.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapIncrement(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
Stepper val = (Stepper)(object)((stepper is Stepper) ? stepper : null);
if (val != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.Increment = val.Increment;
}
}
}
public static void MapIsEnabled(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.IsEnabled = ((IView)stepper).IsEnabled;
}
}
}

View File

@@ -1,99 +1,107 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Switch on Linux using Skia rendering.
/// Maps ISwitch interface to SkiaSwitch platform view.
/// </summary>
public partial class SwitchHandler : ViewHandler<ISwitch, SkiaSwitch>
public class SwitchHandler : ViewHandler<ISwitch, SkiaSwitch>
{
public static IPropertyMapper<ISwitch, SwitchHandler> Mapper = new PropertyMapper<ISwitch, SwitchHandler>(ViewHandler.ViewMapper)
{
[nameof(ISwitch.IsOn)] = MapIsOn,
[nameof(ISwitch.TrackColor)] = MapTrackColor,
[nameof(ISwitch.ThumbColor)] = MapThumbColor,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<ISwitch, SwitchHandler> Mapper = (IPropertyMapper<ISwitch, SwitchHandler>)(object)new PropertyMapper<ISwitch, SwitchHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsOn"] = MapIsOn,
["TrackColor"] = MapTrackColor,
["ThumbColor"] = MapThumbColor,
["Background"] = MapBackground,
["IsEnabled"] = MapIsEnabled
};
public static CommandMapper<ISwitch, SwitchHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<ISwitch, SwitchHandler> CommandMapper = new CommandMapper<ISwitch, SwitchHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public SwitchHandler() : base(Mapper, CommandMapper)
{
}
public SwitchHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public SwitchHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public SwitchHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaSwitch CreatePlatformView()
{
return new SkiaSwitch();
}
protected override SkiaSwitch CreatePlatformView()
{
return new SkiaSwitch();
}
protected override void ConnectHandler(SkiaSwitch platformView)
{
base.ConnectHandler(platformView);
platformView.Toggled += OnToggled;
}
protected override void ConnectHandler(SkiaSwitch platformView)
{
base.ConnectHandler(platformView);
platformView.Toggled += OnToggled;
}
protected override void DisconnectHandler(SkiaSwitch platformView)
{
platformView.Toggled -= OnToggled;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaSwitch platformView)
{
platformView.Toggled -= OnToggled;
base.DisconnectHandler(platformView);
}
private void OnToggled(object? sender, Platform.ToggledEventArgs e)
{
if (VirtualView is not null && VirtualView.IsOn != e.Value)
{
VirtualView.IsOn = e.Value;
}
}
private void OnToggled(object? sender, ToggledEventArgs e)
{
if (base.VirtualView != null && base.VirtualView.IsOn != e.Value)
{
base.VirtualView.IsOn = e.Value;
}
}
public static void MapIsOn(SwitchHandler handler, ISwitch @switch)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsOn = @switch.IsOn;
}
public static void MapIsOn(SwitchHandler handler, ISwitch @switch)
{
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null)
{
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.IsOn = @switch.IsOn;
}
}
public static void MapTrackColor(SwitchHandler handler, ISwitch @switch)
{
if (handler.PlatformView is null) return;
public static void MapTrackColor(SwitchHandler handler, ISwitch @switch)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null && @switch.TrackColor != null)
{
SKColor onTrackColor = @switch.TrackColor.ToSKColor();
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.OnTrackColor = onTrackColor;
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.OffTrackColor = ((SKColor)(ref onTrackColor)).WithAlpha((byte)128);
}
}
// TrackColor sets both On and Off track colors
if (@switch.TrackColor is not null)
{
var color = @switch.TrackColor.ToSKColor();
handler.PlatformView.OnTrackColor = color;
// Off track could be a lighter version
handler.PlatformView.OffTrackColor = color.WithAlpha(128);
}
}
public static void MapThumbColor(SwitchHandler handler, ISwitch @switch)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null && @switch.ThumbColor != null)
{
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.ThumbColor = @switch.ThumbColor.ToSKColor();
}
}
public static void MapThumbColor(SwitchHandler handler, ISwitch @switch)
{
if (handler.PlatformView is null) return;
public static void MapBackground(SwitchHandler handler, ISwitch @switch)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null)
{
Paint background = ((IView)@switch).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (@switch.ThumbColor is not null)
handler.PlatformView.ThumbColor = @switch.ThumbColor.ToSKColor();
}
public static void MapBackground(SwitchHandler handler, ISwitch @switch)
{
if (handler.PlatformView is null) return;
if (@switch.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapIsEnabled(SwitchHandler handler, ISwitch @switch)
{
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null)
{
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.IsEnabled = ((IView)@switch).IsEnabled;
}
}
}

View File

@@ -1,55 +1,43 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for TabbedPage on Linux using Skia rendering.
/// Maps ITabbedView interface to SkiaTabbedPage platform view.
/// </summary>
public partial class TabbedPageHandler : ViewHandler<ITabbedView, SkiaTabbedPage>
public class TabbedPageHandler : ViewHandler<ITabbedView, SkiaTabbedPage>
{
public static IPropertyMapper<ITabbedView, TabbedPageHandler> Mapper = new PropertyMapper<ITabbedView, TabbedPageHandler>(ViewHandler.ViewMapper)
{
};
public static IPropertyMapper<ITabbedView, TabbedPageHandler> Mapper = (IPropertyMapper<ITabbedView, TabbedPageHandler>)(object)new PropertyMapper<ITabbedView, TabbedPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper });
public static CommandMapper<ITabbedView, TabbedPageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<ITabbedView, TabbedPageHandler> CommandMapper = new CommandMapper<ITabbedView, TabbedPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public TabbedPageHandler() : base(Mapper, CommandMapper)
{
}
public TabbedPageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public TabbedPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public TabbedPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaTabbedPage CreatePlatformView()
{
return new SkiaTabbedPage();
}
protected override SkiaTabbedPage CreatePlatformView()
{
return new SkiaTabbedPage();
}
protected override void ConnectHandler(SkiaTabbedPage platformView)
{
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
}
protected override void ConnectHandler(SkiaTabbedPage platformView)
{
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
}
protected override void DisconnectHandler(SkiaTabbedPage platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
platformView.ClearTabs();
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaTabbedPage platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
platformView.ClearTabs();
base.DisconnectHandler(platformView);
}
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
// Notify the virtual view of selection change
}
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
}
}

View File

@@ -0,0 +1,84 @@
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class TextButtonHandler : ButtonHandler
{
public new static IPropertyMapper<ITextButton, TextButtonHandler> Mapper = (IPropertyMapper<ITextButton, TextButtonHandler>)(object)new PropertyMapper<ITextButton, TextButtonHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ButtonHandler.Mapper })
{
["Text"] = MapText,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["CharacterSpacing"] = MapCharacterSpacing
};
public TextButtonHandler()
: base((IPropertyMapper?)(object)Mapper)
{
}
protected override void ConnectHandler(SkiaButton platformView)
{
base.ConnectHandler(platformView);
IButton virtualView = ((ViewHandler<IButton, SkiaButton>)(object)this).VirtualView;
ITextButton val = (ITextButton)(object)((virtualView is ITextButton) ? virtualView : null);
if (val != null)
{
MapText(this, val);
MapTextColor(this, val);
MapFont(this, val);
MapCharacterSpacing(this, val);
}
}
public static void MapText(TextButtonHandler handler, ITextButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.Text = ((IText)button).Text ?? string.Empty;
}
}
public static void MapTextColor(TextButtonHandler handler, ITextButton button)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null && ((ITextStyle)button).TextColor != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.TextColor = ((ITextStyle)button).TextColor.ToSKColor();
}
}
public static void MapFont(TextButtonHandler handler, ITextButton button)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Invalid comparison between Unknown and I4
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Invalid comparison between Unknown and I4
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Invalid comparison between Unknown and I4
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)button).Font;
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.IsBold = (int)((Font)(ref font)).Weight >= 700;
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.IsItalic = (int)((Font)(ref font)).Slant == 1 || (int)((Font)(ref font)).Slant == 2;
}
}
public static void MapCharacterSpacing(TextButtonHandler handler, ITextButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.CharacterSpacing = (float)((ITextStyle)button).CharacterSpacing;
}
}
}

View File

@@ -1,100 +1,115 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for TimePicker on Linux using Skia rendering.
/// </summary>
public partial class TimePickerHandler : ViewHandler<ITimePicker, SkiaTimePicker>
public class TimePickerHandler : ViewHandler<ITimePicker, SkiaTimePicker>
{
public static IPropertyMapper<ITimePicker, TimePickerHandler> Mapper =
new PropertyMapper<ITimePicker, TimePickerHandler>(ViewHandler.ViewMapper)
{
[nameof(ITimePicker.Time)] = MapTime,
[nameof(ITimePicker.Format)] = MapFormat,
[nameof(ITimePicker.TextColor)] = MapTextColor,
[nameof(ITimePicker.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IView.Background)] = MapBackground,
};
public static IPropertyMapper<ITimePicker, TimePickerHandler> Mapper = (IPropertyMapper<ITimePicker, TimePickerHandler>)(object)new PropertyMapper<ITimePicker, TimePickerHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Time"] = MapTime,
["Format"] = MapFormat,
["TextColor"] = MapTextColor,
["CharacterSpacing"] = MapCharacterSpacing,
["Background"] = MapBackground
};
public static CommandMapper<ITimePicker, TimePickerHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public static CommandMapper<ITimePicker, TimePickerHandler> CommandMapper = new CommandMapper<ITimePicker, TimePickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public TimePickerHandler() : base(Mapper, CommandMapper)
{
}
public TimePickerHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public TimePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public TimePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaTimePicker CreatePlatformView()
{
return new SkiaTimePicker();
}
protected override SkiaTimePicker CreatePlatformView()
{
return new SkiaTimePicker();
}
protected override void ConnectHandler(SkiaTimePicker platformView)
{
base.ConnectHandler(platformView);
platformView.TimeSelected += OnTimeSelected;
}
protected override void ConnectHandler(SkiaTimePicker platformView)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
base.ConnectHandler(platformView);
platformView.TimeSelected += OnTimeSelected;
Application current = Application.Current;
if (current != null && (int)current.UserAppTheme == 2)
{
platformView.ClockBackgroundColor = new SKColor((byte)30, (byte)30, (byte)30);
platformView.ClockFaceColor = new SKColor((byte)45, (byte)45, (byte)45);
platformView.TextColor = new SKColor((byte)224, (byte)224, (byte)224);
platformView.BorderColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.BackgroundColor = new SKColor((byte)45, (byte)45, (byte)45);
}
}
protected override void DisconnectHandler(SkiaTimePicker platformView)
{
platformView.TimeSelected -= OnTimeSelected;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaTimePicker platformView)
{
platformView.TimeSelected -= OnTimeSelected;
base.DisconnectHandler(platformView);
}
private void OnTimeSelected(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnTimeSelected(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
base.VirtualView.Time = base.PlatformView.Time;
}
}
VirtualView.Time = PlatformView.Time;
}
public static void MapTime(TimePickerHandler handler, ITimePicker timePicker)
{
if (((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView.Time = timePicker.Time;
}
}
public static void MapTime(TimePickerHandler handler, ITimePicker timePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Time = timePicker.Time;
}
public static void MapFormat(TimePickerHandler handler, ITimePicker timePicker)
{
if (((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView.Format = timePicker.Format ?? "t";
}
}
public static void MapFormat(TimePickerHandler handler, ITimePicker timePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Format = timePicker.Format ?? "t";
}
public static void MapTextColor(TimePickerHandler handler, ITimePicker timePicker)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView != null && ((ITextStyle)timePicker).TextColor != null)
{
((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView.TextColor = ((ITextStyle)timePicker).TextColor.ToSKColor();
}
}
public static void MapTextColor(TimePickerHandler handler, ITimePicker timePicker)
{
if (handler.PlatformView is null) return;
if (timePicker.TextColor is not null)
{
handler.PlatformView.TextColor = timePicker.TextColor.ToSKColor();
}
}
public static void MapCharacterSpacing(TimePickerHandler handler, ITimePicker timePicker)
{
}
public static void MapCharacterSpacing(TimePickerHandler handler, ITimePicker timePicker)
{
// Character spacing would require custom text rendering
}
public static void MapBackground(TimePickerHandler handler, ITimePicker timePicker)
{
if (handler.PlatformView is null) return;
if (timePicker.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackground(TimePickerHandler handler, ITimePicker timePicker)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView != null)
{
Paint background = ((IView)timePicker).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
}

View File

@@ -1,96 +1,120 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for WebView control on Linux using WebKitGTK.
/// </summary>
public partial class WebViewHandler : ViewHandler<IWebView, SkiaWebView>
public class WebViewHandler : ViewHandler<IWebView, SkiaWebView>
{
public static IPropertyMapper<IWebView, WebViewHandler> Mapper = new PropertyMapper<IWebView, WebViewHandler>(ViewHandler.ViewMapper)
{
[nameof(IWebView.Source)] = MapSource,
};
public static IPropertyMapper<IWebView, WebViewHandler> Mapper = (IPropertyMapper<IWebView, WebViewHandler>)(object)new PropertyMapper<IWebView, WebViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper }) { ["Source"] = MapSource };
public static CommandMapper<IWebView, WebViewHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
[nameof(IWebView.GoBack)] = MapGoBack,
[nameof(IWebView.GoForward)] = MapGoForward,
[nameof(IWebView.Reload)] = MapReload,
};
public static CommandMapper<IWebView, WebViewHandler> CommandMapper = new CommandMapper<IWebView, WebViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper)
{
["GoBack"] = MapGoBack,
["GoForward"] = MapGoForward,
["Reload"] = MapReload
};
public WebViewHandler() : base(Mapper, CommandMapper)
{
}
public WebViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public WebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public WebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaWebView CreatePlatformView()
{
return new SkiaWebView();
}
protected override SkiaWebView CreatePlatformView()
{
return new SkiaWebView();
}
protected override void ConnectHandler(SkiaWebView platformView)
{
base.ConnectHandler(platformView);
protected override void ConnectHandler(SkiaWebView platformView)
{
base.ConnectHandler(platformView);
platformView.Navigating += OnNavigating;
platformView.Navigated += OnNavigated;
}
platformView.Navigating += OnNavigating;
platformView.Navigated += OnNavigated;
}
protected override void DisconnectHandler(SkiaWebView platformView)
{
platformView.Navigating -= OnNavigating;
platformView.Navigated -= OnNavigated;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaWebView platformView)
{
platformView.Navigating -= OnNavigating;
platformView.Navigated -= OnNavigated;
private void OnNavigating(object? sender, WebNavigatingEventArgs e)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
IWebView virtualView = base.VirtualView;
IWebViewController val = (IWebViewController)(object)((virtualView is IWebViewController) ? virtualView : null);
if (val != null)
{
WebNavigatingEventArgs e2 = new WebNavigatingEventArgs((WebNavigationEvent)3, (WebViewSource)null, e.Url);
val.SendNavigating(e2);
}
}
base.DisconnectHandler(platformView);
}
private void OnNavigated(object? sender, WebNavigatedEventArgs e)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
IWebView virtualView = base.VirtualView;
IWebViewController val = (IWebViewController)(object)((virtualView is IWebViewController) ? virtualView : null);
if (val != null)
{
WebNavigationResult val2 = (WebNavigationResult)(e.Success ? 1 : 4);
WebNavigatedEventArgs e2 = new WebNavigatedEventArgs((WebNavigationEvent)3, (WebViewSource)null, e.Url, val2);
val.SendNavigated(e2);
}
}
private void OnNavigating(object? sender, WebNavigatingEventArgs e)
{
// Forward to virtual view if needed
}
public static void MapSource(WebViewHandler handler, IWebView webView)
{
Console.WriteLine("[WebViewHandler] MapSource called");
if (((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView == null)
{
Console.WriteLine("[WebViewHandler] PlatformView is null!");
return;
}
IWebViewSource source = webView.Source;
Console.WriteLine("[WebViewHandler] Source type: " + (((object)source)?.GetType().Name ?? "null"));
UrlWebViewSource val = (UrlWebViewSource)(object)((source is UrlWebViewSource) ? source : null);
if (val != null)
{
Console.WriteLine("[WebViewHandler] Loading URL: " + val.Url);
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView.Source = val.Url ?? "";
return;
}
HtmlWebViewSource val2 = (HtmlWebViewSource)(object)((source is HtmlWebViewSource) ? source : null);
if (val2 != null)
{
Console.WriteLine($"[WebViewHandler] Loading HTML ({val2.Html?.Length ?? 0} chars)");
Console.WriteLine("[WebViewHandler] HTML preview: " + val2.Html?.Substring(0, Math.Min(100, val2.Html?.Length ?? 0)) + "...");
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView.Html = val2.Html ?? "";
}
else
{
Console.WriteLine("[WebViewHandler] Unknown source type or null");
}
}
private void OnNavigated(object? sender, WebNavigatedEventArgs e)
{
// Forward to virtual view if needed
}
public static void MapGoBack(WebViewHandler handler, IWebView webView, object? args)
{
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.GoBack();
}
public static void MapSource(WebViewHandler handler, IWebView webView)
{
if (handler.PlatformView == null) return;
public static void MapGoForward(WebViewHandler handler, IWebView webView, object? args)
{
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.GoForward();
}
var source = webView.Source;
if (source is UrlWebViewSource urlSource)
{
handler.PlatformView.Source = urlSource.Url ?? "";
}
else if (source is HtmlWebViewSource htmlSource)
{
handler.PlatformView.Html = htmlSource.Html ?? "";
}
}
public static void MapGoBack(WebViewHandler handler, IWebView webView, object? args)
{
handler.PlatformView?.GoBack();
}
public static void MapGoForward(WebViewHandler handler, IWebView webView, object? args)
{
handler.PlatformView?.GoForward();
}
public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
{
handler.PlatformView?.Reload();
}
public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
{
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.Reload();
}
}

View File

@@ -1,281 +1,166 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using System;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
/// <summary>
/// Handler for Window on Linux.
/// Maps IWindow to the Linux display window system.
/// </summary>
public partial class WindowHandler : ElementHandler<IWindow, SkiaWindow>
public class WindowHandler : ElementHandler<IWindow, SkiaWindow>
{
public static IPropertyMapper<IWindow, WindowHandler> Mapper =
new PropertyMapper<IWindow, WindowHandler>(ElementHandler.ElementMapper)
{
[nameof(IWindow.Title)] = MapTitle,
[nameof(IWindow.Content)] = MapContent,
[nameof(IWindow.X)] = MapX,
[nameof(IWindow.Y)] = MapY,
[nameof(IWindow.Width)] = MapWidth,
[nameof(IWindow.Height)] = MapHeight,
[nameof(IWindow.MinimumWidth)] = MapMinimumWidth,
[nameof(IWindow.MinimumHeight)] = MapMinimumHeight,
[nameof(IWindow.MaximumWidth)] = MapMaximumWidth,
[nameof(IWindow.MaximumHeight)] = MapMaximumHeight,
};
public static IPropertyMapper<IWindow, WindowHandler> Mapper = (IPropertyMapper<IWindow, WindowHandler>)(object)new PropertyMapper<IWindow, WindowHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ElementHandler.ElementMapper })
{
["Title"] = MapTitle,
["Content"] = MapContent,
["X"] = MapX,
["Y"] = MapY,
["Width"] = MapWidth,
["Height"] = MapHeight,
["MinimumWidth"] = MapMinimumWidth,
["MinimumHeight"] = MapMinimumHeight,
["MaximumWidth"] = MapMaximumWidth,
["MaximumHeight"] = MapMaximumHeight
};
public static CommandMapper<IWindow, WindowHandler> CommandMapper =
new(ElementHandler.ElementCommandMapper)
{
};
public static CommandMapper<IWindow, WindowHandler> CommandMapper = new CommandMapper<IWindow, WindowHandler>((CommandMapper)(object)ElementHandler.ElementCommandMapper);
public WindowHandler() : base(Mapper, CommandMapper)
{
}
public WindowHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public WindowHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public WindowHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaWindow CreatePlatformElement()
{
return new SkiaWindow();
}
protected override SkiaWindow CreatePlatformElement()
{
return new SkiaWindow();
}
protected override void ConnectHandler(SkiaWindow platformView)
{
base.ConnectHandler(platformView);
platformView.CloseRequested += OnCloseRequested;
platformView.SizeChanged += OnSizeChanged;
}
protected override void ConnectHandler(SkiaWindow platformView)
{
base.ConnectHandler(platformView);
platformView.CloseRequested += OnCloseRequested;
platformView.SizeChanged += OnSizeChanged;
}
protected override void DisconnectHandler(SkiaWindow platformView)
{
platformView.CloseRequested -= OnCloseRequested;
platformView.SizeChanged -= OnSizeChanged;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaWindow platformView)
{
platformView.CloseRequested -= OnCloseRequested;
platformView.SizeChanged -= OnSizeChanged;
base.DisconnectHandler(platformView);
}
private void OnCloseRequested(object? sender, EventArgs e)
{
VirtualView?.Destroying();
}
private void OnCloseRequested(object? sender, EventArgs e)
{
IWindow virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Destroying();
}
}
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
{
VirtualView?.FrameChanged(new Rect(0, 0, e.Width, e.Height));
}
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
IWindow virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.FrameChanged(new Rect(0.0, 0.0, (double)e.Width, (double)e.Height));
}
}
public static void MapTitle(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Title = window.Title ?? "MAUI Application";
}
public static void MapTitle(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Title = ((ITitledElement)window).Title ?? "MAUI Application";
}
}
public static void MapContent(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
public static void MapContent(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
IView content = window.Content;
object obj;
if (content == null)
{
obj = null;
}
else
{
IViewHandler handler2 = content.Handler;
obj = ((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null);
}
if (obj is SkiaView content2)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Content = content2;
}
}
}
var content = window.Content;
if (content?.Handler?.PlatformView is SkiaView skiaContent)
{
handler.PlatformView.Content = skiaContent;
}
}
public static void MapX(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.X = (int)window.X;
}
}
public static void MapX(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.X = (int)window.X;
}
public static void MapY(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Y = (int)window.Y;
}
}
public static void MapY(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Y = (int)window.Y;
}
public static void MapWidth(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Width = (int)window.Width;
}
}
public static void MapWidth(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Width = (int)window.Width;
}
public static void MapHeight(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Height = (int)window.Height;
}
}
public static void MapHeight(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Height = (int)window.Height;
}
public static void MapMinimumWidth(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.MinWidth = (int)window.MinimumWidth;
}
}
public static void MapMinimumWidth(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MinWidth = (int)window.MinimumWidth;
}
public static void MapMinimumHeight(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.MinHeight = (int)window.MinimumHeight;
}
}
public static void MapMinimumHeight(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MinHeight = (int)window.MinimumHeight;
}
public static void MapMaximumWidth(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.MaxWidth = (int)window.MaximumWidth;
}
}
public static void MapMaximumWidth(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaxWidth = (int)window.MaximumWidth;
}
public static void MapMaximumHeight(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaxHeight = (int)window.MaximumHeight;
}
}
/// <summary>
/// Skia window wrapper for Linux display servers.
/// Handles rendering of content and popup overlays automatically.
/// </summary>
public class SkiaWindow
{
private SkiaView? _content;
private string _title = "MAUI Application";
private int _x, _y;
private int _width = 800;
private int _height = 600;
private int _minWidth = 100;
private int _minHeight = 100;
private int _maxWidth = int.MaxValue;
private int _maxHeight = int.MaxValue;
public SkiaView? Content
{
get => _content;
set
{
_content = value;
ContentChanged?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Renders the window content and popup overlays to the canvas.
/// This should be called by the platform rendering loop.
/// </summary>
public void Render(SKCanvas canvas)
{
// Clear background
canvas.Clear(SKColors.White);
// Draw main content
if (_content != null)
{
_content.Measure(new SKSize(_width, _height));
_content.Arrange(new SKRect(0, 0, _width, _height));
_content.Draw(canvas);
}
// Draw popup overlays on top (dropdowns, date pickers, etc.)
// This ensures popups always render above all other content
SkiaView.DrawPopupOverlays(canvas);
}
public string Title
{
get => _title;
set
{
_title = value;
TitleChanged?.Invoke(this, EventArgs.Empty);
}
}
public int X
{
get => _x;
set { _x = value; PositionChanged?.Invoke(this, EventArgs.Empty); }
}
public int Y
{
get => _y;
set { _y = value; PositionChanged?.Invoke(this, EventArgs.Empty); }
}
public int Width
{
get => _width;
set
{
_width = Math.Clamp(value, _minWidth, _maxWidth);
SizeChanged?.Invoke(this, new SizeChangedEventArgs(_width, _height));
}
}
public int Height
{
get => _height;
set
{
_height = Math.Clamp(value, _minHeight, _maxHeight);
SizeChanged?.Invoke(this, new SizeChangedEventArgs(_width, _height));
}
}
public int MinWidth
{
get => _minWidth;
set { _minWidth = value; }
}
public int MinHeight
{
get => _minHeight;
set { _minHeight = value; }
}
public int MaxWidth
{
get => _maxWidth;
set { _maxWidth = value; }
}
public int MaxHeight
{
get => _maxHeight;
set { _maxHeight = value; }
}
public event EventHandler? ContentChanged;
public event EventHandler? TitleChanged;
public event EventHandler? PositionChanged;
public event EventHandler<SizeChangedEventArgs>? SizeChanged;
public event EventHandler? CloseRequested;
public void Close()
{
CloseRequested?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Event args for window size changes.
/// </summary>
public class SizeChangedEventArgs : EventArgs
{
public int Width { get; }
public int Height { get; }
public SizeChangedEventArgs(int width, int height)
{
Width = width;
Height = height;
}
public static void MapMaximumHeight(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.MaxHeight = (int)window.MaximumHeight;
}
}
}