Fix compilation: restore clean RC1 codebase
- Restore clean BindableProperty.Create syntax from RC1 commit - Remove decompiler artifacts with mangled delegate types - Add Svg.Skia package reference for icon support - Fix duplicate type definitions - Library now compiles successfully (0 errors) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,62 +1,64 @@
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class ActivityIndicatorHandler : ViewHandler<IActivityIndicator, SkiaActivityIndicator>
|
||||
/// <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 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 IPropertyMapper<IActivityIndicator, ActivityIndicatorHandler> Mapper = new PropertyMapper<IActivityIndicator, ActivityIndicatorHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
[nameof(IActivityIndicator.IsRunning)] = MapIsRunning,
|
||||
[nameof(IActivityIndicator.Color)] = MapColor,
|
||||
[nameof(IView.Background)] = MapBackground,
|
||||
};
|
||||
|
||||
public static CommandMapper<IActivityIndicator, ActivityIndicatorHandler> CommandMapper = new CommandMapper<IActivityIndicator, ActivityIndicatorHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IActivityIndicator, ActivityIndicatorHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public ActivityIndicatorHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public ActivityIndicatorHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public ActivityIndicatorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public ActivityIndicatorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaActivityIndicator CreatePlatformView()
|
||||
{
|
||||
return new SkiaActivityIndicator();
|
||||
}
|
||||
protected override SkiaActivityIndicator CreatePlatformView()
|
||||
{
|
||||
return new SkiaActivityIndicator();
|
||||
}
|
||||
|
||||
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 MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsRunning = activityIndicator.IsRunning;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,137 @@
|
||||
// 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;
|
||||
|
||||
public class ApplicationHandler : ElementHandler<IApplication, LinuxApplicationContext>
|
||||
/// <summary>
|
||||
/// Handler for MAUI Application on Linux.
|
||||
/// Bridges the MAUI Application lifecycle with LinuxApplication.
|
||||
/// </summary>
|
||||
public partial class ApplicationHandler : ElementHandler<IApplication, LinuxApplicationContext>
|
||||
{
|
||||
public static IPropertyMapper<IApplication, ApplicationHandler> Mapper = (IPropertyMapper<IApplication, ApplicationHandler>)(object)new PropertyMapper<IApplication, ApplicationHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ElementHandler.ElementMapper });
|
||||
public static IPropertyMapper<IApplication, ApplicationHandler> Mapper =
|
||||
new PropertyMapper<IApplication, ApplicationHandler>(ElementHandler.ElementMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public static CommandMapper<IApplication, ApplicationHandler> CommandMapper = new CommandMapper<IApplication, ApplicationHandler>((CommandMapper)(object)ElementHandler.ElementCommandMapper)
|
||||
{
|
||||
["OpenWindow"] = MapOpenWindow,
|
||||
["CloseWindow"] = MapCloseWindow
|
||||
};
|
||||
public static CommandMapper<IApplication, ApplicationHandler> CommandMapper =
|
||||
new(ElementHandler.ElementCommandMapper)
|
||||
{
|
||||
[nameof(IApplication.OpenWindow)] = MapOpenWindow,
|
||||
[nameof(IApplication.CloseWindow)] = MapCloseWindow,
|
||||
};
|
||||
|
||||
public ApplicationHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public ApplicationHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public ApplicationHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public ApplicationHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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 = base.VirtualView;
|
||||
}
|
||||
protected override void ConnectHandler(LinuxApplicationContext platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.Application = 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)
|
||||
{
|
||||
IWindow val = (IWindow)((args is IWindow) ? args : null);
|
||||
if (val != null)
|
||||
{
|
||||
((ElementHandler<IApplication, LinuxApplicationContext>)(object)handler).PlatformView?.OpenWindow(val);
|
||||
}
|
||||
}
|
||||
public static void MapOpenWindow(ApplicationHandler handler, IApplication application, object? args)
|
||||
{
|
||||
if (args is IWindow window)
|
||||
{
|
||||
handler.PlatformView?.OpenWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,186 +1,158 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Controls.Shapes;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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.Platform.Linux.Hosting;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Platform;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class BorderHandler : ViewHandler<IBorderView, SkiaBorder>
|
||||
/// <summary>
|
||||
/// Handler for Border on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class BorderHandler : ViewHandler<IBorderView, SkiaBorder>
|
||||
{
|
||||
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 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 CommandMapper<IBorderView, BorderHandler> CommandMapper = new CommandMapper<IBorderView, BorderHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IBorderView, BorderHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public BorderHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public BorderHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public BorderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public BorderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaBorder CreatePlatformView()
|
||||
{
|
||||
return new SkiaBorder();
|
||||
}
|
||||
protected override SkiaBorder CreatePlatformView()
|
||||
{
|
||||
return new SkiaBorder();
|
||||
}
|
||||
|
||||
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 ConnectHandler(SkiaBorder platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
}
|
||||
|
||||
protected override void DisconnectHandler(SkiaBorder platformView)
|
||||
{
|
||||
platformView.Tapped -= OnPlatformViewTapped;
|
||||
platformView.MauiView = null;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaBorder platformView)
|
||||
{
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
public static void MapContent(BorderHandler handler, IBorderView border)
|
||||
{
|
||||
if (handler.PlatformView is null || handler.MauiContext is null) return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
handler.PlatformView.ClearChildren();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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 MapStrokeThickness(BorderHandler handler, IBorderView border)
|
||||
{
|
||||
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
|
||||
{
|
||||
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.StrokeThickness = (float)((IStroke)border).StrokeThickness;
|
||||
}
|
||||
}
|
||||
if (content.Handler?.PlatformView is SkiaView skiaContent)
|
||||
{
|
||||
Console.WriteLine($"[BorderHandler] Adding content: {skiaContent.GetType().Name}");
|
||||
handler.PlatformView.AddChild(skiaContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapStroke(BorderHandler handler, IBorderView border)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (border.Stroke is SolidPaint solidPaint && solidPaint.Color is not null)
|
||||
{
|
||||
handler.PlatformView.Stroke = solidPaint.Color.ToSKColor();
|
||||
}
|
||||
}
|
||||
|
||||
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 MapStrokeThickness(BorderHandler handler, IBorderView border)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.StrokeThickness = (float)border.StrokeThickness;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +1,67 @@
|
||||
// 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;
|
||||
|
||||
public class BoxViewHandler : ViewHandler<BoxView, SkiaBoxView>
|
||||
/// <summary>
|
||||
/// Handler for BoxView on Linux.
|
||||
/// </summary>
|
||||
public partial class BoxViewHandler : ViewHandler<BoxView, SkiaBoxView>
|
||||
{
|
||||
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 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 BoxViewHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)null)
|
||||
{
|
||||
}
|
||||
public BoxViewHandler() : base(Mapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaBoxView CreatePlatformView()
|
||||
{
|
||||
return new SkiaBoxView();
|
||||
}
|
||||
protected override SkiaBoxView CreatePlatformView()
|
||||
{
|
||||
return new SkiaBoxView();
|
||||
}
|
||||
|
||||
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 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 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 MapCornerRadius(BoxViewHandler handler, BoxView boxView)
|
||||
{
|
||||
handler.PlatformView.CornerRadius = (float)boxView.CornerRadius.TopLeft;
|
||||
}
|
||||
|
||||
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 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 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();
|
||||
}
|
||||
}
|
||||
public static void MapBackgroundColor(BoxViewHandler handler, BoxView boxView)
|
||||
{
|
||||
if (boxView.BackgroundColor != null)
|
||||
{
|
||||
handler.PlatformView.BackgroundColor = boxView.BackgroundColor.ToSKColor();
|
||||
handler.PlatformView.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,153 +1,198 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class ButtonHandler : ViewHandler<IButton, SkiaButton>
|
||||
/// <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 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 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 CommandMapper<IButton, ButtonHandler> CommandMapper = new CommandMapper<IButton, ButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IButton, ButtonHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public ButtonHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public ButtonHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public ButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public ButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaButton CreatePlatformView()
|
||||
{
|
||||
return new SkiaButton();
|
||||
}
|
||||
protected override SkiaButton CreatePlatformView()
|
||||
{
|
||||
var button = new SkiaButton();
|
||||
return button;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
protected override void ConnectHandler(SkiaButton platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.Clicked += OnClicked;
|
||||
platformView.Pressed += OnPressed;
|
||||
platformView.Released += OnReleased;
|
||||
|
||||
protected override void DisconnectHandler(SkiaButton platformView)
|
||||
{
|
||||
platformView.Clicked -= OnClicked;
|
||||
platformView.Pressed -= OnPressed;
|
||||
platformView.Released -= OnReleased;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
IButton virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.Clicked();
|
||||
}
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaButton platformView)
|
||||
{
|
||||
platformView.Clicked -= OnClicked;
|
||||
platformView.Pressed -= OnPressed;
|
||||
platformView.Released -= OnReleased;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
private void OnPressed(object? sender, EventArgs e)
|
||||
{
|
||||
IButton virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.Pressed();
|
||||
}
|
||||
}
|
||||
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 OnReleased(object? sender, EventArgs e)
|
||||
{
|
||||
IButton virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.Released();
|
||||
}
|
||||
}
|
||||
public static void MapStrokeColor(ButtonHandler handler, IButton button)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
var strokeColor = button.StrokeColor;
|
||||
if (strokeColor is not null)
|
||||
handler.PlatformView.BorderColor = strokeColor.ToSKColor();
|
||||
}
|
||||
|
||||
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 MapStrokeThickness(ButtonHandler handler, IButton button)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.BorderWidth = (float)button.StrokeThickness;
|
||||
}
|
||||
|
||||
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 MapCornerRadius(ButtonHandler handler, IButton button)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.CornerRadius = button.CornerRadius;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapBackground(ButtonHandler handler, IButton button)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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 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();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,164 +1,116 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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.Primitives;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class CheckBoxHandler : ViewHandler<ICheckBox, SkiaCheckBox>
|
||||
/// <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 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 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 CommandMapper<ICheckBox, CheckBoxHandler> CommandMapper = new CommandMapper<ICheckBox, CheckBoxHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<ICheckBox, CheckBoxHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public CheckBoxHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public CheckBoxHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public CheckBoxHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public CheckBoxHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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, CheckedChangedEventArgs e)
|
||||
{
|
||||
if (base.VirtualView != null && base.VirtualView.IsChecked != e.IsChecked)
|
||||
{
|
||||
base.VirtualView.IsChecked = e.IsChecked;
|
||||
}
|
||||
}
|
||||
private void OnCheckedChanged(object? sender, Platform.CheckedChangedEventArgs e)
|
||||
{
|
||||
if (VirtualView is not null && VirtualView.IsChecked != e.IsChecked)
|
||||
{
|
||||
VirtualView.IsChecked = e.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 MapIsChecked(CheckBoxHandler handler, ICheckBox checkBox)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsChecked = checkBox.IsChecked;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapForeground(CheckBoxHandler handler, ICheckBox checkBox)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (checkBox.Foreground is SolidPaint solidPaint && solidPaint.Color is not null)
|
||||
{
|
||||
handler.PlatformView.CheckColor = solidPaint.Color.ToSKColor();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
public static void MapBackground(CheckBoxHandler handler, ICheckBox checkBox)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (checkBox.Background is SolidPaint solidPaint && solidPaint.Color is not null)
|
||||
{
|
||||
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,458 +1,374 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Maui.Controls;
|
||||
// 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.Platform.Linux.Hosting;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Platform;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class CollectionViewHandler : ViewHandler<CollectionView, SkiaCollectionView>
|
||||
/// <summary>
|
||||
/// Handler for CollectionView on Linux using Skia rendering.
|
||||
/// Maps CollectionView to SkiaCollectionView platform view.
|
||||
/// </summary>
|
||||
public partial class CollectionViewHandler : ViewHandler<CollectionView, SkiaCollectionView>
|
||||
{
|
||||
private bool _isUpdatingSelection;
|
||||
private bool _isUpdatingSelection;
|
||||
|
||||
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
|
||||
};
|
||||
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 CommandMapper<CollectionView, CollectionViewHandler> CommandMapper = new CommandMapper<CollectionView, CollectionViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["ScrollTo"] = MapScrollTo };
|
||||
// SelectableItemsView properties
|
||||
[nameof(SelectableItemsView.SelectedItem)] = MapSelectedItem,
|
||||
[nameof(SelectableItemsView.SelectedItems)] = MapSelectedItems,
|
||||
[nameof(SelectableItemsView.SelectionMode)] = MapSelectionMode,
|
||||
|
||||
public CollectionViewHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
// StructuredItemsView properties
|
||||
[nameof(StructuredItemsView.Header)] = MapHeader,
|
||||
[nameof(StructuredItemsView.Footer)] = MapFooter,
|
||||
[nameof(StructuredItemsView.ItemsLayout)] = MapItemsLayout,
|
||||
|
||||
public CollectionViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
[nameof(IView.Background)] = MapBackground,
|
||||
[nameof(CollectionView.BackgroundColor)] = MapBackgroundColor,
|
||||
};
|
||||
|
||||
protected override SkiaCollectionView CreatePlatformView()
|
||||
{
|
||||
return new SkiaCollectionView();
|
||||
}
|
||||
public static CommandMapper<CollectionView, CollectionViewHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
["ScrollTo"] = MapScrollTo,
|
||||
};
|
||||
|
||||
protected override void ConnectHandler(SkiaCollectionView platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.SelectionChanged += OnSelectionChanged;
|
||||
platformView.Scrolled += OnScrolled;
|
||||
platformView.ItemTapped += OnItemTapped;
|
||||
}
|
||||
public CollectionViewHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void DisconnectHandler(SkiaCollectionView platformView)
|
||||
{
|
||||
platformView.SelectionChanged -= OnSelectionChanged;
|
||||
platformView.Scrolled -= OnScrolled;
|
||||
platformView.ItemTapped -= OnItemTapped;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
public CollectionViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
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 SkiaCollectionView CreatePlatformView()
|
||||
{
|
||||
return new SkiaCollectionView();
|
||||
}
|
||||
|
||||
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 ConnectHandler(SkiaCollectionView platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.SelectionChanged += OnSelectionChanged;
|
||||
platformView.Scrolled += OnScrolled;
|
||||
platformView.ItemTapped += OnItemTapped;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaCollectionView platformView)
|
||||
{
|
||||
platformView.SelectionChanged -= OnSelectionChanged;
|
||||
platformView.Scrolled -= OnScrolled;
|
||||
platformView.ItemTapped -= OnItemTapped;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private void OnSelectionChanged(object? sender, CollectionSelectionChangedEventArgs e)
|
||||
{
|
||||
if (VirtualView is null || _isUpdatingSelection) return;
|
||||
|
||||
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();
|
||||
}
|
||||
try
|
||||
{
|
||||
_isUpdatingSelection = true;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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 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 OnScrolled(object? sender, ItemsScrolledEventArgs e)
|
||||
{
|
||||
VirtualView?.SendScrolled(new ItemsViewScrolledEventArgs
|
||||
{
|
||||
VerticalOffset = e.ScrollOffset,
|
||||
VerticalDelta = 0,
|
||||
HorizontalOffset = 0,
|
||||
HorizontalDelta = 0
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
|
||||
{
|
||||
// Item tap is handled through selection
|
||||
}
|
||||
|
||||
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 MapItemsSource(CollectionViewHandler handler, CollectionView collectionView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.ItemsSource = collectionView.ItemsSource;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
public static void MapItemTemplate(CollectionViewHandler handler, CollectionView collectionView)
|
||||
{
|
||||
if (handler.PlatformView is null || handler.MauiContext is null) return;
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
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 MapHeader(CollectionViewHandler handler, CollectionView collectionView)
|
||||
{
|
||||
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
|
||||
{
|
||||
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Header = ((StructuredItemsView)collectionView).Header;
|
||||
}
|
||||
}
|
||||
// Force binding evaluation by accessing the visual tree
|
||||
// This ensures child bindings are evaluated before handler creation
|
||||
PropagateBindingContext(view, item);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
// Create handler for the view
|
||||
if (view.Handler == null && handler.MauiContext != null)
|
||||
{
|
||||
view.Handler = view.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 (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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cellView.Handler?.PlatformView is SkiaView skiaView)
|
||||
{
|
||||
return skiaView;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore template creation errors
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
handler.PlatformView.Invalidate();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapEmptyView(CollectionViewHandler handler, CollectionView collectionView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,133 +1,114 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class DatePickerHandler : ViewHandler<IDatePicker, SkiaDatePicker>
|
||||
/// <summary>
|
||||
/// Handler for DatePicker on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class DatePickerHandler : ViewHandler<IDatePicker, SkiaDatePicker>
|
||||
{
|
||||
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 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 CommandMapper<IDatePicker, DatePickerHandler> CommandMapper = new CommandMapper<IDatePicker, DatePickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IDatePicker, DatePickerHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public DatePickerHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public DatePickerHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public DatePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public DatePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaDatePicker CreatePlatformView()
|
||||
{
|
||||
return new SkiaDatePicker();
|
||||
}
|
||||
protected override SkiaDatePicker CreatePlatformView()
|
||||
{
|
||||
return new SkiaDatePicker();
|
||||
}
|
||||
|
||||
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 ConnectHandler(SkiaDatePicker platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.DateSelected += OnDateSelected;
|
||||
}
|
||||
|
||||
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 (base.VirtualView != null && base.PlatformView != null)
|
||||
{
|
||||
base.VirtualView.Date = base.PlatformView.Date;
|
||||
}
|
||||
}
|
||||
private void OnDateSelected(object? sender, EventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
VirtualView.Date = PlatformView.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 MapDate(DatePickerHandler handler, IDatePicker datePicker)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Date = datePicker.Date;
|
||||
}
|
||||
|
||||
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 MapMinimumDate(DatePickerHandler handler, IDatePicker datePicker)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.MinimumDate = datePicker.MinimumDate;
|
||||
}
|
||||
|
||||
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 MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.MaximumDate = datePicker.MaximumDate;
|
||||
}
|
||||
|
||||
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 MapFormat(DatePickerHandler handler, IDatePicker datePicker)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Format = datePicker.Format ?? "d";
|
||||
}
|
||||
|
||||
public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker)
|
||||
{
|
||||
}
|
||||
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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,182 +1,181 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class EditorHandler : ViewHandler<IEditor, SkiaEditor>
|
||||
/// <summary>
|
||||
/// Handler for Editor (multiline text) on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class EditorHandler : ViewHandler<IEditor, SkiaEditor>
|
||||
{
|
||||
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 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 CommandMapper<IEditor, EditorHandler> CommandMapper = new CommandMapper<IEditor, EditorHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IEditor, EditorHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public EditorHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public EditorHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public EditorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public EditorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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 (base.VirtualView != null && base.PlatformView != null)
|
||||
{
|
||||
((ITextInput)base.VirtualView).Text = base.PlatformView.Text;
|
||||
}
|
||||
}
|
||||
private void OnTextChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
|
||||
private void OnCompleted(object? sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
VirtualView.Text = PlatformView.Text;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
private void OnCompleted(object? sender, EventArgs e)
|
||||
{
|
||||
// Editor doesn't typically have a completed event, but we could trigger it
|
||||
}
|
||||
|
||||
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 MapText(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Text = editor.Text ?? "";
|
||||
handler.PlatformView.Invalidate();
|
||||
}
|
||||
|
||||
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 MapPlaceholder(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Placeholder = editor.Placeholder ?? "";
|
||||
}
|
||||
|
||||
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 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 MapCharacterSpacing(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
}
|
||||
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 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 MapCharacterSpacing(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
// Character spacing would require custom text rendering
|
||||
}
|
||||
|
||||
public static void MapIsTextPredictionEnabled(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
}
|
||||
public static void MapIsReadOnly(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsReadOnly = editor.IsReadOnly;
|
||||
}
|
||||
|
||||
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 MapIsTextPredictionEnabled(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
// Text prediction not applicable to desktop
|
||||
}
|
||||
|
||||
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 MapMaxLength(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.MaxLength = editor.MaxLength;
|
||||
}
|
||||
|
||||
public static void MapSelectionLength(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
}
|
||||
public static void MapCursorPosition(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.CursorPosition = editor.CursorPosition;
|
||||
}
|
||||
|
||||
public static void MapKeyboard(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
}
|
||||
public static void MapSelectionLength(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
// Selection would need to be added to SkiaEditor
|
||||
}
|
||||
|
||||
public static void MapHorizontalTextAlignment(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
}
|
||||
public static void MapKeyboard(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
// Virtual keyboard type not applicable to desktop
|
||||
}
|
||||
|
||||
public static void MapVerticalTextAlignment(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
}
|
||||
public static void MapHorizontalTextAlignment(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 MapVerticalTextAlignment(EditorHandler handler, IEditor editor)
|
||||
{
|
||||
// Text alignment would require changes to SkiaEditor drawing
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,280 +1,215 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class EntryHandler : ViewHandler<IEntry, SkiaEntry>
|
||||
/// <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 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 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 CommandMapper<IEntry, EntryHandler> CommandMapper = new CommandMapper<IEntry, EntryHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IEntry, EntryHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public EntryHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public EntryHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public EntryHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public EntryHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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, TextChangedEventArgs e)
|
||||
{
|
||||
if (base.VirtualView != null && base.PlatformView != null && ((ITextInput)base.VirtualView).Text != e.NewTextValue)
|
||||
{
|
||||
((ITextInput)base.VirtualView).Text = e.NewTextValue ?? string.Empty;
|
||||
}
|
||||
}
|
||||
private void OnTextChanged(object? sender, Platform.TextChangedEventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
|
||||
private void OnCompleted(object? sender, EventArgs e)
|
||||
{
|
||||
IEntry virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.Completed();
|
||||
}
|
||||
}
|
||||
if (VirtualView.Text != e.NewTextValue)
|
||||
{
|
||||
VirtualView.Text = e.NewTextValue ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
private void OnCompleted(object? sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.Completed();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
public static void MapText(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (handler.PlatformView.Text != entry.Text)
|
||||
{
|
||||
handler.PlatformView.Text = entry.Text ?? string.Empty;
|
||||
handler.PlatformView.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
public static void MapTextColor(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (entry.TextColor is not null)
|
||||
handler.PlatformView.TextColor = entry.TextColor.ToSKColor();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
public static void MapFont(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
var font = entry.Font;
|
||||
if (font.Size > 0)
|
||||
handler.PlatformView.FontSize = (float)font.Size;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(font.Family))
|
||||
handler.PlatformView.FontFamily = font.Family;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
handler.PlatformView.IsBold = font.Weight >= FontWeight.Bold;
|
||||
handler.PlatformView.IsItalic = font.Slant == FontSlant.Italic || font.Slant == FontSlant.Oblique;
|
||||
}
|
||||
|
||||
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 MapCharacterSpacing(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.CharacterSpacing = (float)entry.CharacterSpacing;
|
||||
}
|
||||
|
||||
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 MapPlaceholder(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Placeholder = entry.Placeholder ?? string.Empty;
|
||||
}
|
||||
|
||||
public static void MapReturnType(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
_ = ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView;
|
||||
}
|
||||
public static void MapPlaceholderColor(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (entry.PlaceholderColor is not null)
|
||||
handler.PlatformView.PlaceholderColor = entry.PlaceholderColor.ToSKColor();
|
||||
}
|
||||
|
||||
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 MapIsReadOnly(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsReadOnly = entry.IsReadOnly;
|
||||
}
|
||||
|
||||
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 MapMaxLength(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.MaxLength = entry.MaxLength;
|
||||
}
|
||||
|
||||
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 MapCursorPosition(EntryHandler handler, IEntry entry)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.CursorPosition = entry.CursorPosition;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +1,91 @@
|
||||
using System;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class FlyoutPageHandler : ViewHandler<IFlyoutView, SkiaFlyoutPage>
|
||||
/// <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 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 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 CommandMapper<IFlyoutView, FlyoutPageHandler> CommandMapper = new CommandMapper<IFlyoutView, FlyoutPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IFlyoutView, FlyoutPageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public FlyoutPageHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public FlyoutPageHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public FlyoutPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public FlyoutPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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)
|
||||
{
|
||||
}
|
||||
private void OnIsPresentedChanged(object? sender, EventArgs e)
|
||||
{
|
||||
// Sync back to the virtual view
|
||||
}
|
||||
|
||||
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 MapIsPresented(FlyoutPageHandler handler, IFlyoutView flyoutView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsPresented = flyoutView.IsPresented;
|
||||
}
|
||||
|
||||
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 MapFlyoutWidth(FlyoutPageHandler handler, IFlyoutView flyoutView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.FlyoutWidth = (float)flyoutView.FlyoutWidth;
|
||||
}
|
||||
|
||||
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 MapIsGestureEnabled(FlyoutPageHandler handler, IFlyoutView flyoutView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.GestureEnabled = flyoutView.IsGestureEnabled;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,134 +1,104 @@
|
||||
using System;
|
||||
// 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.Controls.Compatibility;
|
||||
using Microsoft.Maui.Handlers;
|
||||
using Microsoft.Maui.Platform.Linux.Hosting;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class FrameHandler : ViewHandler<Frame, SkiaFrame>
|
||||
/// <summary>
|
||||
/// Handler for Frame on Linux using SkiaFrame.
|
||||
/// </summary>
|
||||
public partial class FrameHandler : ViewHandler<Frame, SkiaFrame>
|
||||
{
|
||||
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 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 FrameHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)null)
|
||||
{
|
||||
}
|
||||
public FrameHandler() : base(Mapper)
|
||||
{
|
||||
}
|
||||
|
||||
public FrameHandler(IPropertyMapper? mapper)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)null)
|
||||
{
|
||||
}
|
||||
public FrameHandler(IPropertyMapper? mapper)
|
||||
: base(mapper ?? Mapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaFrame CreatePlatformView()
|
||||
{
|
||||
return new SkiaFrame();
|
||||
}
|
||||
protected override SkiaFrame CreatePlatformView()
|
||||
{
|
||||
return new SkiaFrame();
|
||||
}
|
||||
|
||||
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 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 DisconnectHandler(SkiaFrame platformView)
|
||||
{
|
||||
platformView.Tapped -= OnPlatformViewTapped;
|
||||
platformView.MauiView = null;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
public static void MapCornerRadius(FrameHandler handler, Frame frame)
|
||||
{
|
||||
handler.PlatformView.CornerRadius = frame.CornerRadius;
|
||||
}
|
||||
|
||||
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 MapHasShadow(FrameHandler handler, Frame frame)
|
||||
{
|
||||
handler.PlatformView.HasShadow = frame.HasShadow;
|
||||
}
|
||||
|
||||
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 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 MapCornerRadius(FrameHandler handler, Frame frame)
|
||||
{
|
||||
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.CornerRadius = frame.CornerRadius;
|
||||
}
|
||||
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 MapHasShadow(FrameHandler handler, Frame frame)
|
||||
{
|
||||
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.HasShadow = frame.HasShadow;
|
||||
}
|
||||
public static void MapContent(FrameHandler handler, Frame frame)
|
||||
{
|
||||
if (handler.PlatformView is null || handler.MauiContext is null) return;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
handler.PlatformView.ClearChildren();
|
||||
|
||||
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);
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (content.Handler?.PlatformView is SkiaView skiaContent)
|
||||
{
|
||||
handler.PlatformView.AddChild(skiaContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,547 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,62 @@
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class GraphicsViewHandler : ViewHandler<IGraphicsView, SkiaGraphicsView>
|
||||
/// <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 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 IPropertyMapper<IGraphicsView, GraphicsViewHandler> Mapper = new PropertyMapper<IGraphicsView, GraphicsViewHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
[nameof(IGraphicsView.Drawable)] = MapDrawable,
|
||||
[nameof(IView.Background)] = MapBackground,
|
||||
};
|
||||
|
||||
public static CommandMapper<IGraphicsView, GraphicsViewHandler> CommandMapper = new CommandMapper<IGraphicsView, GraphicsViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["Invalidate"] = MapInvalidate };
|
||||
public static CommandMapper<IGraphicsView, GraphicsViewHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
[nameof(IGraphicsView.Invalidate)] = MapInvalidate,
|
||||
};
|
||||
|
||||
public GraphicsViewHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public GraphicsViewHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public GraphicsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public GraphicsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaGraphicsView CreatePlatformView()
|
||||
{
|
||||
return new SkiaGraphicsView();
|
||||
}
|
||||
protected override SkiaGraphicsView CreatePlatformView()
|
||||
{
|
||||
return new SkiaGraphicsView();
|
||||
}
|
||||
|
||||
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 MapDrawable(GraphicsViewHandler handler, IGraphicsView graphicsView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Drawable = graphicsView.Drawable;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapBackground(GraphicsViewHandler handler, IGraphicsView graphicsView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
public static void MapInvalidate(GraphicsViewHandler handler, IGraphicsView graphicsView, object? args)
|
||||
{
|
||||
((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView?.Invalidate();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,275 +1,233 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class ImageButtonHandler : ViewHandler<IImageButton, SkiaImageButton>
|
||||
/// <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>
|
||||
{
|
||||
internal class ImageSourceServiceResultManager
|
||||
{
|
||||
private readonly ImageButtonHandler _handler;
|
||||
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,
|
||||
};
|
||||
|
||||
private CancellationTokenSource? _cts;
|
||||
public static CommandMapper<IImageButton, ImageButtonHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public ImageSourceServiceResultManager(ImageButtonHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
public ImageButtonHandler() : base(Mapper, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public ImageButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
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 SkiaImageButton CreatePlatformView()
|
||||
{
|
||||
return new SkiaImageButton();
|
||||
}
|
||||
|
||||
public static CommandMapper<IImageButton, ImageButtonHandler> CommandMapper = new CommandMapper<IImageButton, ImageButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
protected override void ConnectHandler(SkiaImageButton platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.Clicked += OnClicked;
|
||||
platformView.Pressed += OnPressed;
|
||||
platformView.Released += OnReleased;
|
||||
platformView.ImageLoaded += OnImageLoaded;
|
||||
platformView.ImageLoadingError += OnImageLoadingError;
|
||||
}
|
||||
|
||||
private ImageSourceServiceResultManager _sourceLoader;
|
||||
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 => _sourceLoader ?? (_sourceLoader = new ImageSourceServiceResultManager(this));
|
||||
private void OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.Clicked();
|
||||
}
|
||||
|
||||
public ImageButtonHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
private void OnPressed(object? sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.Pressed();
|
||||
}
|
||||
|
||||
public ImageButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
private void OnReleased(object? sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.Released();
|
||||
}
|
||||
|
||||
protected override SkiaImageButton CreatePlatformView()
|
||||
{
|
||||
return new SkiaImageButton();
|
||||
}
|
||||
private void OnImageLoaded(object? sender, EventArgs 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;
|
||||
}
|
||||
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
|
||||
{
|
||||
if (VirtualView is IImageSourcePart imageSourcePart)
|
||||
{
|
||||
imageSourcePart.UpdateIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
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 MapAspect(ImageButtonHandler handler, IImageButton imageButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Aspect = imageButton.Aspect;
|
||||
}
|
||||
|
||||
private void OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
IImageButton virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
((IButton)virtualView).Clicked();
|
||||
}
|
||||
}
|
||||
public static void MapIsOpaque(ImageButtonHandler handler, IImageButton imageButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsOpaque = imageButton.IsOpaque;
|
||||
}
|
||||
|
||||
private void OnPressed(object? sender, EventArgs e)
|
||||
{
|
||||
IImageButton virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
((IButton)virtualView).Pressed();
|
||||
}
|
||||
}
|
||||
public static void MapSource(ImageButtonHandler handler, IImageButton imageButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.SourceLoader.UpdateImageSourceAsync();
|
||||
}
|
||||
|
||||
private void OnReleased(object? sender, EventArgs e)
|
||||
{
|
||||
IImageButton virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
((IButton)virtualView).Released();
|
||||
}
|
||||
}
|
||||
public static void MapStrokeColor(ImageButtonHandler handler, IImageButton imageButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
private void OnImageLoaded(object? sender, EventArgs e)
|
||||
{
|
||||
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.UpdateIsLoading(false);
|
||||
}
|
||||
}
|
||||
if (imageButton.StrokeColor is not null)
|
||||
handler.PlatformView.StrokeColor = imageButton.StrokeColor.ToSKColor();
|
||||
}
|
||||
|
||||
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs 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;
|
||||
}
|
||||
|
||||
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 MapCornerRadius(ImageButtonHandler handler, IImageButton imageButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.CornerRadius = imageButton.CornerRadius;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
public static void MapPadding(ImageButtonHandler handler, IImageButton imageButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
public static void MapSource(ImageButtonHandler handler, IImageButton imageButton)
|
||||
{
|
||||
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
|
||||
{
|
||||
handler.SourceLoader.UpdateImageSourceAsync();
|
||||
}
|
||||
}
|
||||
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 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();
|
||||
}
|
||||
}
|
||||
public static void MapBackground(ImageButtonHandler handler, IImageButton imageButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (imageButton.Background is SolidPaint solidPaint && solidPaint.Color is not null)
|
||||
{
|
||||
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
// Image source loading helper
|
||||
private ImageSourceServiceResultManager _sourceLoader = null!;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private ImageSourceServiceResultManager SourceLoader =>
|
||||
_sourceLoader ??= new ImageSourceServiceResultManager(this);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
internal class ImageSourceServiceResultManager
|
||||
{
|
||||
private readonly ImageButtonHandler _handler;
|
||||
private CancellationTokenSource? _cts;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,342 +1,180 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class ImageHandler : ViewHandler<IImage, SkiaImage>
|
||||
/// <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>
|
||||
{
|
||||
internal class ImageSourceServiceResultManager
|
||||
{
|
||||
private readonly ImageHandler _handler;
|
||||
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,
|
||||
};
|
||||
|
||||
private CancellationTokenSource? _cts;
|
||||
public static CommandMapper<IImage, ImageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public ImageSourceServiceResultManager(ImageHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
public ImageHandler() : base(Mapper, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
public ImageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
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 SkiaImage CreatePlatformView()
|
||||
{
|
||||
return new SkiaImage();
|
||||
}
|
||||
|
||||
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 ConnectHandler(SkiaImage platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.ImageLoaded += OnImageLoaded;
|
||||
platformView.ImageLoadingError += OnImageLoadingError;
|
||||
}
|
||||
|
||||
public static CommandMapper<IImage, ImageHandler> CommandMapper = new CommandMapper<IImage, ImageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
protected override void DisconnectHandler(SkiaImage platformView)
|
||||
{
|
||||
platformView.ImageLoaded -= OnImageLoaded;
|
||||
platformView.ImageLoadingError -= OnImageLoadingError;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
private ImageSourceServiceResultManager _sourceLoader;
|
||||
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 => _sourceLoader ?? (_sourceLoader = new ImageSourceServiceResultManager(this));
|
||||
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
|
||||
{
|
||||
// Handle loading error
|
||||
if (VirtualView is IImageSourcePart imageSourcePart)
|
||||
{
|
||||
imageSourcePart.UpdateIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
public ImageHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public static void MapAspect(ImageHandler handler, IImage image)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Aspect = image.Aspect;
|
||||
}
|
||||
|
||||
public ImageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public static void MapIsOpaque(ImageHandler handler, IImage image)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsOpaque = image.IsOpaque;
|
||||
}
|
||||
|
||||
protected override SkiaImage CreatePlatformView()
|
||||
{
|
||||
return new SkiaImage();
|
||||
}
|
||||
public static void MapSource(ImageHandler handler, IImage image)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
protected override void ConnectHandler(SkiaImage platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.ImageLoaded += OnImageLoaded;
|
||||
platformView.ImageLoadingError += OnImageLoadingError;
|
||||
}
|
||||
handler.SourceLoader.UpdateImageSourceAsync();
|
||||
}
|
||||
|
||||
protected override void DisconnectHandler(SkiaImage platformView)
|
||||
{
|
||||
platformView.ImageLoaded -= OnImageLoaded;
|
||||
platformView.ImageLoadingError -= OnImageLoadingError;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
public static void MapBackground(ImageHandler handler, IImage image)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
private void OnImageLoaded(object? sender, EventArgs e)
|
||||
{
|
||||
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.UpdateIsLoading(false);
|
||||
}
|
||||
}
|
||||
if (image.Background is SolidPaint solidPaint && solidPaint.Color is not null)
|
||||
{
|
||||
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
|
||||
{
|
||||
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.UpdateIsLoading(false);
|
||||
}
|
||||
}
|
||||
// Image source loading helper
|
||||
private ImageSourceServiceResultManager _sourceLoader = null!;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private ImageSourceServiceResultManager SourceLoader =>
|
||||
_sourceLoader ??= new ImageSourceServiceResultManager(this);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
internal class ImageSourceServiceResultManager
|
||||
{
|
||||
private readonly ImageHandler _handler;
|
||||
private CancellationTokenSource? _cts;
|
||||
|
||||
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 ImageSourceServiceResultManager(ImageHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
public async void UpdateImageSourceAsync()
|
||||
{
|
||||
_cts?.Cancel();
|
||||
_cts = new CancellationTokenSource();
|
||||
var token = _cts.Token;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
var source = _handler.VirtualView?.Source;
|
||||
if (source == null)
|
||||
{
|
||||
_handler.PlatformView?.LoadFromData(Array.Empty<byte>());
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,175 +1,164 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class ItemsViewHandler<TItemsView> : ViewHandler<TItemsView, SkiaItemsView> where TItemsView : ItemsView
|
||||
/// <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 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 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 CommandMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewCommandMapper = new CommandMapper<TItemsView, ItemsViewHandler<TItemsView>>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["ScrollTo"] = MapScrollTo };
|
||||
public static CommandMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewCommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
["ScrollTo"] = MapScrollTo,
|
||||
};
|
||||
|
||||
public ItemsViewHandler()
|
||||
: base((IPropertyMapper)(object)ItemsViewMapper, (CommandMapper)(object)ItemsViewCommandMapper)
|
||||
{
|
||||
}
|
||||
public ItemsViewHandler() : base(ItemsViewMapper, ItemsViewCommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public ItemsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)ItemsViewMapper)), (CommandMapper)(((object)commandMapper) ?? ((object)ItemsViewCommandMapper)))
|
||||
{
|
||||
}
|
||||
public ItemsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? ItemsViewMapper, commandMapper ?? 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;
|
||||
platformView.ItemRenderer = RenderItem;
|
||||
}
|
||||
protected override void ConnectHandler(SkiaItemsView platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.Scrolled += OnScrolled;
|
||||
platformView.ItemTapped += OnItemTapped;
|
||||
|
||||
protected override void DisconnectHandler(SkiaItemsView platformView)
|
||||
{
|
||||
platformView.Scrolled -= OnScrolled;
|
||||
platformView.ItemTapped -= OnItemTapped;
|
||||
platformView.ItemRenderer = null;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
// Set up item renderer
|
||||
platformView.ItemRenderer = RenderItem;
|
||||
}
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaItemsView platformView)
|
||||
{
|
||||
platformView.Scrolled -= OnScrolled;
|
||||
platformView.ItemTapped -= OnItemTapped;
|
||||
platformView.ItemRenderer = null;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
|
||||
{
|
||||
}
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
|
||||
{
|
||||
// Item tap handling - can be extended for selection
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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 MapItemTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
|
||||
{
|
||||
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView?.Invalidate();
|
||||
}
|
||||
// For now, render based on item ToString
|
||||
// Full DataTemplate support would require creating actual views
|
||||
return false;
|
||||
}
|
||||
|
||||
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 MapItemsSource(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.ItemsSource = itemsView.ItemsSource;
|
||||
}
|
||||
|
||||
public static void MapEmptyViewTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
|
||||
{
|
||||
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView?.Invalidate();
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
public static void MapEmptyView(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
handler.PlatformView.EmptyView = itemsView.EmptyView;
|
||||
if (itemsView.EmptyView is string text)
|
||||
{
|
||||
handler.PlatformView.EmptyViewText = text;
|
||||
}
|
||||
}
|
||||
|
||||
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 MapEmptyViewTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
|
||||
{
|
||||
// EmptyViewTemplate would be used to render custom empty view
|
||||
handler.PlatformView?.Invalidate();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,388 +1,208 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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.Platform.Linux.Window;
|
||||
using Microsoft.Maui.Primitives;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class LabelHandler : ViewHandler<ILabel, SkiaLabel>
|
||||
/// <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 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 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 CommandMapper<ILabel, LabelHandler> CommandMapper = new CommandMapper<ILabel, LabelHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<ILabel, LabelHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public LabelHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public LabelHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public LabelHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public LabelHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaLabel CreatePlatformView()
|
||||
{
|
||||
return new SkiaLabel();
|
||||
}
|
||||
protected override SkiaLabel CreatePlatformView()
|
||||
{
|
||||
return new SkiaLabel();
|
||||
}
|
||||
|
||||
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 MapText(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Text = label.Text ?? string.Empty;
|
||||
}
|
||||
|
||||
protected override void DisconnectHandler(SkiaLabel platformView)
|
||||
{
|
||||
platformView.Tapped -= OnPlatformViewTapped;
|
||||
platformView.MauiView = null;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
public static void MapTextColor(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (label.TextColor is not null)
|
||||
handler.PlatformView.TextColor = label.TextColor.ToSKColor();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
public static void MapFont(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
var font = label.Font;
|
||||
if (font.Size > 0)
|
||||
handler.PlatformView.FontSize = (float)font.Size;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(font.Family))
|
||||
handler.PlatformView.FontFamily = font.Family;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
handler.PlatformView.IsBold = font.Weight >= FontWeight.Bold;
|
||||
handler.PlatformView.IsItalic = font.Slant == FontSlant.Italic || font.Slant == FontSlant.Oblique;
|
||||
}
|
||||
|
||||
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 MapCharacterSpacing(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.CharacterSpacing = (float)label.CharacterSpacing;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
public static void MapHorizontalTextAlignment(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
// 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 MapLineHeight(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
|
||||
{
|
||||
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.LineHeight = (float)label.LineHeight;
|
||||
}
|
||||
}
|
||||
public static void MapVerticalTextAlignment(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapTextDecorations(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
handler.PlatformView.IsUnderline = (label.TextDecorations & TextDecorations.Underline) != 0;
|
||||
handler.PlatformView.IsStrikethrough = (label.TextDecorations & TextDecorations.Strikethrough) != 0;
|
||||
}
|
||||
|
||||
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 MapLineHeight(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.LineHeight = (float)label.LineHeight;
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
public static void MapLineBreakMode(LabelHandler handler, ILabel label)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
// 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 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;
|
||||
}
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,166 +1,368 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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.Platform.Linux.Hosting;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class LayoutHandler : ViewHandler<ILayout, SkiaLayoutView>
|
||||
/// <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 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 IPropertyMapper<ILayout, LayoutHandler> Mapper = new PropertyMapper<ILayout, LayoutHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
[nameof(ILayout.ClipsToBounds)] = MapClipsToBounds,
|
||||
[nameof(IView.Background)] = MapBackground,
|
||||
[nameof(IPadding.Padding)] = MapPadding,
|
||||
};
|
||||
|
||||
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 static CommandMapper<ILayout, LayoutHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
["Add"] = MapAdd,
|
||||
["Remove"] = MapRemove,
|
||||
["Clear"] = MapClear,
|
||||
["Insert"] = MapInsert,
|
||||
["Update"] = MapUpdate,
|
||||
};
|
||||
|
||||
public LayoutHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public LayoutHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public LayoutHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public LayoutHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaLayoutView CreatePlatformView()
|
||||
{
|
||||
return new SkiaStackLayout();
|
||||
}
|
||||
protected override SkiaLayoutView CreatePlatformView()
|
||||
{
|
||||
return new SkiaStackLayout();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void ConnectHandler(SkiaLayoutView platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
// Create handlers for all children and add them to the platform view
|
||||
if (VirtualView == null || MauiContext == null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < VirtualView.Count; i++)
|
||||
{
|
||||
var child = VirtualView[i];
|
||||
if (child == null) continue;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Create handler for child if it doesn't exist
|
||||
if (child.Handler == null)
|
||||
{
|
||||
child.Handler = child.ToHandler(MauiContext);
|
||||
}
|
||||
|
||||
public static void MapClear(LayoutHandler handler, ILayout layout, object? arg)
|
||||
{
|
||||
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView?.ClearChildren();
|
||||
}
|
||||
// Add child's platform view to our layout
|
||||
if (child.Handler?.PlatformView is SkiaView skiaChild)
|
||||
{
|
||||
platformView.AddChild(skiaChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapInsert(LayoutHandler handler, ILayout layout, object? arg)
|
||||
{
|
||||
MapAdd(handler, layout, arg);
|
||||
}
|
||||
public static void MapClipsToBounds(LayoutHandler handler, ILayout layout)
|
||||
{
|
||||
if (handler.PlatformView == null) return;
|
||||
handler.PlatformView.ClipToBounds = layout.ClipsToBounds;
|
||||
}
|
||||
|
||||
public static void MapUpdate(LayoutHandler handler, ILayout layout, object? arg)
|
||||
{
|
||||
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView?.InvalidateMeasure();
|
||||
}
|
||||
public static void MapBackground(LayoutHandler handler, ILayout layout)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,448 +1,381 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Maui.Controls;
|
||||
// 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.Platform.Linux.Hosting;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Platform;
|
||||
using SkiaSharp;
|
||||
using Svg.Skia;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNavigationPage>
|
||||
/// <summary>
|
||||
/// Handler for NavigationPage on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNavigationPage>
|
||||
{
|
||||
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 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 CommandMapper<NavigationPage, NavigationPageHandler> CommandMapper = new CommandMapper<NavigationPage, NavigationPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["RequestNavigation"] = MapRequestNavigation };
|
||||
public static CommandMapper<NavigationPage, NavigationPageHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
[nameof(IStackNavigationView.RequestNavigation)] = MapRequestNavigation,
|
||||
};
|
||||
|
||||
private readonly Dictionary<Page, (SkiaPage, INotifyCollectionChanged)> _toolbarSubscriptions = new Dictionary<Page, (SkiaPage, INotifyCollectionChanged)>();
|
||||
public NavigationPageHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public NavigationPageHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public NavigationPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public NavigationPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
protected override SkiaNavigationPage CreatePlatformView()
|
||||
{
|
||||
return new SkiaNavigationPage();
|
||||
}
|
||||
|
||||
protected override SkiaNavigationPage CreatePlatformView()
|
||||
{
|
||||
return new SkiaNavigationPage();
|
||||
}
|
||||
protected override void ConnectHandler(SkiaNavigationPage platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.Pushed += OnPushed;
|
||||
platformView.Popped += OnPopped;
|
||||
platformView.PoppedToRoot += OnPoppedToRoot;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
// Subscribe to navigation events from virtual view
|
||||
if (VirtualView != null)
|
||||
{
|
||||
VirtualView.Pushed += OnVirtualViewPushed;
|
||||
VirtualView.Popped += OnVirtualViewPopped;
|
||||
VirtualView.PoppedToRoot += OnVirtualViewPoppedToRoot;
|
||||
|
||||
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);
|
||||
}
|
||||
// Set up initial navigation stack
|
||||
SetupNavigationStack();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaNavigationPage platformView)
|
||||
{
|
||||
platformView.Pushed -= OnPushed;
|
||||
platformView.Popped -= OnPopped;
|
||||
platformView.PoppedToRoot -= OnPoppedToRoot;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (VirtualView != null)
|
||||
{
|
||||
VirtualView.Pushed -= OnVirtualViewPushed;
|
||||
VirtualView.Popped -= OnVirtualViewPopped;
|
||||
VirtualView.PoppedToRoot -= OnVirtualViewPoppedToRoot;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private void SetupNavigationStack()
|
||||
{
|
||||
if (VirtualView == null || PlatformView == null || MauiContext == null) return;
|
||||
|
||||
private void OnVirtualViewPopped(object? sender, NavigationEventArgs e)
|
||||
{
|
||||
Page page = e.Page;
|
||||
Console.WriteLine("[NavigationPageHandler] VirtualView Popped: " + ((page != null) ? page.Title : null));
|
||||
base.PlatformView?.Pop();
|
||||
}
|
||||
// Get all pages in the navigation stack
|
||||
var pages = VirtualView.Navigation.NavigationStack.ToList();
|
||||
Console.WriteLine($"[NavigationPageHandler] Setting up {pages.Count} pages");
|
||||
|
||||
private void OnVirtualViewPoppedToRoot(object? sender, NavigationEventArgs e)
|
||||
{
|
||||
Console.WriteLine("[NavigationPageHandler] VirtualView PoppedToRoot");
|
||||
base.PlatformView?.PopToRoot();
|
||||
}
|
||||
// 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 OnPushed(object? sender, NavigationEventArgs e)
|
||||
{
|
||||
}
|
||||
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 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());
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"[NavigationPageHandler] Page handler type: {page.Handler?.GetType().Name}");
|
||||
Console.WriteLine($"[NavigationPageHandler] Page PlatformView type: {page.Handler?.PlatformView?.GetType().Name}");
|
||||
|
||||
private void OnPoppedToRoot(object? sender, NavigationEventArgs e)
|
||||
{
|
||||
}
|
||||
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 ?? "";
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"[NavigationPageHandler] SkiaPage content: {skiaPage.Content?.GetType().Name ?? "null"}");
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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 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();
|
||||
}
|
||||
}
|
||||
// Map toolbar items
|
||||
MapToolbarItems(skiaPage, page);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,124 +1,166 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class PageHandler : ViewHandler<Page, SkiaPage>
|
||||
/// <summary>
|
||||
/// Base handler for Page on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class PageHandler : ViewHandler<Page, SkiaPage>
|
||||
{
|
||||
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 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 CommandMapper<Page, PageHandler> CommandMapper = new CommandMapper<Page, PageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<Page, PageHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public PageHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public PageHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public PageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public PageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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)
|
||||
{
|
||||
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 OnAppearing(object? sender, EventArgs e)
|
||||
{
|
||||
Console.WriteLine($"[PageHandler] OnAppearing received for: {VirtualView?.Title}");
|
||||
(VirtualView as IPageController)?.SendAppearing();
|
||||
}
|
||||
|
||||
private void OnDisappearing(object? sender, EventArgs e)
|
||||
{
|
||||
Page virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
((IPageController)virtualView).SendDisappearing();
|
||||
}
|
||||
}
|
||||
private void OnDisappearing(object? sender, EventArgs e)
|
||||
{
|
||||
(VirtualView as IPageController)?.SendDisappearing();
|
||||
}
|
||||
|
||||
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 MapTitle(PageHandler handler, Page page)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Title = page.Title ?? "";
|
||||
}
|
||||
|
||||
public static void MapBackgroundImageSource(PageHandler handler, Page page)
|
||||
{
|
||||
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView?.Invalidate();
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
public static void MapPadding(PageHandler handler, Page page)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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 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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,175 +1,161 @@
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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.Collections.Specialized;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class PickerHandler : ViewHandler<IPicker, SkiaPicker>
|
||||
/// <summary>
|
||||
/// Handler for Picker on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class PickerHandler : ViewHandler<IPicker, SkiaPicker>
|
||||
{
|
||||
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 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 CommandMapper<IPicker, PickerHandler> CommandMapper = new CommandMapper<IPicker, PickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IPicker, PickerHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
private INotifyCollectionChanged? _itemsCollection;
|
||||
private INotifyCollectionChanged? _itemsCollection;
|
||||
|
||||
public PickerHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public PickerHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public PickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public PickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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;
|
||||
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();
|
||||
}
|
||||
protected override void ConnectHandler(SkiaPicker platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
|
||||
|
||||
protected override void DisconnectHandler(SkiaPicker platformView)
|
||||
{
|
||||
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
|
||||
if (_itemsCollection != null)
|
||||
{
|
||||
_itemsCollection.CollectionChanged -= OnItemsCollectionChanged;
|
||||
_itemsCollection = null;
|
||||
}
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
// Subscribe to items collection changes
|
||||
if (VirtualView is Picker picker && picker.Items is INotifyCollectionChanged items)
|
||||
{
|
||||
_itemsCollection = items;
|
||||
_itemsCollection.CollectionChanged += OnItemsCollectionChanged;
|
||||
}
|
||||
|
||||
private void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
ReloadItems();
|
||||
}
|
||||
// Load items
|
||||
ReloadItems();
|
||||
}
|
||||
|
||||
private void OnSelectedIndexChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (base.VirtualView != null && base.PlatformView != null)
|
||||
{
|
||||
base.VirtualView.SelectedIndex = base.PlatformView.SelectedIndex;
|
||||
}
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaPicker platformView)
|
||||
{
|
||||
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
|
||||
|
||||
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() ?? ""));
|
||||
}
|
||||
}
|
||||
if (_itemsCollection != null)
|
||||
{
|
||||
_itemsCollection.CollectionChanged -= OnItemsCollectionChanged;
|
||||
_itemsCollection = null;
|
||||
}
|
||||
|
||||
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 ?? "";
|
||||
}
|
||||
}
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
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 OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
ReloadItems();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private void OnSelectedIndexChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
VirtualView.SelectedIndex = PlatformView.SelectedIndex;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
private void ReloadItems()
|
||||
{
|
||||
if (PlatformView is null || VirtualView is null) return;
|
||||
|
||||
public static void MapCharacterSpacing(PickerHandler handler, IPicker picker)
|
||||
{
|
||||
}
|
||||
var items = VirtualView.GetItemsAsArray();
|
||||
PlatformView.SetItems(items.Select(i => i?.ToString() ?? ""));
|
||||
}
|
||||
|
||||
public static void MapHorizontalTextAlignment(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 MapVerticalTextAlignment(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 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 MapSelectedIndex(PickerHandler handler, IPicker picker)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.SelectedIndex = picker.SelectedIndex;
|
||||
}
|
||||
|
||||
public static void MapItemsSource(PickerHandler handler, IPicker picker)
|
||||
{
|
||||
handler.ReloadItems();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,113 +1,65 @@
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class ProgressBarHandler : ViewHandler<IProgress, SkiaProgressBar>
|
||||
/// <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 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 IPropertyMapper<IProgress, ProgressBarHandler> Mapper = new PropertyMapper<IProgress, ProgressBarHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
[nameof(IProgress.Progress)] = MapProgress,
|
||||
[nameof(IProgress.ProgressColor)] = MapProgressColor,
|
||||
[nameof(IView.Background)] = MapBackground,
|
||||
};
|
||||
|
||||
public static CommandMapper<IProgress, ProgressBarHandler> CommandMapper = new CommandMapper<IProgress, ProgressBarHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IProgress, ProgressBarHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public ProgressBarHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public ProgressBarHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaProgressBar CreatePlatformView()
|
||||
{
|
||||
return new SkiaProgressBar();
|
||||
}
|
||||
public ProgressBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
protected override SkiaProgressBar CreatePlatformView()
|
||||
{
|
||||
return new SkiaProgressBar();
|
||||
}
|
||||
|
||||
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 MapProgress(ProgressBarHandler handler, IProgress progress)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Progress = Math.Clamp(progress.Progress, 0.0, 1.0);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
public static void MapProgressColor(ProgressBarHandler handler, IProgress progress)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
public static void MapProgress(ProgressBarHandler handler, IProgress progress)
|
||||
{
|
||||
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Progress = progress.Progress;
|
||||
}
|
||||
if (progress.ProgressColor is not null)
|
||||
handler.PlatformView.ProgressColor = progress.ProgressColor.ToSKColor();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
public static void MapBackground(ProgressBarHandler handler, IProgress progress)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
if (progress.Background is SolidPaint solidPaint && solidPaint.Color is not null)
|
||||
{
|
||||
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +1,106 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class RadioButtonHandler : ViewHandler<IRadioButton, SkiaRadioButton>
|
||||
/// <summary>
|
||||
/// Handler for RadioButton on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class RadioButtonHandler : ViewHandler<IRadioButton, SkiaRadioButton>
|
||||
{
|
||||
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 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 CommandMapper<IRadioButton, RadioButtonHandler> CommandMapper = new CommandMapper<IRadioButton, RadioButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IRadioButton, RadioButtonHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public RadioButtonHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public RadioButtonHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public RadioButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public RadioButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
protected override void ConnectHandler(SkiaRadioButton platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.CheckedChanged += OnCheckedChanged;
|
||||
|
||||
protected override void DisconnectHandler(SkiaRadioButton platformView)
|
||||
{
|
||||
platformView.CheckedChanged -= OnCheckedChanged;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
// Set content if available
|
||||
if (VirtualView is RadioButton rb)
|
||||
{
|
||||
platformView.Content = rb.Content?.ToString() ?? "";
|
||||
platformView.GroupName = rb.GroupName;
|
||||
platformView.Value = rb.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCheckedChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (base.VirtualView != null && base.PlatformView != null)
|
||||
{
|
||||
base.VirtualView.IsChecked = base.PlatformView.IsChecked;
|
||||
}
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaRadioButton platformView)
|
||||
{
|
||||
platformView.CheckedChanged -= OnCheckedChanged;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private void OnCheckedChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
VirtualView.IsChecked = PlatformView.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 MapIsChecked(RadioButtonHandler handler, IRadioButton radioButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsChecked = radioButton.IsChecked;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapTextColor(RadioButtonHandler handler, IRadioButton radioButton)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,115 +1,109 @@
|
||||
using System;
|
||||
// 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.Platform.Linux.Hosting;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class ScrollViewHandler : ViewHandler<IScrollView, SkiaScrollView>
|
||||
/// <summary>
|
||||
/// Handler for ScrollView on Linux using SkiaScrollView.
|
||||
/// </summary>
|
||||
public partial class ScrollViewHandler : ViewHandler<IScrollView, SkiaScrollView>
|
||||
{
|
||||
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 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 CommandMapper<IScrollView, ScrollViewHandler> CommandMapper = new CommandMapper<IScrollView, ScrollViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["RequestScrollTo"] = MapRequestScrollTo };
|
||||
public static CommandMapper<IScrollView, ScrollViewHandler> CommandMapper =
|
||||
new(ViewCommandMapper)
|
||||
{
|
||||
[nameof(IScrollView.RequestScrollTo)] = MapRequestScrollTo
|
||||
};
|
||||
|
||||
public ScrollViewHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public ScrollViewHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public ScrollViewHandler(IPropertyMapper? mapper)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public ScrollViewHandler(IPropertyMapper? mapper)
|
||||
: base(mapper ?? Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaScrollView CreatePlatformView()
|
||||
{
|
||||
return new SkiaScrollView();
|
||||
}
|
||||
protected override SkiaScrollView CreatePlatformView()
|
||||
{
|
||||
return new SkiaScrollView();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
public static void MapContent(ScrollViewHandler handler, IScrollView scrollView)
|
||||
{
|
||||
if (handler.PlatformView == null || handler.MauiContext == null)
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
var content = scrollView.PresentedContent;
|
||||
if (content != null)
|
||||
{
|
||||
Console.WriteLine($"[ScrollViewHandler] MapContent: {content.GetType().Name}");
|
||||
|
||||
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;
|
||||
}
|
||||
// Create handler for content if it doesn't exist
|
||||
if (content.Handler == null)
|
||||
{
|
||||
content.Handler = content.ToHandler(handler.MauiContext);
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,142 +1,135 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class SearchBarHandler : ViewHandler<ISearchBar, SkiaSearchBar>
|
||||
/// <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 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 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 CommandMapper<ISearchBar, SearchBarHandler> CommandMapper = new CommandMapper<ISearchBar, SearchBarHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<ISearchBar, SearchBarHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public SearchBarHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public SearchBarHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public SearchBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public SearchBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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 (base.VirtualView != null && base.PlatformView != null && ((ITextInput)base.VirtualView).Text != e.NewTextValue)
|
||||
{
|
||||
((ITextInput)base.VirtualView).Text = e.NewTextValue ?? string.Empty;
|
||||
}
|
||||
}
|
||||
private void OnTextChanged(object? sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
|
||||
private void OnSearchButtonPressed(object? sender, EventArgs e)
|
||||
{
|
||||
ISearchBar virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.SearchButtonPressed();
|
||||
}
|
||||
}
|
||||
if (VirtualView.Text != e.NewTextValue)
|
||||
{
|
||||
VirtualView.Text = e.NewTextValue ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private void OnSearchButtonPressed(object? sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.SearchButtonPressed();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
public static void MapText(SearchBarHandler handler, ISearchBar searchBar)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (handler.PlatformView.Text != searchBar.Text)
|
||||
handler.PlatformView.Text = searchBar.Text ?? string.Empty;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
public static void MapTextColor(SearchBarHandler handler, ISearchBar searchBar)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
if (searchBar.TextColor is not null)
|
||||
handler.PlatformView.TextColor = searchBar.TextColor.ToSKColor();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
public static void MapFont(SearchBarHandler handler, ISearchBar searchBar)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,88 +1,93 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
// 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 Microsoft.Maui.Graphics;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class ShellHandler : ViewHandler<Shell, SkiaShell>
|
||||
/// <summary>
|
||||
/// Handler for Shell on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class ShellHandler : ViewHandler<Shell, SkiaShell>
|
||||
{
|
||||
public static IPropertyMapper<Shell, ShellHandler> Mapper = (IPropertyMapper<Shell, ShellHandler>)(object)new PropertyMapper<Shell, ShellHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper });
|
||||
public static IPropertyMapper<Shell, ShellHandler> Mapper = new PropertyMapper<Shell, ShellHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public static CommandMapper<Shell, ShellHandler> CommandMapper = new CommandMapper<Shell, ShellHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<Shell, ShellHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public ShellHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public ShellHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public ShellHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public ShellHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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;
|
||||
if (base.VirtualView != null)
|
||||
{
|
||||
base.VirtualView.Navigating += OnShellNavigating;
|
||||
base.VirtualView.Navigated += OnShellNavigated;
|
||||
}
|
||||
}
|
||||
protected override void ConnectHandler(SkiaShell platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.FlyoutIsPresentedChanged += OnFlyoutIsPresentedChanged;
|
||||
platformView.Navigated += OnNavigated;
|
||||
|
||||
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);
|
||||
}
|
||||
// Subscribe to Shell navigation events
|
||||
if (VirtualView != null)
|
||||
{
|
||||
VirtualView.Navigating += OnShellNavigating;
|
||||
VirtualView.Navigated += OnShellNavigated;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFlyoutIsPresentedChanged(object? sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaShell platformView)
|
||||
{
|
||||
platformView.FlyoutIsPresentedChanged -= OnFlyoutIsPresentedChanged;
|
||||
platformView.Navigated -= OnNavigated;
|
||||
|
||||
private void OnNavigated(object? sender, ShellNavigationEventArgs e)
|
||||
{
|
||||
}
|
||||
if (VirtualView != null)
|
||||
{
|
||||
VirtualView.Navigating -= OnShellNavigating;
|
||||
VirtualView.Navigated -= OnShellNavigated;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,160 +1,153 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class SliderHandler : ViewHandler<ISlider, SkiaSlider>
|
||||
/// <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 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 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 CommandMapper<ISlider, SliderHandler> CommandMapper = new CommandMapper<ISlider, SliderHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<ISlider, SliderHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public SliderHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public SliderHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public SliderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public SliderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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;
|
||||
if (base.VirtualView != null)
|
||||
{
|
||||
MapMinimum(this, base.VirtualView);
|
||||
MapMaximum(this, base.VirtualView);
|
||||
MapValue(this, base.VirtualView);
|
||||
MapIsEnabled(this, base.VirtualView);
|
||||
}
|
||||
}
|
||||
protected override void ConnectHandler(SkiaSlider platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.ValueChanged += OnValueChanged;
|
||||
platformView.DragStarted += OnDragStarted;
|
||||
platformView.DragCompleted += OnDragCompleted;
|
||||
|
||||
protected override void DisconnectHandler(SkiaSlider platformView)
|
||||
{
|
||||
platformView.ValueChanged -= OnValueChanged;
|
||||
platformView.DragStarted -= OnDragStarted;
|
||||
platformView.DragCompleted -= OnDragCompleted;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaSlider platformView)
|
||||
{
|
||||
platformView.ValueChanged -= OnValueChanged;
|
||||
platformView.DragStarted -= OnDragStarted;
|
||||
platformView.DragCompleted -= OnDragCompleted;
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
private void OnDragStarted(object? sender, EventArgs e)
|
||||
{
|
||||
ISlider virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.DragStarted();
|
||||
}
|
||||
}
|
||||
private void OnValueChanged(object? sender, SliderValueChangedEventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
|
||||
private void OnDragCompleted(object? sender, EventArgs e)
|
||||
{
|
||||
ISlider virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.DragCompleted();
|
||||
}
|
||||
}
|
||||
if (Math.Abs(VirtualView.Value - e.NewValue) > 0.0001)
|
||||
{
|
||||
VirtualView.Value = e.NewValue;
|
||||
}
|
||||
}
|
||||
|
||||
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 OnDragStarted(object? sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.DragStarted();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private void OnDragCompleted(object? sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.DragCompleted();
|
||||
}
|
||||
|
||||
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 MapMinimum(SliderHandler handler, ISlider slider)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Minimum = slider.Minimum;
|
||||
}
|
||||
|
||||
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 MapMaximum(SliderHandler handler, ISlider slider)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Maximum = slider.Maximum;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
public static void MapValue(SliderHandler handler, ISlider slider)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
if (Math.Abs(handler.PlatformView.Value - slider.Value) > 0.0001)
|
||||
handler.PlatformView.Value = slider.Value;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapMinimumTrackColor(SliderHandler handler, ISlider slider)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,133 +1,89 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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.Platform;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class StepperHandler : ViewHandler<IStepper, SkiaStepper>
|
||||
/// <summary>
|
||||
/// Handler for Stepper on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class StepperHandler : ViewHandler<IStepper, SkiaStepper>
|
||||
{
|
||||
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 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 CommandMapper<IStepper, StepperHandler> CommandMapper = new CommandMapper<IStepper, StepperHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<IStepper, StepperHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public StepperHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public StepperHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public StepperHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public StepperHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaStepper CreatePlatformView()
|
||||
{
|
||||
return new SkiaStepper();
|
||||
}
|
||||
protected override SkiaStepper CreatePlatformView()
|
||||
{
|
||||
return new SkiaStepper();
|
||||
}
|
||||
|
||||
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 ConnectHandler(SkiaStepper platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.ValueChanged += OnValueChanged;
|
||||
}
|
||||
|
||||
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 (base.VirtualView != null && base.PlatformView != null)
|
||||
{
|
||||
((IRange)base.VirtualView).Value = base.PlatformView.Value;
|
||||
}
|
||||
}
|
||||
private void OnValueChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
VirtualView.Value = PlatformView.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 MapValue(StepperHandler handler, IStepper stepper)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Value = stepper.Value;
|
||||
}
|
||||
|
||||
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 MapMinimum(StepperHandler handler, IStepper stepper)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Minimum = stepper.Minimum;
|
||||
}
|
||||
|
||||
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 MapMaximum(StepperHandler handler, IStepper stepper)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Maximum = stepper.Maximum;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapBackground(StepperHandler handler, IStepper stepper)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (stepper.Background is SolidPaint solidPaint && solidPaint.Color is not null)
|
||||
{
|
||||
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,107 +1,99 @@
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class SwitchHandler : ViewHandler<ISwitch, SkiaSwitch>
|
||||
/// <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 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 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 CommandMapper<ISwitch, SwitchHandler> CommandMapper = new CommandMapper<ISwitch, SwitchHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<ISwitch, SwitchHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public SwitchHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public SwitchHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public SwitchHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public SwitchHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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, ToggledEventArgs e)
|
||||
{
|
||||
if (base.VirtualView != null && base.VirtualView.IsOn != e.Value)
|
||||
{
|
||||
base.VirtualView.IsOn = e.Value;
|
||||
}
|
||||
}
|
||||
private void OnToggled(object? sender, Platform.ToggledEventArgs e)
|
||||
{
|
||||
if (VirtualView is not null && VirtualView.IsOn != e.Value)
|
||||
{
|
||||
VirtualView.IsOn = e.Value;
|
||||
}
|
||||
}
|
||||
|
||||
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 MapIsOn(SwitchHandler handler, ISwitch @switch)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.IsOn = @switch.IsOn;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
public static void MapTrackColor(SwitchHandler handler, ISwitch @switch)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
// 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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapThumbColor(SwitchHandler handler, ISwitch @switch)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,55 @@
|
||||
using System;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class TabbedPageHandler : ViewHandler<ITabbedView, SkiaTabbedPage>
|
||||
/// <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 static IPropertyMapper<ITabbedView, TabbedPageHandler> Mapper = (IPropertyMapper<ITabbedView, TabbedPageHandler>)(object)new PropertyMapper<ITabbedView, TabbedPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper });
|
||||
public static IPropertyMapper<ITabbedView, TabbedPageHandler> Mapper = new PropertyMapper<ITabbedView, TabbedPageHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public static CommandMapper<ITabbedView, TabbedPageHandler> CommandMapper = new CommandMapper<ITabbedView, TabbedPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<ITabbedView, TabbedPageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public TabbedPageHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public TabbedPageHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public TabbedPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public TabbedPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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)
|
||||
{
|
||||
}
|
||||
private void OnSelectedIndexChanged(object? sender, EventArgs e)
|
||||
{
|
||||
// Notify the virtual view of selection change
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +1,100 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class TimePickerHandler : ViewHandler<ITimePicker, SkiaTimePicker>
|
||||
/// <summary>
|
||||
/// Handler for TimePicker on Linux using Skia rendering.
|
||||
/// </summary>
|
||||
public partial class TimePickerHandler : ViewHandler<ITimePicker, SkiaTimePicker>
|
||||
{
|
||||
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 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 CommandMapper<ITimePicker, TimePickerHandler> CommandMapper = new CommandMapper<ITimePicker, TimePickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
|
||||
public static CommandMapper<ITimePicker, TimePickerHandler> CommandMapper =
|
||||
new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public TimePickerHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public TimePickerHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public TimePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public TimePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaTimePicker CreatePlatformView()
|
||||
{
|
||||
return new SkiaTimePicker();
|
||||
}
|
||||
protected override SkiaTimePicker CreatePlatformView()
|
||||
{
|
||||
return new SkiaTimePicker();
|
||||
}
|
||||
|
||||
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 ConnectHandler(SkiaTimePicker platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.TimeSelected += OnTimeSelected;
|
||||
}
|
||||
|
||||
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 (base.VirtualView != null && base.PlatformView != null)
|
||||
{
|
||||
base.VirtualView.Time = base.PlatformView.Time;
|
||||
}
|
||||
}
|
||||
private void OnTimeSelected(object? sender, EventArgs e)
|
||||
{
|
||||
if (VirtualView is null || PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
VirtualView.Time = PlatformView.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 MapTime(TimePickerHandler handler, ITimePicker timePicker)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Time = timePicker.Time;
|
||||
}
|
||||
|
||||
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 MapFormat(TimePickerHandler handler, ITimePicker timePicker)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Format = timePicker.Format ?? "t";
|
||||
}
|
||||
|
||||
public static void MapCharacterSpacing(TimePickerHandler handler, ITimePicker timePicker)
|
||||
{
|
||||
}
|
||||
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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Linux handler for WebView control using WebKitGTK.
|
||||
/// </summary>
|
||||
public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
|
||||
{
|
||||
/// <summary>
|
||||
/// Property mapper for WebView properties.
|
||||
/// </summary>
|
||||
public static IPropertyMapper<IWebView, WebViewHandler> Mapper = new PropertyMapper<IWebView, WebViewHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
[nameof(IWebView.Source)] = MapSource,
|
||||
[nameof(IWebView.UserAgent)] = MapUserAgent,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Command mapper for WebView commands.
|
||||
/// </summary>
|
||||
public static CommandMapper<IWebView, WebViewHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
[nameof(IWebView.GoBack)] = MapGoBack,
|
||||
[nameof(IWebView.GoForward)] = MapGoForward,
|
||||
[nameof(IWebView.Reload)] = MapReload,
|
||||
[nameof(IWebView.Eval)] = MapEval,
|
||||
[nameof(IWebView.EvaluateJavaScriptAsync)] = MapEvaluateJavaScriptAsync,
|
||||
};
|
||||
|
||||
public WebViewHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public WebViewHandler(IPropertyMapper? mapper)
|
||||
: base(mapper ?? Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public WebViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override LinuxWebView CreatePlatformView()
|
||||
{
|
||||
Console.WriteLine("[WebViewHandler] Creating LinuxWebView");
|
||||
return new LinuxWebView();
|
||||
}
|
||||
|
||||
protected override void ConnectHandler(LinuxWebView platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
|
||||
platformView.Navigating += OnNavigating;
|
||||
platformView.Navigated += OnNavigated;
|
||||
|
||||
// Map initial properties
|
||||
if (VirtualView != null)
|
||||
{
|
||||
MapSource(this, VirtualView);
|
||||
MapUserAgent(this, VirtualView);
|
||||
}
|
||||
|
||||
Console.WriteLine("[WebViewHandler] Handler connected");
|
||||
}
|
||||
|
||||
protected override void DisconnectHandler(LinuxWebView platformView)
|
||||
{
|
||||
platformView.Navigating -= OnNavigating;
|
||||
platformView.Navigated -= OnNavigated;
|
||||
|
||||
base.DisconnectHandler(platformView);
|
||||
Console.WriteLine("[WebViewHandler] Handler disconnected");
|
||||
}
|
||||
|
||||
private void OnNavigating(object? sender, WebViewNavigatingEventArgs e)
|
||||
{
|
||||
if (VirtualView == null)
|
||||
return;
|
||||
|
||||
// Notify the virtual view about navigation starting
|
||||
VirtualView.Navigating(WebNavigationEvent.NewPage, e.Url);
|
||||
}
|
||||
|
||||
private void OnNavigated(object? sender, WebViewNavigatedEventArgs e)
|
||||
{
|
||||
if (VirtualView == null)
|
||||
return;
|
||||
|
||||
// Notify the virtual view about navigation completed
|
||||
var result = e.Success ? WebNavigationResult.Success : WebNavigationResult.Failure;
|
||||
VirtualView.Navigated(WebNavigationEvent.NewPage, e.Url, result);
|
||||
}
|
||||
|
||||
#region Property Mappers
|
||||
|
||||
public static void MapSource(WebViewHandler handler, IWebView webView)
|
||||
{
|
||||
var source = webView.Source;
|
||||
if (source == null)
|
||||
return;
|
||||
|
||||
Console.WriteLine($"[WebViewHandler] MapSource: {source.GetType().Name}");
|
||||
|
||||
if (source is IUrlWebViewSource urlSource && !string.IsNullOrEmpty(urlSource.Url))
|
||||
{
|
||||
handler.PlatformView?.LoadUrl(urlSource.Url);
|
||||
}
|
||||
else if (source is IHtmlWebViewSource htmlSource && !string.IsNullOrEmpty(htmlSource.Html))
|
||||
{
|
||||
handler.PlatformView?.LoadHtml(htmlSource.Html, htmlSource.BaseUrl);
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapUserAgent(WebViewHandler handler, IWebView webView)
|
||||
{
|
||||
if (handler.PlatformView != null && !string.IsNullOrEmpty(webView.UserAgent))
|
||||
{
|
||||
handler.PlatformView.UserAgent = webView.UserAgent;
|
||||
Console.WriteLine($"[WebViewHandler] MapUserAgent: {webView.UserAgent}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Command Mappers
|
||||
|
||||
public static void MapGoBack(WebViewHandler handler, IWebView webView, object? args)
|
||||
{
|
||||
if (handler.PlatformView?.CanGoBack == true)
|
||||
{
|
||||
handler.PlatformView.GoBack();
|
||||
Console.WriteLine("[WebViewHandler] GoBack");
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapGoForward(WebViewHandler handler, IWebView webView, object? args)
|
||||
{
|
||||
if (handler.PlatformView?.CanGoForward == true)
|
||||
{
|
||||
handler.PlatformView.GoForward();
|
||||
Console.WriteLine("[WebViewHandler] GoForward");
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
|
||||
{
|
||||
handler.PlatformView?.Reload();
|
||||
Console.WriteLine("[WebViewHandler] Reload");
|
||||
}
|
||||
|
||||
public static void MapEval(WebViewHandler handler, IWebView webView, object? args)
|
||||
{
|
||||
if (args is string script)
|
||||
{
|
||||
handler.PlatformView?.Eval(script);
|
||||
Console.WriteLine($"[WebViewHandler] Eval: {script.Substring(0, Math.Min(50, script.Length))}...");
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapEvaluateJavaScriptAsync(WebViewHandler handler, IWebView webView, object? args)
|
||||
{
|
||||
if (args is EvaluateJavaScriptAsyncRequest request)
|
||||
{
|
||||
var result = handler.PlatformView?.EvaluateJavaScriptAsync(request.Script);
|
||||
if (result != null)
|
||||
{
|
||||
result.ContinueWith(t =>
|
||||
{
|
||||
request.SetResult(t.Result);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
request.SetResult(null);
|
||||
}
|
||||
Console.WriteLine($"[WebViewHandler] EvaluateJavaScriptAsync: {request.Script.Substring(0, Math.Min(50, request.Script.Length))}...");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request object for async JavaScript evaluation.
|
||||
/// </summary>
|
||||
public class EvaluateJavaScriptAsyncRequest
|
||||
{
|
||||
public string Script { get; }
|
||||
private readonly TaskCompletionSource<string?> _tcs = new();
|
||||
|
||||
public EvaluateJavaScriptAsyncRequest(string script)
|
||||
{
|
||||
Script = script;
|
||||
}
|
||||
|
||||
public Task<string?> Task => _tcs.Task;
|
||||
|
||||
public void SetResult(string? result)
|
||||
{
|
||||
_tcs.TrySetResult(result);
|
||||
}
|
||||
}
|
||||
@@ -1,120 +1,96 @@
|
||||
using System;
|
||||
// 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 Microsoft.Maui.Platform;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class WebViewHandler : ViewHandler<IWebView, SkiaWebView>
|
||||
/// <summary>
|
||||
/// Handler for WebView control on Linux using WebKitGTK.
|
||||
/// </summary>
|
||||
public partial class WebViewHandler : ViewHandler<IWebView, SkiaWebView>
|
||||
{
|
||||
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 IPropertyMapper<IWebView, WebViewHandler> Mapper = new PropertyMapper<IWebView, WebViewHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
[nameof(IWebView.Source)] = MapSource,
|
||||
};
|
||||
|
||||
public static CommandMapper<IWebView, WebViewHandler> CommandMapper = new CommandMapper<IWebView, WebViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
["GoBack"] = MapGoBack,
|
||||
["GoForward"] = MapGoForward,
|
||||
["Reload"] = MapReload
|
||||
};
|
||||
public static CommandMapper<IWebView, WebViewHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||
{
|
||||
[nameof(IWebView.GoBack)] = MapGoBack,
|
||||
[nameof(IWebView.GoForward)] = MapGoForward,
|
||||
[nameof(IWebView.Reload)] = MapReload,
|
||||
};
|
||||
|
||||
public WebViewHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public WebViewHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public WebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public WebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override SkiaWebView CreatePlatformView()
|
||||
{
|
||||
return new SkiaWebView();
|
||||
}
|
||||
protected override SkiaWebView CreatePlatformView()
|
||||
{
|
||||
return new SkiaWebView();
|
||||
}
|
||||
|
||||
protected override void ConnectHandler(SkiaWebView platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
platformView.Navigating += OnNavigating;
|
||||
platformView.Navigated += OnNavigated;
|
||||
}
|
||||
protected override void ConnectHandler(SkiaWebView platformView)
|
||||
{
|
||||
base.ConnectHandler(platformView);
|
||||
|
||||
protected override void DisconnectHandler(SkiaWebView platformView)
|
||||
{
|
||||
platformView.Navigating -= OnNavigating;
|
||||
platformView.Navigated -= OnNavigated;
|
||||
base.DisconnectHandler(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);
|
||||
}
|
||||
}
|
||||
protected override void DisconnectHandler(SkiaWebView platformView)
|
||||
{
|
||||
platformView.Navigating -= OnNavigating;
|
||||
platformView.Navigated -= OnNavigated;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
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 OnNavigating(object? sender, WebNavigatingEventArgs e)
|
||||
{
|
||||
// Forward to virtual view if needed
|
||||
}
|
||||
|
||||
public static void MapGoBack(WebViewHandler handler, IWebView webView, object? args)
|
||||
{
|
||||
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.GoBack();
|
||||
}
|
||||
private void OnNavigated(object? sender, WebNavigatedEventArgs e)
|
||||
{
|
||||
// Forward to virtual view if needed
|
||||
}
|
||||
|
||||
public static void MapGoForward(WebViewHandler handler, IWebView webView, object? args)
|
||||
{
|
||||
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.GoForward();
|
||||
}
|
||||
public static void MapSource(WebViewHandler handler, IWebView webView)
|
||||
{
|
||||
if (handler.PlatformView == null) return;
|
||||
|
||||
public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
|
||||
{
|
||||
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.Reload();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,166 +1,281 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Graphics;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
public class WindowHandler : ElementHandler<IWindow, SkiaWindow>
|
||||
/// <summary>
|
||||
/// Handler for Window on Linux.
|
||||
/// Maps IWindow to the Linux display window system.
|
||||
/// </summary>
|
||||
public partial class WindowHandler : ElementHandler<IWindow, SkiaWindow>
|
||||
{
|
||||
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 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 CommandMapper<IWindow, WindowHandler> CommandMapper = new CommandMapper<IWindow, WindowHandler>((CommandMapper)(object)ElementHandler.ElementCommandMapper);
|
||||
public static CommandMapper<IWindow, WindowHandler> CommandMapper =
|
||||
new(ElementHandler.ElementCommandMapper)
|
||||
{
|
||||
};
|
||||
|
||||
public WindowHandler()
|
||||
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
|
||||
{
|
||||
}
|
||||
public WindowHandler() : base(Mapper, CommandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
public WindowHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
|
||||
{
|
||||
}
|
||||
public WindowHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
|
||||
: base(mapper ?? Mapper, commandMapper ?? 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)
|
||||
{
|
||||
IWindow virtualView = base.VirtualView;
|
||||
if (virtualView != null)
|
||||
{
|
||||
virtualView.Destroying();
|
||||
}
|
||||
}
|
||||
private void OnCloseRequested(object? sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.Destroying();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
|
||||
{
|
||||
VirtualView?.FrameChanged(new Rect(0, 0, e.Width, e.Height));
|
||||
}
|
||||
|
||||
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 MapTitle(WindowHandler handler, IWindow window)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Title = window.Title ?? "MAUI Application";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void MapContent(WindowHandler handler, IWindow window)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
var content = window.Content;
|
||||
if (content?.Handler?.PlatformView is SkiaView skiaContent)
|
||||
{
|
||||
handler.PlatformView.Content = skiaContent;
|
||||
}
|
||||
}
|
||||
|
||||
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 MapX(WindowHandler handler, IWindow window)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.X = (int)window.X;
|
||||
}
|
||||
|
||||
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 MapY(WindowHandler handler, IWindow window)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Y = (int)window.Y;
|
||||
}
|
||||
|
||||
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 MapWidth(WindowHandler handler, IWindow window)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Width = (int)window.Width;
|
||||
}
|
||||
|
||||
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 MapHeight(WindowHandler handler, IWindow window)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.Height = (int)window.Height;
|
||||
}
|
||||
|
||||
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 MapMinimumWidth(WindowHandler handler, IWindow window)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.MinWidth = (int)window.MinimumWidth;
|
||||
}
|
||||
|
||||
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 MapMinimumHeight(WindowHandler handler, IWindow window)
|
||||
{
|
||||
if (handler.PlatformView is null) return;
|
||||
handler.PlatformView.MinHeight = (int)window.MinimumHeight;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Maui.Animations;
|
||||
using Microsoft.Maui.Dispatching;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
public class GtkMauiContext : IMauiContext
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
private readonly IMauiHandlersFactory _handlers;
|
||||
|
||||
private IAnimationManager? _animationManager;
|
||||
|
||||
private IDispatcher? _dispatcher;
|
||||
|
||||
public IServiceProvider Services => _services;
|
||||
|
||||
public IMauiHandlersFactory Handlers => _handlers;
|
||||
|
||||
public IAnimationManager AnimationManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_animationManager == null)
|
||||
{
|
||||
_animationManager = (IAnimationManager?)(((object)_services.GetService<IAnimationManager>()) ?? ((object)new LinuxAnimationManager((ITicker)(object)new LinuxTicker())));
|
||||
}
|
||||
return _animationManager;
|
||||
}
|
||||
}
|
||||
|
||||
public IDispatcher Dispatcher
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dispatcher == null)
|
||||
{
|
||||
_dispatcher = (IDispatcher?)(((object)_services.GetService<IDispatcher>()) ?? ((object)new LinuxDispatcher()));
|
||||
}
|
||||
return _dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
public GtkMauiContext(IServiceProvider services)
|
||||
{
|
||||
_services = services ?? throw new ArgumentNullException("services");
|
||||
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
|
||||
if (LinuxApplication.Current == null)
|
||||
{
|
||||
new LinuxApplication();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using Microsoft.Maui.Hosting;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
public static class HandlerMappingExtensions
|
||||
{
|
||||
public static IMauiHandlersCollection AddHandler<TView, THandler>(this IMauiHandlersCollection handlers) where TView : class where THandler : class
|
||||
{
|
||||
MauiHandlersCollectionExtensions.AddHandler(handlers, typeof(TView), typeof(THandler));
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Maui.Animations;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
internal class LinuxAnimationManager : IAnimationManager
|
||||
{
|
||||
private readonly List<Animation> _animations = new List<Animation>();
|
||||
|
||||
private readonly ITicker _ticker;
|
||||
|
||||
public double SpeedModifier { get; set; } = 1.0;
|
||||
|
||||
public bool AutoStartTicker { get; set; } = true;
|
||||
|
||||
public ITicker Ticker => _ticker;
|
||||
|
||||
public LinuxAnimationManager(ITicker ticker)
|
||||
{
|
||||
_ticker = ticker;
|
||||
_ticker.Fire = OnTickerFire;
|
||||
}
|
||||
|
||||
public void Add(Animation animation)
|
||||
{
|
||||
_animations.Add(animation);
|
||||
if (AutoStartTicker && !_ticker.IsRunning)
|
||||
{
|
||||
_ticker.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(Animation animation)
|
||||
{
|
||||
_animations.Remove(animation);
|
||||
if (_animations.Count == 0 && _ticker.IsRunning)
|
||||
{
|
||||
_ticker.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTickerFire()
|
||||
{
|
||||
Animation[] array = _animations.ToArray();
|
||||
foreach (Animation val in array)
|
||||
{
|
||||
val.Tick(0.016 * SpeedModifier);
|
||||
if (val.HasFinished)
|
||||
{
|
||||
Remove(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Maui.Dispatching;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
internal class LinuxDispatcher : IDispatcher
|
||||
{
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private readonly Queue<Action> _queue = new Queue<Action>();
|
||||
|
||||
private bool _isDispatching;
|
||||
|
||||
public bool IsDispatchRequired => false;
|
||||
|
||||
public IDispatcherTimer CreateTimer()
|
||||
{
|
||||
return (IDispatcherTimer)(object)new LinuxDispatcherTimer();
|
||||
}
|
||||
|
||||
public bool Dispatch(Action action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
_queue.Enqueue(action);
|
||||
}
|
||||
ProcessQueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DispatchDelayed(TimeSpan delay, Action action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Task.Delay(delay).ContinueWith((Task _) => Dispatch(action));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ProcessQueue()
|
||||
{
|
||||
if (_isDispatching)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isDispatching = true;
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Action action;
|
||||
lock (_lock)
|
||||
{
|
||||
if (_queue.Count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
action = _queue.Dequeue();
|
||||
}
|
||||
action?.Invoke();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isDispatching = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.Maui.Dispatching;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
internal class LinuxDispatcherTimer : IDispatcherTimer
|
||||
{
|
||||
private Timer? _timer;
|
||||
|
||||
private TimeSpan _interval = TimeSpan.FromMilliseconds(16L, 0L);
|
||||
|
||||
private bool _isRunning;
|
||||
|
||||
private bool _isRepeating = true;
|
||||
|
||||
public TimeSpan Interval
|
||||
{
|
||||
get
|
||||
{
|
||||
return _interval;
|
||||
}
|
||||
set
|
||||
{
|
||||
_interval = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRunning => _isRunning;
|
||||
|
||||
public bool IsRepeating
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isRepeating;
|
||||
}
|
||||
set
|
||||
{
|
||||
_isRepeating = value;
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler? Tick;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
_isRunning = true;
|
||||
_timer = new Timer(OnTimerCallback, null, _interval, _isRepeating ? _interval : Timeout.InfiniteTimeSpan);
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_isRunning = false;
|
||||
_timer?.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
private void OnTimerCallback(object? state)
|
||||
{
|
||||
this.Tick?.Invoke(this, EventArgs.Empty);
|
||||
if (!_isRepeating)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,105 +1,153 @@
|
||||
using System;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Maui.ApplicationModel;
|
||||
using Microsoft.Maui.ApplicationModel.Communication;
|
||||
using Microsoft.Maui.ApplicationModel.DataTransfer;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Devices;
|
||||
using Microsoft.Maui.Dispatching;
|
||||
using Microsoft.Maui.Hosting;
|
||||
using Microsoft.Maui.Networking;
|
||||
using Microsoft.Maui.Platform.Linux.Converters;
|
||||
using Microsoft.Maui.Platform.Linux.Dispatching;
|
||||
using Microsoft.Maui.Platform.Linux.Handlers;
|
||||
using Microsoft.Maui.Platform.Linux.Services;
|
||||
using Microsoft.Maui.Platform.Linux.Converters;
|
||||
using Microsoft.Maui.Storage;
|
||||
using Microsoft.Maui.Platform.Linux.Handlers;
|
||||
using Microsoft.Maui.Controls;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for configuring MAUI applications for Linux.
|
||||
/// </summary>
|
||||
public static class LinuxMauiAppBuilderExtensions
|
||||
{
|
||||
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder)
|
||||
{
|
||||
return builder.UseLinux(null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Configures the MAUI application to run on Linux.
|
||||
/// </summary>
|
||||
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder)
|
||||
{
|
||||
return builder.UseLinux(configure: null);
|
||||
}
|
||||
|
||||
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder, Action<LinuxApplicationOptions>? configure)
|
||||
{
|
||||
LinuxApplicationOptions linuxApplicationOptions = new LinuxApplicationOptions();
|
||||
configure?.Invoke(linuxApplicationOptions);
|
||||
builder.Services.TryAddSingleton<IDispatcherProvider>((IDispatcherProvider)(object)LinuxDispatcherProvider.Instance);
|
||||
builder.Services.TryAddSingleton<IDeviceInfo>((IDeviceInfo)(object)DeviceInfoService.Instance);
|
||||
builder.Services.TryAddSingleton<IDeviceDisplay>((IDeviceDisplay)(object)DeviceDisplayService.Instance);
|
||||
builder.Services.TryAddSingleton<IAppInfo>((IAppInfo)(object)AppInfoService.Instance);
|
||||
builder.Services.TryAddSingleton<IConnectivity>((IConnectivity)(object)ConnectivityService.Instance);
|
||||
builder.Services.TryAddSingleton<ILauncher, LauncherService>();
|
||||
builder.Services.TryAddSingleton<IPreferences, PreferencesService>();
|
||||
builder.Services.TryAddSingleton<IFilePicker, FilePickerService>();
|
||||
builder.Services.TryAddSingleton<IClipboard, ClipboardService>();
|
||||
builder.Services.TryAddSingleton<IShare, ShareService>();
|
||||
builder.Services.TryAddSingleton<ISecureStorage, SecureStorageService>();
|
||||
builder.Services.TryAddSingleton<IVersionTracking, VersionTrackingService>();
|
||||
builder.Services.TryAddSingleton<IAppActions, AppActionsService>();
|
||||
builder.Services.TryAddSingleton<IBrowser, BrowserService>();
|
||||
builder.Services.TryAddSingleton<IEmail, EmailService>();
|
||||
builder.Services.TryAddSingleton((IServiceProvider _) => GtkHostService.Instance);
|
||||
RegisterTypeConverters();
|
||||
HandlerMauiAppBuilderExtensions.ConfigureMauiHandlers(builder, (Action<IMauiHandlersCollection>)delegate(IMauiHandlersCollection handlers)
|
||||
{
|
||||
handlers.AddHandler<IApplication, ApplicationHandler>();
|
||||
handlers.AddHandler<BoxView, BoxViewHandler>();
|
||||
handlers.AddHandler<Button, TextButtonHandler>();
|
||||
handlers.AddHandler<Label, LabelHandler>();
|
||||
handlers.AddHandler<Entry, EntryHandler>();
|
||||
handlers.AddHandler<Editor, EditorHandler>();
|
||||
handlers.AddHandler<CheckBox, CheckBoxHandler>();
|
||||
handlers.AddHandler<Switch, SwitchHandler>();
|
||||
handlers.AddHandler<Slider, SliderHandler>();
|
||||
handlers.AddHandler<Stepper, StepperHandler>();
|
||||
handlers.AddHandler<RadioButton, RadioButtonHandler>();
|
||||
handlers.AddHandler<Grid, GridHandler>();
|
||||
handlers.AddHandler<StackLayout, StackLayoutHandler>();
|
||||
handlers.AddHandler<VerticalStackLayout, StackLayoutHandler>();
|
||||
handlers.AddHandler<HorizontalStackLayout, StackLayoutHandler>();
|
||||
handlers.AddHandler<AbsoluteLayout, LayoutHandler>();
|
||||
handlers.AddHandler<FlexLayout, LayoutHandler>();
|
||||
handlers.AddHandler<ScrollView, ScrollViewHandler>();
|
||||
handlers.AddHandler<Frame, FrameHandler>();
|
||||
handlers.AddHandler<Border, BorderHandler>();
|
||||
handlers.AddHandler<ContentView, BorderHandler>();
|
||||
handlers.AddHandler<Picker, PickerHandler>();
|
||||
handlers.AddHandler<DatePicker, DatePickerHandler>();
|
||||
handlers.AddHandler<TimePicker, TimePickerHandler>();
|
||||
handlers.AddHandler<SearchBar, SearchBarHandler>();
|
||||
handlers.AddHandler<ProgressBar, ProgressBarHandler>();
|
||||
handlers.AddHandler<ActivityIndicator, ActivityIndicatorHandler>();
|
||||
handlers.AddHandler<Image, ImageHandler>();
|
||||
handlers.AddHandler<ImageButton, ImageButtonHandler>();
|
||||
handlers.AddHandler<GraphicsView, GraphicsViewHandler>();
|
||||
handlers.AddHandler<WebView, GtkWebViewHandler>();
|
||||
handlers.AddHandler<CollectionView, CollectionViewHandler>();
|
||||
handlers.AddHandler<ListView, CollectionViewHandler>();
|
||||
handlers.AddHandler<Page, PageHandler>();
|
||||
handlers.AddHandler<ContentPage, ContentPageHandler>();
|
||||
handlers.AddHandler<NavigationPage, NavigationPageHandler>();
|
||||
handlers.AddHandler<Shell, ShellHandler>();
|
||||
handlers.AddHandler<FlyoutPage, FlyoutPageHandler>();
|
||||
handlers.AddHandler<TabbedPage, TabbedPageHandler>();
|
||||
handlers.AddHandler<Application, ApplicationHandler>();
|
||||
handlers.AddHandler<Window, WindowHandler>();
|
||||
});
|
||||
builder.Services.AddSingleton(linuxApplicationOptions);
|
||||
return builder;
|
||||
}
|
||||
/// <summary>
|
||||
/// Configures the MAUI application to run on Linux with options.
|
||||
/// </summary>
|
||||
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder, Action<LinuxApplicationOptions>? configure)
|
||||
{
|
||||
var options = new LinuxApplicationOptions();
|
||||
configure?.Invoke(options);
|
||||
|
||||
private static void RegisterTypeConverters()
|
||||
{
|
||||
TypeDescriptor.AddAttributes(typeof(SKColor), new TypeConverterAttribute(typeof(SKColorTypeConverter)));
|
||||
TypeDescriptor.AddAttributes(typeof(SKRect), new TypeConverterAttribute(typeof(SKRectTypeConverter)));
|
||||
TypeDescriptor.AddAttributes(typeof(SKSize), new TypeConverterAttribute(typeof(SKSizeTypeConverter)));
|
||||
TypeDescriptor.AddAttributes(typeof(SKPoint), new TypeConverterAttribute(typeof(SKPointTypeConverter)));
|
||||
}
|
||||
// Register platform services
|
||||
builder.Services.TryAddSingleton<ILauncher, LauncherService>();
|
||||
builder.Services.TryAddSingleton<IPreferences, PreferencesService>();
|
||||
builder.Services.TryAddSingleton<IFilePicker, FilePickerService>();
|
||||
builder.Services.TryAddSingleton<IClipboard, ClipboardService>();
|
||||
builder.Services.TryAddSingleton<IShare, ShareService>();
|
||||
builder.Services.TryAddSingleton<ISecureStorage, SecureStorageService>();
|
||||
builder.Services.TryAddSingleton<IVersionTracking, VersionTrackingService>();
|
||||
builder.Services.TryAddSingleton<IAppActions, AppActionsService>();
|
||||
builder.Services.TryAddSingleton<IBrowser, BrowserService>();
|
||||
builder.Services.TryAddSingleton<IEmail, EmailService>();
|
||||
|
||||
// Register type converters for XAML support
|
||||
RegisterTypeConverters();
|
||||
|
||||
// Register Linux-specific handlers
|
||||
builder.ConfigureMauiHandlers(handlers =>
|
||||
{
|
||||
// Application handler
|
||||
handlers.AddHandler<IApplication, ApplicationHandler>();
|
||||
|
||||
// Core controls
|
||||
handlers.AddHandler<BoxView, BoxViewHandler>();
|
||||
handlers.AddHandler<Button, TextButtonHandler>();
|
||||
handlers.AddHandler<Label, LabelHandler>();
|
||||
handlers.AddHandler<Entry, EntryHandler>();
|
||||
handlers.AddHandler<Editor, EditorHandler>();
|
||||
handlers.AddHandler<CheckBox, CheckBoxHandler>();
|
||||
handlers.AddHandler<Switch, SwitchHandler>();
|
||||
handlers.AddHandler<Slider, SliderHandler>();
|
||||
handlers.AddHandler<Stepper, StepperHandler>();
|
||||
handlers.AddHandler<RadioButton, RadioButtonHandler>();
|
||||
|
||||
// Layout controls
|
||||
handlers.AddHandler<Grid, GridHandler>();
|
||||
handlers.AddHandler<StackLayout, StackLayoutHandler>();
|
||||
handlers.AddHandler<VerticalStackLayout, StackLayoutHandler>();
|
||||
handlers.AddHandler<HorizontalStackLayout, StackLayoutHandler>();
|
||||
handlers.AddHandler<AbsoluteLayout, LayoutHandler>();
|
||||
handlers.AddHandler<FlexLayout, LayoutHandler>();
|
||||
handlers.AddHandler<ScrollView, ScrollViewHandler>();
|
||||
handlers.AddHandler<Frame, FrameHandler>();
|
||||
handlers.AddHandler<Border, BorderHandler>();
|
||||
handlers.AddHandler<ContentView, BorderHandler>();
|
||||
|
||||
// Picker controls
|
||||
handlers.AddHandler<Picker, PickerHandler>();
|
||||
handlers.AddHandler<DatePicker, DatePickerHandler>();
|
||||
handlers.AddHandler<TimePicker, TimePickerHandler>();
|
||||
handlers.AddHandler<SearchBar, SearchBarHandler>();
|
||||
|
||||
// Progress & Activity
|
||||
handlers.AddHandler<ProgressBar, ProgressBarHandler>();
|
||||
handlers.AddHandler<ActivityIndicator, ActivityIndicatorHandler>();
|
||||
|
||||
// Image & Graphics
|
||||
handlers.AddHandler<Image, ImageHandler>();
|
||||
handlers.AddHandler<ImageButton, ImageButtonHandler>();
|
||||
handlers.AddHandler<GraphicsView, GraphicsViewHandler>();
|
||||
|
||||
// Collection Views
|
||||
handlers.AddHandler<CollectionView, CollectionViewHandler>();
|
||||
handlers.AddHandler<ListView, CollectionViewHandler>();
|
||||
|
||||
// Pages & Navigation
|
||||
handlers.AddHandler<Page, PageHandler>();
|
||||
handlers.AddHandler<ContentPage, ContentPageHandler>();
|
||||
handlers.AddHandler<NavigationPage, NavigationPageHandler>();
|
||||
handlers.AddHandler<Shell, ShellHandler>();
|
||||
handlers.AddHandler<FlyoutPage, FlyoutPageHandler>();
|
||||
handlers.AddHandler<TabbedPage, TabbedPageHandler>();
|
||||
|
||||
// Application & Window
|
||||
handlers.AddHandler<Application, ApplicationHandler>();
|
||||
handlers.AddHandler<Microsoft.Maui.Controls.Window, WindowHandler>();
|
||||
});
|
||||
|
||||
// Store options for later use
|
||||
builder.Services.AddSingleton(options);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers custom type converters for Linux platform.
|
||||
/// </summary>
|
||||
private static void RegisterTypeConverters()
|
||||
{
|
||||
// Register SkiaSharp type converters for XAML styling support
|
||||
TypeDescriptor.AddAttributes(typeof(SKColor), new TypeConverterAttribute(typeof(SKColorTypeConverter)));
|
||||
TypeDescriptor.AddAttributes(typeof(SKRect), new TypeConverterAttribute(typeof(SKRectTypeConverter)));
|
||||
TypeDescriptor.AddAttributes(typeof(SKSize), new TypeConverterAttribute(typeof(SKSizeTypeConverter)));
|
||||
TypeDescriptor.AddAttributes(typeof(SKPoint), new TypeConverterAttribute(typeof(SKPointTypeConverter)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler registration extensions.
|
||||
/// </summary>
|
||||
public static class HandlerMappingExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a handler for the specified view type.
|
||||
/// </summary>
|
||||
public static IMauiHandlersCollection AddHandler<TView, THandler>(
|
||||
this IMauiHandlersCollection handlers)
|
||||
where TView : class
|
||||
where THandler : class
|
||||
{
|
||||
handlers.AddHandler(typeof(TView), typeof(THandler));
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,299 @@
|
||||
using System;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Maui.Animations;
|
||||
using Microsoft.Maui.Dispatching;
|
||||
using Microsoft.Maui.Platform;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// Linux-specific implementation of IMauiContext.
|
||||
/// Provides the infrastructure for creating handlers and accessing platform services.
|
||||
/// </summary>
|
||||
public class LinuxMauiContext : IMauiContext
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IMauiHandlersFactory _handlers;
|
||||
private readonly LinuxApplication _linuxApp;
|
||||
private IAnimationManager? _animationManager;
|
||||
private IDispatcher? _dispatcher;
|
||||
|
||||
private readonly IMauiHandlersFactory _handlers;
|
||||
public LinuxMauiContext(IServiceProvider services, LinuxApplication linuxApp)
|
||||
{
|
||||
_services = services ?? throw new ArgumentNullException(nameof(services));
|
||||
_linuxApp = linuxApp ?? throw new ArgumentNullException(nameof(linuxApp));
|
||||
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
|
||||
}
|
||||
|
||||
private readonly LinuxApplication _linuxApp;
|
||||
/// <inheritdoc />
|
||||
public IServiceProvider Services => _services;
|
||||
|
||||
private IAnimationManager? _animationManager;
|
||||
/// <inheritdoc />
|
||||
public IMauiHandlersFactory Handlers => _handlers;
|
||||
|
||||
private IDispatcher? _dispatcher;
|
||||
/// <summary>
|
||||
/// Gets the Linux application instance.
|
||||
/// </summary>
|
||||
public LinuxApplication LinuxApp => _linuxApp;
|
||||
|
||||
public IServiceProvider Services => _services;
|
||||
/// <summary>
|
||||
/// Gets the animation manager.
|
||||
/// </summary>
|
||||
public IAnimationManager AnimationManager
|
||||
{
|
||||
get
|
||||
{
|
||||
_animationManager ??= _services.GetService<IAnimationManager>()
|
||||
?? new LinuxAnimationManager(new LinuxTicker());
|
||||
return _animationManager;
|
||||
}
|
||||
}
|
||||
|
||||
public IMauiHandlersFactory Handlers => _handlers;
|
||||
|
||||
public LinuxApplication LinuxApp => _linuxApp;
|
||||
|
||||
public IAnimationManager AnimationManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_animationManager == null)
|
||||
{
|
||||
_animationManager = (IAnimationManager?)(((object)_services.GetService<IAnimationManager>()) ?? ((object)new LinuxAnimationManager((ITicker)(object)new LinuxTicker())));
|
||||
}
|
||||
return _animationManager;
|
||||
}
|
||||
}
|
||||
|
||||
public IDispatcher Dispatcher
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dispatcher == null)
|
||||
{
|
||||
_dispatcher = (IDispatcher?)(((object)_services.GetService<IDispatcher>()) ?? ((object)new LinuxDispatcher()));
|
||||
}
|
||||
return _dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
public LinuxMauiContext(IServiceProvider services, LinuxApplication linuxApp)
|
||||
{
|
||||
_services = services ?? throw new ArgumentNullException("services");
|
||||
_linuxApp = linuxApp ?? throw new ArgumentNullException("linuxApp");
|
||||
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the dispatcher for UI thread operations.
|
||||
/// </summary>
|
||||
public IDispatcher Dispatcher
|
||||
{
|
||||
get
|
||||
{
|
||||
_dispatcher ??= _services.GetService<IDispatcher>()
|
||||
?? new LinuxDispatcher();
|
||||
return _dispatcher;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scoped MAUI context for a specific window or view hierarchy.
|
||||
/// </summary>
|
||||
public class ScopedLinuxMauiContext : IMauiContext
|
||||
{
|
||||
private readonly LinuxMauiContext _parent;
|
||||
|
||||
public ScopedLinuxMauiContext(LinuxMauiContext parent)
|
||||
{
|
||||
_parent = parent ?? throw new ArgumentNullException(nameof(parent));
|
||||
}
|
||||
|
||||
public IServiceProvider Services => _parent.Services;
|
||||
public IMauiHandlersFactory Handlers => _parent.Handlers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linux dispatcher for UI thread operations.
|
||||
/// </summary>
|
||||
internal class LinuxDispatcher : IDispatcher
|
||||
{
|
||||
private readonly object _lock = new();
|
||||
private readonly Queue<Action> _queue = new();
|
||||
private bool _isDispatching;
|
||||
|
||||
public bool IsDispatchRequired => false; // Linux uses single-threaded event loop
|
||||
|
||||
public IDispatcherTimer CreateTimer()
|
||||
{
|
||||
return new LinuxDispatcherTimer();
|
||||
}
|
||||
|
||||
public bool Dispatch(Action action)
|
||||
{
|
||||
if (action == null)
|
||||
return false;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_queue.Enqueue(action);
|
||||
}
|
||||
|
||||
ProcessQueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DispatchDelayed(TimeSpan delay, Action action)
|
||||
{
|
||||
if (action == null)
|
||||
return false;
|
||||
|
||||
Task.Delay(delay).ContinueWith(_ => Dispatch(action));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ProcessQueue()
|
||||
{
|
||||
if (_isDispatching)
|
||||
return;
|
||||
|
||||
_isDispatching = true;
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Action? action;
|
||||
lock (_lock)
|
||||
{
|
||||
if (_queue.Count == 0)
|
||||
break;
|
||||
action = _queue.Dequeue();
|
||||
}
|
||||
action?.Invoke();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isDispatching = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linux dispatcher timer implementation.
|
||||
/// </summary>
|
||||
internal class LinuxDispatcherTimer : IDispatcherTimer
|
||||
{
|
||||
private Timer? _timer;
|
||||
private TimeSpan _interval = TimeSpan.FromMilliseconds(16); // ~60fps default
|
||||
private bool _isRunning;
|
||||
private bool _isRepeating = true;
|
||||
|
||||
public TimeSpan Interval
|
||||
{
|
||||
get => _interval;
|
||||
set => _interval = value;
|
||||
}
|
||||
|
||||
public bool IsRunning => _isRunning;
|
||||
|
||||
public bool IsRepeating
|
||||
{
|
||||
get => _isRepeating;
|
||||
set => _isRepeating = value;
|
||||
}
|
||||
|
||||
public event EventHandler? Tick;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_isRunning)
|
||||
return;
|
||||
|
||||
_isRunning = true;
|
||||
_timer = new Timer(OnTimerCallback, null, _interval, _isRepeating ? _interval : Timeout.InfiniteTimeSpan);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_isRunning = false;
|
||||
_timer?.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
private void OnTimerCallback(object? state)
|
||||
{
|
||||
Tick?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
if (!_isRepeating)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linux animation manager.
|
||||
/// </summary>
|
||||
internal class LinuxAnimationManager : IAnimationManager
|
||||
{
|
||||
private readonly List<Microsoft.Maui.Animations.Animation> _animations = new();
|
||||
private readonly ITicker _ticker;
|
||||
|
||||
public LinuxAnimationManager(ITicker ticker)
|
||||
{
|
||||
_ticker = ticker;
|
||||
_ticker.Fire = OnTickerFire;
|
||||
}
|
||||
|
||||
public double SpeedModifier { get; set; } = 1.0;
|
||||
public bool AutoStartTicker { get; set; } = true;
|
||||
|
||||
public ITicker Ticker => _ticker;
|
||||
|
||||
public void Add(Microsoft.Maui.Animations.Animation animation)
|
||||
{
|
||||
_animations.Add(animation);
|
||||
|
||||
if (AutoStartTicker && !_ticker.IsRunning)
|
||||
{
|
||||
_ticker.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(Microsoft.Maui.Animations.Animation animation)
|
||||
{
|
||||
_animations.Remove(animation);
|
||||
|
||||
if (_animations.Count == 0 && _ticker.IsRunning)
|
||||
{
|
||||
_ticker.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTickerFire()
|
||||
{
|
||||
var animations = _animations.ToArray();
|
||||
foreach (var animation in animations)
|
||||
{
|
||||
animation.Tick(16.0 / 1000.0 * SpeedModifier); // ~60fps
|
||||
if (animation.HasFinished)
|
||||
{
|
||||
Remove(animation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Linux ticker for animation timing.
|
||||
/// </summary>
|
||||
internal class LinuxTicker : ITicker
|
||||
{
|
||||
private Timer? _timer;
|
||||
private bool _isRunning;
|
||||
private int _maxFps = 60;
|
||||
|
||||
public bool IsRunning => _isRunning;
|
||||
|
||||
public bool SystemEnabled => true;
|
||||
|
||||
public int MaxFps
|
||||
{
|
||||
get => _maxFps;
|
||||
set => _maxFps = Math.Max(1, Math.Min(120, value));
|
||||
}
|
||||
|
||||
public Action? Fire { get; set; }
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_isRunning)
|
||||
return;
|
||||
|
||||
_isRunning = true;
|
||||
var interval = TimeSpan.FromMilliseconds(1000.0 / _maxFps);
|
||||
_timer = new Timer(OnTimerCallback, null, TimeSpan.Zero, interval);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_isRunning = false;
|
||||
_timer?.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
private void OnTimerCallback(object? state)
|
||||
{
|
||||
Fire?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.Maui.Animations;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
internal class LinuxTicker : ITicker
|
||||
{
|
||||
private Timer? _timer;
|
||||
|
||||
private bool _isRunning;
|
||||
|
||||
private int _maxFps = 60;
|
||||
|
||||
public bool IsRunning => _isRunning;
|
||||
|
||||
public bool SystemEnabled => true;
|
||||
|
||||
public int MaxFps
|
||||
{
|
||||
get
|
||||
{
|
||||
return _maxFps;
|
||||
}
|
||||
set
|
||||
{
|
||||
_maxFps = Math.Max(1, Math.Min(120, value));
|
||||
}
|
||||
}
|
||||
|
||||
public Action? Fire { get; set; }
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
_isRunning = true;
|
||||
TimeSpan period = TimeSpan.FromMilliseconds(1000.0 / (double)_maxFps);
|
||||
_timer = new Timer(OnTimerCallback, null, TimeSpan.Zero, period);
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_isRunning = false;
|
||||
_timer?.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
private void OnTimerCallback(object? state)
|
||||
{
|
||||
Fire?.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -1,470 +1,497 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
// 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.Graphics;
|
||||
using Microsoft.Maui.Platform;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// Renders MAUI views to Skia platform views.
|
||||
/// Handles the conversion of the view hierarchy.
|
||||
/// </summary>
|
||||
public class LinuxViewRenderer
|
||||
{
|
||||
private readonly IMauiContext _mauiContext;
|
||||
private readonly IMauiContext _mauiContext;
|
||||
|
||||
public static Shell? CurrentMauiShell { get; private set; }
|
||||
/// <summary>
|
||||
/// Static reference to the current MAUI Shell for navigation support.
|
||||
/// Used when Shell.Current is not available through normal lifecycle.
|
||||
/// </summary>
|
||||
public static Shell? CurrentMauiShell { get; private set; }
|
||||
|
||||
public static SkiaShell? CurrentSkiaShell { get; private set; }
|
||||
/// <summary>
|
||||
/// Static reference to the current SkiaShell for navigation updates.
|
||||
/// </summary>
|
||||
public static SkiaShell? CurrentSkiaShell { get; private set; }
|
||||
|
||||
public static LinuxViewRenderer? CurrentRenderer { get; set; }
|
||||
/// <summary>
|
||||
/// Navigate to a route using the SkiaShell directly.
|
||||
/// Use this instead of Shell.Current.GoToAsync on Linux.
|
||||
/// </summary>
|
||||
/// <param name="route">The route to navigate to (e.g., "Buttons" or "//Buttons")</param>
|
||||
/// <returns>True if navigation succeeded</returns>
|
||||
public static bool NavigateToRoute(string route)
|
||||
{
|
||||
if (CurrentSkiaShell == null)
|
||||
{
|
||||
Console.WriteLine($"[NavigateToRoute] CurrentSkiaShell is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool NavigateToRoute(string route)
|
||||
{
|
||||
if (CurrentSkiaShell == null)
|
||||
{
|
||||
Console.WriteLine("[NavigateToRoute] CurrentSkiaShell is null");
|
||||
return false;
|
||||
}
|
||||
string text = route.TrimStart('/');
|
||||
Console.WriteLine("[NavigateToRoute] Navigating to: " + text);
|
||||
for (int i = 0; i < CurrentSkiaShell.Sections.Count; i++)
|
||||
{
|
||||
ShellSection shellSection = CurrentSkiaShell.Sections[i];
|
||||
if (shellSection.Route.Equals(text, StringComparison.OrdinalIgnoreCase) || shellSection.Title.Equals(text, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.WriteLine($"[NavigateToRoute] Found section {i}: {shellSection.Title}");
|
||||
CurrentSkiaShell.NavigateToSection(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Console.WriteLine("[NavigateToRoute] Route not found: " + text);
|
||||
return false;
|
||||
}
|
||||
// Clean up the route - remove leading // or /
|
||||
var cleanRoute = route.TrimStart('/');
|
||||
Console.WriteLine($"[NavigateToRoute] Navigating to: {cleanRoute}");
|
||||
|
||||
public static bool PushPage(Page page)
|
||||
{
|
||||
Console.WriteLine("[PushPage] Pushing page: " + ((object)page).GetType().Name);
|
||||
if (CurrentSkiaShell == null)
|
||||
{
|
||||
Console.WriteLine("[PushPage] CurrentSkiaShell is null");
|
||||
return false;
|
||||
}
|
||||
if (CurrentRenderer == null)
|
||||
{
|
||||
Console.WriteLine("[PushPage] CurrentRenderer is null");
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
SkiaView skiaView = null;
|
||||
ContentPage val = (ContentPage)(object)((page is ContentPage) ? page : null);
|
||||
if (val != null && val.Content != null)
|
||||
{
|
||||
skiaView = CurrentRenderer.RenderView((IView)(object)val.Content);
|
||||
}
|
||||
if (skiaView == null)
|
||||
{
|
||||
Console.WriteLine("[PushPage] Failed to render page content");
|
||||
return false;
|
||||
}
|
||||
if (!(skiaView is SkiaScrollView))
|
||||
{
|
||||
skiaView = new SkiaScrollView
|
||||
{
|
||||
Content = skiaView
|
||||
};
|
||||
}
|
||||
CurrentSkiaShell.PushAsync(skiaView, page.Title ?? "Detail");
|
||||
Console.WriteLine("[PushPage] Successfully pushed page");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("[PushPage] Error: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < CurrentSkiaShell.Sections.Count; i++)
|
||||
{
|
||||
var section = CurrentSkiaShell.Sections[i];
|
||||
if (section.Route.Equals(cleanRoute, StringComparison.OrdinalIgnoreCase) ||
|
||||
section.Title.Equals(cleanRoute, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.WriteLine($"[NavigateToRoute] Found section {i}: {section.Title}");
|
||||
CurrentSkiaShell.NavigateToSection(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool PopPage()
|
||||
{
|
||||
Console.WriteLine("[PopPage] Popping page");
|
||||
if (CurrentSkiaShell == null)
|
||||
{
|
||||
Console.WriteLine("[PopPage] CurrentSkiaShell is null");
|
||||
return false;
|
||||
}
|
||||
return CurrentSkiaShell.PopAsync();
|
||||
}
|
||||
Console.WriteLine($"[NavigateToRoute] Route not found: {cleanRoute}");
|
||||
return false;
|
||||
}
|
||||
|
||||
public LinuxViewRenderer(IMauiContext mauiContext)
|
||||
{
|
||||
_mauiContext = mauiContext ?? throw new ArgumentNullException("mauiContext");
|
||||
CurrentRenderer = this;
|
||||
}
|
||||
/// <summary>
|
||||
/// Current renderer instance for page rendering.
|
||||
/// </summary>
|
||||
public static LinuxViewRenderer? CurrentRenderer { get; set; }
|
||||
|
||||
public SkiaView? RenderPage(Page page)
|
||||
{
|
||||
if (page == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Shell val = (Shell)(object)((page is Shell) ? page : null);
|
||||
if (val != null)
|
||||
{
|
||||
return RenderShell(val);
|
||||
}
|
||||
IViewHandler handler = ((VisualElement)page).Handler;
|
||||
if (handler != null)
|
||||
{
|
||||
((IElementHandler)handler).DisconnectHandler();
|
||||
}
|
||||
if (((IElement)(object)page).ToHandler(_mauiContext).PlatformView is SkiaView skiaView)
|
||||
{
|
||||
ContentPage val2 = (ContentPage)(object)((page is ContentPage) ? page : null);
|
||||
if (val2 != null && val2.Content != null)
|
||||
{
|
||||
SkiaView skiaView2 = RenderView((IView)(object)val2.Content);
|
||||
if (skiaView is SkiaPage skiaPage && skiaView2 != null)
|
||||
{
|
||||
skiaPage.Content = skiaView2;
|
||||
}
|
||||
}
|
||||
return skiaView;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Pushes a page onto the navigation stack.
|
||||
/// </summary>
|
||||
/// <param name="page">The page to push</param>
|
||||
/// <returns>True if successful</returns>
|
||||
public static bool PushPage(Page page)
|
||||
{
|
||||
Console.WriteLine($"[PushPage] Pushing page: {page.GetType().Name}");
|
||||
|
||||
private SkiaShell RenderShell(Shell shell)
|
||||
{
|
||||
//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_002e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0041: Expected I4, but got Unknown
|
||||
CurrentMauiShell = shell;
|
||||
SkiaShell skiaShell = new SkiaShell();
|
||||
skiaShell.Title = ((Page)shell).Title ?? "App";
|
||||
SkiaShell skiaShell2 = skiaShell;
|
||||
FlyoutBehavior flyoutBehavior = shell.FlyoutBehavior;
|
||||
skiaShell2.FlyoutBehavior = (int)flyoutBehavior switch
|
||||
{
|
||||
1 => ShellFlyoutBehavior.Flyout,
|
||||
2 => ShellFlyoutBehavior.Locked,
|
||||
0 => ShellFlyoutBehavior.Disabled,
|
||||
_ => ShellFlyoutBehavior.Flyout,
|
||||
};
|
||||
skiaShell.MauiShell = shell;
|
||||
SkiaShell skiaShell3 = skiaShell;
|
||||
ApplyShellColors(skiaShell3, shell);
|
||||
object flyoutHeader = shell.FlyoutHeader;
|
||||
View val = (View)((flyoutHeader is View) ? flyoutHeader : null);
|
||||
if (val != null)
|
||||
{
|
||||
SkiaView skiaView = RenderView((IView)(object)val);
|
||||
if (skiaView != null)
|
||||
{
|
||||
skiaShell3.FlyoutHeaderView = skiaView;
|
||||
skiaShell3.FlyoutHeaderHeight = (float)((((VisualElement)val).HeightRequest > 0.0) ? ((VisualElement)val).HeightRequest : 140.0);
|
||||
}
|
||||
}
|
||||
Version version = Assembly.GetEntryAssembly()?.GetName().Version;
|
||||
skiaShell3.FlyoutFooterText = $"Version {version?.Major ?? 1}.{version?.Minor ?? 0}.{version?.Build ?? 0}";
|
||||
foreach (ShellItem item in shell.Items)
|
||||
{
|
||||
ProcessShellItem(skiaShell3, item);
|
||||
}
|
||||
CurrentSkiaShell = skiaShell3;
|
||||
skiaShell3.ContentRenderer = CreateShellContentPage;
|
||||
skiaShell3.ColorRefresher = ApplyShellColors;
|
||||
shell.Navigated += OnShellNavigated;
|
||||
shell.Navigating += delegate(object? s, ShellNavigatingEventArgs e)
|
||||
{
|
||||
Console.WriteLine($"[Navigation] Navigating: {e.Target}");
|
||||
};
|
||||
Console.WriteLine($"[Navigation] Shell navigation events subscribed. Sections: {skiaShell3.Sections.Count}");
|
||||
for (int num = 0; num < skiaShell3.Sections.Count; num++)
|
||||
{
|
||||
Console.WriteLine($"[Navigation] Section {num}: Route='{skiaShell3.Sections[num].Route}', Title='{skiaShell3.Sections[num].Title}'");
|
||||
}
|
||||
return skiaShell3;
|
||||
}
|
||||
if (CurrentSkiaShell == null)
|
||||
{
|
||||
Console.WriteLine($"[PushPage] CurrentSkiaShell is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ApplyShellColors(SkiaShell skiaShell, Shell shell)
|
||||
{
|
||||
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0012: Invalid comparison between Unknown and I4
|
||||
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
|
||||
Application current = Application.Current;
|
||||
bool flag = current != null && (int)current.UserAppTheme == 2;
|
||||
Console.WriteLine("[ApplyShellColors] Theme is: " + (flag ? "Dark" : "Light"));
|
||||
if (shell.FlyoutBackgroundColor != null && shell.FlyoutBackgroundColor != Colors.Transparent)
|
||||
{
|
||||
Color flyoutBackgroundColor = shell.FlyoutBackgroundColor;
|
||||
skiaShell.FlyoutBackgroundColor = new SKColor((byte)(flyoutBackgroundColor.Red * 255f), (byte)(flyoutBackgroundColor.Green * 255f), (byte)(flyoutBackgroundColor.Blue * 255f), (byte)(flyoutBackgroundColor.Alpha * 255f));
|
||||
Console.WriteLine($"[ApplyShellColors] FlyoutBackgroundColor from MAUI: {skiaShell.FlyoutBackgroundColor}");
|
||||
}
|
||||
else
|
||||
{
|
||||
skiaShell.FlyoutBackgroundColor = (flag ? new SKColor((byte)30, (byte)30, (byte)30) : new SKColor(byte.MaxValue, byte.MaxValue, byte.MaxValue));
|
||||
Console.WriteLine($"[ApplyShellColors] Using default FlyoutBackgroundColor: {skiaShell.FlyoutBackgroundColor}");
|
||||
}
|
||||
skiaShell.FlyoutTextColor = (flag ? new SKColor((byte)224, (byte)224, (byte)224) : new SKColor((byte)33, (byte)33, (byte)33));
|
||||
Console.WriteLine($"[ApplyShellColors] FlyoutTextColor: {skiaShell.FlyoutTextColor}");
|
||||
skiaShell.ContentBackgroundColor = (flag ? new SKColor((byte)18, (byte)18, (byte)18) : new SKColor((byte)250, (byte)250, (byte)250));
|
||||
Console.WriteLine($"[ApplyShellColors] ContentBackgroundColor: {skiaShell.ContentBackgroundColor}");
|
||||
if (((VisualElement)shell).BackgroundColor != null && ((VisualElement)shell).BackgroundColor != Colors.Transparent)
|
||||
{
|
||||
Color backgroundColor = ((VisualElement)shell).BackgroundColor;
|
||||
skiaShell.NavBarBackgroundColor = new SKColor((byte)(backgroundColor.Red * 255f), (byte)(backgroundColor.Green * 255f), (byte)(backgroundColor.Blue * 255f), (byte)(backgroundColor.Alpha * 255f));
|
||||
}
|
||||
else
|
||||
{
|
||||
skiaShell.NavBarBackgroundColor = new SKColor((byte)33, (byte)150, (byte)243);
|
||||
}
|
||||
}
|
||||
if (CurrentRenderer == null)
|
||||
{
|
||||
Console.WriteLine($"[PushPage] CurrentRenderer is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
|
||||
{
|
||||
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||||
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(70, 3);
|
||||
defaultInterpolatedStringHandler.AppendLiteral("[Navigation] OnShellNavigated called - Source: ");
|
||||
defaultInterpolatedStringHandler.AppendFormatted<ShellNavigationSource>(e.Source);
|
||||
defaultInterpolatedStringHandler.AppendLiteral(", Current: ");
|
||||
ShellNavigationState current = e.Current;
|
||||
defaultInterpolatedStringHandler.AppendFormatted((current != null) ? current.Location : null);
|
||||
defaultInterpolatedStringHandler.AppendLiteral(", Previous: ");
|
||||
ShellNavigationState previous = e.Previous;
|
||||
defaultInterpolatedStringHandler.AppendFormatted((previous != null) ? previous.Location : null);
|
||||
Console.WriteLine(defaultInterpolatedStringHandler.ToStringAndClear());
|
||||
if (CurrentSkiaShell == null || CurrentMauiShell == null)
|
||||
{
|
||||
Console.WriteLine("[Navigation] CurrentSkiaShell or CurrentMauiShell is null");
|
||||
return;
|
||||
}
|
||||
ShellNavigationState currentState = CurrentMauiShell.CurrentState;
|
||||
string text = ((currentState == null) ? null : currentState.Location?.OriginalString) ?? "";
|
||||
Console.WriteLine($"[Navigation] Location: {text}, Sections: {CurrentSkiaShell.Sections.Count}");
|
||||
for (int i = 0; i < CurrentSkiaShell.Sections.Count; i++)
|
||||
{
|
||||
ShellSection shellSection = CurrentSkiaShell.Sections[i];
|
||||
Console.WriteLine($"[Navigation] Checking section {i}: Route='{shellSection.Route}', Title='{shellSection.Title}'");
|
||||
if (!string.IsNullOrEmpty(shellSection.Route) && text.Contains(shellSection.Route, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.WriteLine($"[Navigation] Match found by route! Navigating to section {i}");
|
||||
if (i != CurrentSkiaShell.CurrentSectionIndex)
|
||||
{
|
||||
CurrentSkiaShell.NavigateToSection(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(shellSection.Title) && text.Contains(shellSection.Title, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.WriteLine($"[Navigation] Match found by title! Navigating to section {i}");
|
||||
if (i != CurrentSkiaShell.CurrentSectionIndex)
|
||||
{
|
||||
CurrentSkiaShell.NavigateToSection(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Console.WriteLine("[Navigation] No matching section found for location: " + text);
|
||||
}
|
||||
try
|
||||
{
|
||||
// Render the page content
|
||||
SkiaView? pageContent = null;
|
||||
if (page is ContentPage contentPage && contentPage.Content != null)
|
||||
{
|
||||
pageContent = CurrentRenderer.RenderView(contentPage.Content);
|
||||
}
|
||||
|
||||
private void ProcessShellItem(SkiaShell skiaShell, ShellItem item)
|
||||
{
|
||||
FlyoutItem val = (FlyoutItem)(object)((item is FlyoutItem) ? item : null);
|
||||
if (val != null)
|
||||
{
|
||||
ShellSection shellSection = new ShellSection
|
||||
{
|
||||
Title = (((BaseShellItem)val).Title ?? ""),
|
||||
Route = (((BaseShellItem)val).Route ?? ((BaseShellItem)val).Title ?? "")
|
||||
};
|
||||
foreach (ShellSection item2 in ((ShellItem)val).Items)
|
||||
{
|
||||
foreach (ShellContent item3 in item2.Items)
|
||||
{
|
||||
ShellContent shellContent = new ShellContent
|
||||
{
|
||||
Title = (((BaseShellItem)item3).Title ?? ((BaseShellItem)item2).Title ?? ((BaseShellItem)val).Title ?? ""),
|
||||
Route = (((BaseShellItem)item3).Route ?? ""),
|
||||
MauiShellContent = item3
|
||||
};
|
||||
SkiaView skiaView = CreateShellContentPage(item3);
|
||||
if (skiaView != null)
|
||||
{
|
||||
shellContent.Content = skiaView;
|
||||
}
|
||||
shellSection.Items.Add(shellContent);
|
||||
}
|
||||
}
|
||||
if (shellSection.Items.Count == 1)
|
||||
{
|
||||
shellSection.Title = shellSection.Items[0].Title;
|
||||
}
|
||||
skiaShell.AddSection(shellSection);
|
||||
return;
|
||||
}
|
||||
TabBar val2 = (TabBar)(object)((item is TabBar) ? item : null);
|
||||
if (val2 != null)
|
||||
{
|
||||
foreach (ShellSection item4 in ((ShellItem)val2).Items)
|
||||
{
|
||||
ShellSection shellSection2 = new ShellSection
|
||||
{
|
||||
Title = (((BaseShellItem)item4).Title ?? ""),
|
||||
Route = (((BaseShellItem)item4).Route ?? "")
|
||||
};
|
||||
foreach (ShellContent item5 in item4.Items)
|
||||
{
|
||||
ShellContent shellContent2 = new ShellContent
|
||||
{
|
||||
Title = (((BaseShellItem)item5).Title ?? ((BaseShellItem)item4).Title ?? ""),
|
||||
Route = (((BaseShellItem)item5).Route ?? ""),
|
||||
MauiShellContent = item5
|
||||
};
|
||||
SkiaView skiaView2 = CreateShellContentPage(item5);
|
||||
if (skiaView2 != null)
|
||||
{
|
||||
shellContent2.Content = skiaView2;
|
||||
}
|
||||
shellSection2.Items.Add(shellContent2);
|
||||
}
|
||||
skiaShell.AddSection(shellSection2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ShellSection shellSection3 = new ShellSection
|
||||
{
|
||||
Title = (((BaseShellItem)item).Title ?? ""),
|
||||
Route = (((BaseShellItem)item).Route ?? "")
|
||||
};
|
||||
foreach (ShellSection item6 in item.Items)
|
||||
{
|
||||
foreach (ShellContent item7 in item6.Items)
|
||||
{
|
||||
ShellContent shellContent3 = new ShellContent
|
||||
{
|
||||
Title = (((BaseShellItem)item7).Title ?? ""),
|
||||
Route = (((BaseShellItem)item7).Route ?? ""),
|
||||
MauiShellContent = item7
|
||||
};
|
||||
SkiaView skiaView3 = CreateShellContentPage(item7);
|
||||
if (skiaView3 != null)
|
||||
{
|
||||
shellContent3.Content = skiaView3;
|
||||
}
|
||||
shellSection3.Items.Add(shellContent3);
|
||||
}
|
||||
}
|
||||
skiaShell.AddSection(shellSection3);
|
||||
}
|
||||
if (pageContent == null)
|
||||
{
|
||||
Console.WriteLine($"[PushPage] Failed to render page content");
|
||||
return false;
|
||||
}
|
||||
|
||||
private SkiaView? CreateShellContentPage(ShellContent content)
|
||||
{
|
||||
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
|
||||
try
|
||||
{
|
||||
Page val = null;
|
||||
if (content.ContentTemplate != null)
|
||||
{
|
||||
object obj = ((ElementTemplate)content.ContentTemplate).CreateContent();
|
||||
val = (Page)((obj is Page) ? obj : null);
|
||||
}
|
||||
if (val == null)
|
||||
{
|
||||
object content2 = content.Content;
|
||||
Page val2 = (Page)((content2 is Page) ? content2 : null);
|
||||
if (val2 != null)
|
||||
{
|
||||
val = val2;
|
||||
}
|
||||
}
|
||||
ContentPage val3 = (ContentPage)(object)((val is ContentPage) ? val : null);
|
||||
if (val3 != null && val3.Content != null)
|
||||
{
|
||||
SkiaView skiaView = RenderView((IView)(object)val3.Content);
|
||||
if (skiaView != null)
|
||||
{
|
||||
SKColor? value = null;
|
||||
if (((VisualElement)val3).BackgroundColor != null && ((VisualElement)val3).BackgroundColor != Colors.Transparent)
|
||||
{
|
||||
Color backgroundColor = ((VisualElement)val3).BackgroundColor;
|
||||
value = new SKColor((byte)(backgroundColor.Red * 255f), (byte)(backgroundColor.Green * 255f), (byte)(backgroundColor.Blue * 255f), (byte)(backgroundColor.Alpha * 255f));
|
||||
Console.WriteLine($"[CreateShellContentPage] Page BackgroundColor: {value}");
|
||||
}
|
||||
if (skiaView is SkiaScrollView skiaScrollView)
|
||||
{
|
||||
if (value.HasValue)
|
||||
{
|
||||
skiaScrollView.BackgroundColor = value.Value;
|
||||
}
|
||||
return skiaScrollView;
|
||||
}
|
||||
SkiaScrollView skiaScrollView2 = new SkiaScrollView
|
||||
{
|
||||
Content = skiaView
|
||||
};
|
||||
if (value.HasValue)
|
||||
{
|
||||
skiaScrollView2.BackgroundColor = value.Value;
|
||||
}
|
||||
return skiaScrollView2;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Wrap in ScrollView if needed
|
||||
if (pageContent is not SkiaScrollView)
|
||||
{
|
||||
var scrollView = new SkiaScrollView { Content = pageContent };
|
||||
pageContent = scrollView;
|
||||
}
|
||||
|
||||
public SkiaView? RenderView(IView view)
|
||||
{
|
||||
if (view == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
Element val = (Element)(object)((view is Element) ? view : null);
|
||||
if (val != null && val.Handler != null)
|
||||
{
|
||||
val.Handler.DisconnectHandler();
|
||||
}
|
||||
IElementHandler obj = ((IElement)(object)view).ToHandler(_mauiContext);
|
||||
if (!(((obj != null) ? obj.PlatformView : null) is SkiaView result))
|
||||
{
|
||||
return CreateFallbackView(view);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return CreateFallbackView(view);
|
||||
}
|
||||
}
|
||||
// Push onto SkiaShell's navigation stack
|
||||
CurrentSkiaShell.PushAsync(pageContent, page.Title ?? "Detail");
|
||||
Console.WriteLine($"[PushPage] Successfully pushed page");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[PushPage] Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private SkiaView CreateFallbackView(IView view)
|
||||
{
|
||||
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||||
return new SkiaLabel
|
||||
{
|
||||
Text = "[" + ((object)view).GetType().Name + "]",
|
||||
TextColor = SKColors.Gray,
|
||||
FontSize = 12f
|
||||
};
|
||||
}
|
||||
/// <summary>
|
||||
/// Pops the current page from the navigation stack.
|
||||
/// </summary>
|
||||
/// <returns>True if successful</returns>
|
||||
public static bool PopPage()
|
||||
{
|
||||
Console.WriteLine($"[PopPage] Popping page");
|
||||
|
||||
if (CurrentSkiaShell == null)
|
||||
{
|
||||
Console.WriteLine($"[PopPage] CurrentSkiaShell is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
return CurrentSkiaShell.PopAsync();
|
||||
}
|
||||
|
||||
public LinuxViewRenderer(IMauiContext mauiContext)
|
||||
{
|
||||
_mauiContext = mauiContext ?? throw new ArgumentNullException(nameof(mauiContext));
|
||||
// Store reference for push/pop navigation
|
||||
CurrentRenderer = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a MAUI page and returns the corresponding SkiaView.
|
||||
/// </summary>
|
||||
public SkiaView? RenderPage(Page page)
|
||||
{
|
||||
if (page == null)
|
||||
return null;
|
||||
|
||||
// Special handling for Shell - Shell is our navigation container
|
||||
if (page is Shell shell)
|
||||
{
|
||||
return RenderShell(shell);
|
||||
}
|
||||
|
||||
// Set handler context
|
||||
page.Handler?.DisconnectHandler();
|
||||
var handler = page.ToHandler(_mauiContext);
|
||||
|
||||
if (handler.PlatformView is SkiaView skiaPage)
|
||||
{
|
||||
// For ContentPage, render the content
|
||||
if (page is ContentPage contentPage && contentPage.Content != null)
|
||||
{
|
||||
var contentView = RenderView(contentPage.Content);
|
||||
if (skiaPage is SkiaPage sp && contentView != null)
|
||||
{
|
||||
sp.Content = contentView;
|
||||
}
|
||||
}
|
||||
|
||||
return skiaPage;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a MAUI Shell with all its navigation structure.
|
||||
/// </summary>
|
||||
private SkiaShell RenderShell(Shell shell)
|
||||
{
|
||||
// Store reference for navigation - Shell.Current is computed from Application.Current.Windows
|
||||
// Our platform handles navigation through SkiaShell directly
|
||||
CurrentMauiShell = shell;
|
||||
|
||||
var skiaShell = new SkiaShell
|
||||
{
|
||||
Title = shell.Title ?? "App",
|
||||
FlyoutBehavior = shell.FlyoutBehavior switch
|
||||
{
|
||||
FlyoutBehavior.Flyout => ShellFlyoutBehavior.Flyout,
|
||||
FlyoutBehavior.Locked => ShellFlyoutBehavior.Locked,
|
||||
FlyoutBehavior.Disabled => ShellFlyoutBehavior.Disabled,
|
||||
_ => ShellFlyoutBehavior.Flyout
|
||||
}
|
||||
};
|
||||
|
||||
// Process shell items into sections
|
||||
foreach (var item in shell.Items)
|
||||
{
|
||||
ProcessShellItem(skiaShell, item);
|
||||
}
|
||||
|
||||
// Store reference to SkiaShell for navigation
|
||||
CurrentSkiaShell = skiaShell;
|
||||
|
||||
// Subscribe to MAUI Shell navigation events to update SkiaShell
|
||||
shell.Navigated += OnShellNavigated;
|
||||
shell.Navigating += (s, e) => Console.WriteLine($"[Navigation] Navigating: {e.Target}");
|
||||
|
||||
Console.WriteLine($"[Navigation] Shell navigation events subscribed. Sections: {skiaShell.Sections.Count}");
|
||||
for (int i = 0; i < skiaShell.Sections.Count; i++)
|
||||
{
|
||||
Console.WriteLine($"[Navigation] Section {i}: Route='{skiaShell.Sections[i].Route}', Title='{skiaShell.Sections[i].Title}'");
|
||||
}
|
||||
|
||||
return skiaShell;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles MAUI Shell navigation events and updates SkiaShell accordingly.
|
||||
/// </summary>
|
||||
private static void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
|
||||
{
|
||||
Console.WriteLine($"[Navigation] OnShellNavigated called - Source: {e.Source}, Current: {e.Current?.Location}, Previous: {e.Previous?.Location}");
|
||||
|
||||
if (CurrentSkiaShell == null || CurrentMauiShell == null)
|
||||
{
|
||||
Console.WriteLine($"[Navigation] CurrentSkiaShell or CurrentMauiShell is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current route from the Shell
|
||||
var currentState = CurrentMauiShell.CurrentState;
|
||||
var location = currentState?.Location?.OriginalString ?? "";
|
||||
Console.WriteLine($"[Navigation] Location: {location}, Sections: {CurrentSkiaShell.Sections.Count}");
|
||||
|
||||
// Find the matching section in SkiaShell by route
|
||||
for (int i = 0; i < CurrentSkiaShell.Sections.Count; i++)
|
||||
{
|
||||
var section = CurrentSkiaShell.Sections[i];
|
||||
Console.WriteLine($"[Navigation] Checking section {i}: Route='{section.Route}', Title='{section.Title}'");
|
||||
if (!string.IsNullOrEmpty(section.Route) && location.Contains(section.Route, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.WriteLine($"[Navigation] Match found by route! Navigating to section {i}");
|
||||
if (i != CurrentSkiaShell.CurrentSectionIndex)
|
||||
{
|
||||
CurrentSkiaShell.NavigateToSection(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(section.Title) && location.Contains(section.Title, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.WriteLine($"[Navigation] Match found by title! Navigating to section {i}");
|
||||
if (i != CurrentSkiaShell.CurrentSectionIndex)
|
||||
{
|
||||
CurrentSkiaShell.NavigateToSection(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"[Navigation] No matching section found for location: {location}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process a ShellItem (FlyoutItem, TabBar, etc.) into SkiaShell sections.
|
||||
/// </summary>
|
||||
private void ProcessShellItem(SkiaShell skiaShell, ShellItem item)
|
||||
{
|
||||
if (item is FlyoutItem flyoutItem)
|
||||
{
|
||||
// Each FlyoutItem becomes a section
|
||||
var section = new ShellSection
|
||||
{
|
||||
Title = flyoutItem.Title ?? "",
|
||||
Route = flyoutItem.Route ?? flyoutItem.Title ?? ""
|
||||
};
|
||||
|
||||
// Process the items within the FlyoutItem
|
||||
foreach (var shellSection in flyoutItem.Items)
|
||||
{
|
||||
foreach (var content in shellSection.Items)
|
||||
{
|
||||
var shellContent = new ShellContent
|
||||
{
|
||||
Title = content.Title ?? shellSection.Title ?? flyoutItem.Title ?? "",
|
||||
Route = content.Route ?? ""
|
||||
};
|
||||
|
||||
// Create the page content
|
||||
var pageContent = CreateShellContentPage(content);
|
||||
if (pageContent != null)
|
||||
{
|
||||
shellContent.Content = pageContent;
|
||||
}
|
||||
|
||||
section.Items.Add(shellContent);
|
||||
}
|
||||
}
|
||||
|
||||
// If there's only one item, use it as the main section content
|
||||
if (section.Items.Count == 1)
|
||||
{
|
||||
section.Title = section.Items[0].Title;
|
||||
}
|
||||
|
||||
skiaShell.AddSection(section);
|
||||
}
|
||||
else if (item is TabBar tabBar)
|
||||
{
|
||||
// TabBar items get their own sections
|
||||
foreach (var tab in tabBar.Items)
|
||||
{
|
||||
var section = new ShellSection
|
||||
{
|
||||
Title = tab.Title ?? "",
|
||||
Route = tab.Route ?? ""
|
||||
};
|
||||
|
||||
foreach (var content in tab.Items)
|
||||
{
|
||||
var shellContent = new ShellContent
|
||||
{
|
||||
Title = content.Title ?? tab.Title ?? "",
|
||||
Route = content.Route ?? ""
|
||||
};
|
||||
|
||||
var pageContent = CreateShellContentPage(content);
|
||||
if (pageContent != null)
|
||||
{
|
||||
shellContent.Content = pageContent;
|
||||
}
|
||||
|
||||
section.Items.Add(shellContent);
|
||||
}
|
||||
|
||||
skiaShell.AddSection(section);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generic ShellItem
|
||||
var section = new ShellSection
|
||||
{
|
||||
Title = item.Title ?? "",
|
||||
Route = item.Route ?? ""
|
||||
};
|
||||
|
||||
foreach (var shellSection in item.Items)
|
||||
{
|
||||
foreach (var content in shellSection.Items)
|
||||
{
|
||||
var shellContent = new ShellContent
|
||||
{
|
||||
Title = content.Title ?? "",
|
||||
Route = content.Route ?? ""
|
||||
};
|
||||
|
||||
var pageContent = CreateShellContentPage(content);
|
||||
if (pageContent != null)
|
||||
{
|
||||
shellContent.Content = pageContent;
|
||||
}
|
||||
|
||||
section.Items.Add(shellContent);
|
||||
}
|
||||
}
|
||||
|
||||
skiaShell.AddSection(section);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the page content for a ShellContent.
|
||||
/// </summary>
|
||||
private SkiaView? CreateShellContentPage(Controls.ShellContent content)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try to create the page from the content template
|
||||
Page? page = null;
|
||||
|
||||
if (content.ContentTemplate != null)
|
||||
{
|
||||
page = content.ContentTemplate.CreateContent() as Page;
|
||||
}
|
||||
|
||||
if (page == null && content.Content is Page contentPage)
|
||||
{
|
||||
page = contentPage;
|
||||
}
|
||||
|
||||
if (page is ContentPage cp && cp.Content != null)
|
||||
{
|
||||
// Wrap in a scroll view if not already scrollable
|
||||
var contentView = RenderView(cp.Content);
|
||||
if (contentView != null)
|
||||
{
|
||||
if (contentView is SkiaScrollView)
|
||||
{
|
||||
return contentView;
|
||||
}
|
||||
else
|
||||
{
|
||||
var scrollView = new SkiaScrollView
|
||||
{
|
||||
Content = contentView
|
||||
};
|
||||
return scrollView;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Silently handle template creation errors
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a MAUI view and returns the corresponding SkiaView.
|
||||
/// </summary>
|
||||
public SkiaView? RenderView(IView view)
|
||||
{
|
||||
if (view == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
// Disconnect any existing handler
|
||||
if (view is Element element && element.Handler != null)
|
||||
{
|
||||
element.Handler.DisconnectHandler();
|
||||
}
|
||||
|
||||
// Create handler for the view
|
||||
// The handler's ConnectHandler and property mappers handle child views automatically
|
||||
var handler = view.ToHandler(_mauiContext);
|
||||
|
||||
if (handler?.PlatformView is not SkiaView skiaView)
|
||||
{
|
||||
// If no Skia handler, create a fallback
|
||||
return CreateFallbackView(view);
|
||||
}
|
||||
|
||||
// Handlers manage their own children via ConnectHandler and property mappers
|
||||
// No manual child rendering needed here - that caused "View already has a parent" errors
|
||||
return skiaView;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return CreateFallbackView(view);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a fallback view for unsupported view types.
|
||||
/// </summary>
|
||||
private SkiaView CreateFallbackView(IView view)
|
||||
{
|
||||
// For views without handlers, create a placeholder
|
||||
return new SkiaLabel
|
||||
{
|
||||
Text = $"[{view.GetType().Name}]",
|
||||
TextColor = SKColors.Gray,
|
||||
FontSize = 12
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for MAUI handler creation.
|
||||
/// </summary>
|
||||
public static class MauiHandlerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a handler for the view and returns it.
|
||||
/// </summary>
|
||||
public static IElementHandler ToHandler(this IElement element, IMauiContext mauiContext)
|
||||
{
|
||||
var handler = mauiContext.Handlers.GetHandler(element.GetType());
|
||||
if (handler != null)
|
||||
{
|
||||
handler.SetMauiContext(mauiContext);
|
||||
handler.SetVirtualView(element);
|
||||
}
|
||||
return handler!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Platform.Linux.Handlers;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
public static class MauiHandlerExtensions
|
||||
{
|
||||
private static readonly Dictionary<Type, Func<IElementHandler>> LinuxHandlerMap = new Dictionary<Type, Func<IElementHandler>>
|
||||
{
|
||||
[typeof(Button)] = () => (IElementHandler)(object)new TextButtonHandler(),
|
||||
[typeof(Label)] = () => (IElementHandler)(object)new LabelHandler(),
|
||||
[typeof(Entry)] = () => (IElementHandler)(object)new EntryHandler(),
|
||||
[typeof(Editor)] = () => (IElementHandler)(object)new EditorHandler(),
|
||||
[typeof(CheckBox)] = () => (IElementHandler)(object)new CheckBoxHandler(),
|
||||
[typeof(Switch)] = () => (IElementHandler)(object)new SwitchHandler(),
|
||||
[typeof(Slider)] = () => (IElementHandler)(object)new SliderHandler(),
|
||||
[typeof(Stepper)] = () => (IElementHandler)(object)new StepperHandler(),
|
||||
[typeof(ProgressBar)] = () => (IElementHandler)(object)new ProgressBarHandler(),
|
||||
[typeof(ActivityIndicator)] = () => (IElementHandler)(object)new ActivityIndicatorHandler(),
|
||||
[typeof(Picker)] = () => (IElementHandler)(object)new PickerHandler(),
|
||||
[typeof(DatePicker)] = () => (IElementHandler)(object)new DatePickerHandler(),
|
||||
[typeof(TimePicker)] = () => (IElementHandler)(object)new TimePickerHandler(),
|
||||
[typeof(SearchBar)] = () => (IElementHandler)(object)new SearchBarHandler(),
|
||||
[typeof(RadioButton)] = () => (IElementHandler)(object)new RadioButtonHandler(),
|
||||
[typeof(WebView)] = () => (IElementHandler)(object)new GtkWebViewHandler(),
|
||||
[typeof(Image)] = () => (IElementHandler)(object)new ImageHandler(),
|
||||
[typeof(ImageButton)] = () => (IElementHandler)(object)new ImageButtonHandler(),
|
||||
[typeof(BoxView)] = () => (IElementHandler)(object)new BoxViewHandler(),
|
||||
[typeof(Frame)] = () => (IElementHandler)(object)new FrameHandler(),
|
||||
[typeof(Border)] = () => (IElementHandler)(object)new BorderHandler(),
|
||||
[typeof(ContentView)] = () => (IElementHandler)(object)new BorderHandler(),
|
||||
[typeof(ScrollView)] = () => (IElementHandler)(object)new ScrollViewHandler(),
|
||||
[typeof(Grid)] = () => (IElementHandler)(object)new GridHandler(),
|
||||
[typeof(StackLayout)] = () => (IElementHandler)(object)new StackLayoutHandler(),
|
||||
[typeof(VerticalStackLayout)] = () => (IElementHandler)(object)new StackLayoutHandler(),
|
||||
[typeof(HorizontalStackLayout)] = () => (IElementHandler)(object)new StackLayoutHandler(),
|
||||
[typeof(AbsoluteLayout)] = () => (IElementHandler)(object)new LayoutHandler(),
|
||||
[typeof(FlexLayout)] = () => (IElementHandler)(object)new LayoutHandler(),
|
||||
[typeof(CollectionView)] = () => (IElementHandler)(object)new CollectionViewHandler(),
|
||||
[typeof(ListView)] = () => (IElementHandler)(object)new CollectionViewHandler(),
|
||||
[typeof(Page)] = () => (IElementHandler)(object)new PageHandler(),
|
||||
[typeof(ContentPage)] = () => (IElementHandler)(object)new ContentPageHandler(),
|
||||
[typeof(NavigationPage)] = () => (IElementHandler)(object)new NavigationPageHandler(),
|
||||
[typeof(Shell)] = () => (IElementHandler)(object)new ShellHandler(),
|
||||
[typeof(FlyoutPage)] = () => (IElementHandler)(object)new FlyoutPageHandler(),
|
||||
[typeof(TabbedPage)] = () => (IElementHandler)(object)new TabbedPageHandler(),
|
||||
[typeof(Application)] = () => (IElementHandler)(object)new ApplicationHandler(),
|
||||
[typeof(Window)] = () => (IElementHandler)(object)new WindowHandler(),
|
||||
[typeof(GraphicsView)] = () => (IElementHandler)(object)new GraphicsViewHandler()
|
||||
};
|
||||
|
||||
public static IElementHandler ToHandler(this IElement element, IMauiContext mauiContext)
|
||||
{
|
||||
return CreateHandler(element, mauiContext);
|
||||
}
|
||||
|
||||
public static IViewHandler? ToViewHandler(this IView view, IMauiContext mauiContext)
|
||||
{
|
||||
IElementHandler? obj = CreateHandler((IElement)(object)view, mauiContext);
|
||||
return (IViewHandler?)(object)((obj is IViewHandler) ? obj : null);
|
||||
}
|
||||
|
||||
private static IElementHandler? CreateHandler(IElement element, IMauiContext mauiContext)
|
||||
{
|
||||
Type type = ((object)element).GetType();
|
||||
IElementHandler val = null;
|
||||
if (LinuxHandlerMap.TryGetValue(type, out Func<IElementHandler> value))
|
||||
{
|
||||
val = value();
|
||||
Console.WriteLine("[ToHandler] Using Linux handler for " + type.Name + ": " + ((object)val).GetType().Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Type type2 = null;
|
||||
Func<IElementHandler> func = null;
|
||||
foreach (KeyValuePair<Type, Func<IElementHandler>> item in LinuxHandlerMap)
|
||||
{
|
||||
if (item.Key.IsAssignableFrom(type) && (type2 == null || type2.IsAssignableFrom(item.Key)))
|
||||
{
|
||||
type2 = item.Key;
|
||||
func = item.Value;
|
||||
}
|
||||
}
|
||||
if (func != null)
|
||||
{
|
||||
val = func();
|
||||
Console.WriteLine($"[ToHandler] Using Linux handler (via base {type2.Name}) for {type.Name}: {((object)val).GetType().Name}");
|
||||
}
|
||||
}
|
||||
if (val == null)
|
||||
{
|
||||
val = mauiContext.Handlers.GetHandler(type);
|
||||
Console.WriteLine("[ToHandler] Using MAUI handler for " + type.Name + ": " + (((object)val)?.GetType().Name ?? "null"));
|
||||
}
|
||||
if (val != null)
|
||||
{
|
||||
val.SetMauiContext(mauiContext);
|
||||
val.SetVirtualView(element);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
public class ScopedLinuxMauiContext : IMauiContext
|
||||
{
|
||||
private readonly LinuxMauiContext _parent;
|
||||
|
||||
public IServiceProvider Services => _parent.Services;
|
||||
|
||||
public IMauiHandlersFactory Handlers => _parent.Handlers;
|
||||
|
||||
public ScopedLinuxMauiContext(LinuxMauiContext parent)
|
||||
{
|
||||
_parent = parent ?? throw new ArgumentNullException("parent");
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct ClientMessageData
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public long L0;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public long L1;
|
||||
|
||||
[FieldOffset(16)]
|
||||
public long L2;
|
||||
|
||||
[FieldOffset(24)]
|
||||
public long L3;
|
||||
|
||||
[FieldOffset(32)]
|
||||
public long L4;
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public static class WebKitGtk
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void GCallback();
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void LoadChangedCallback(IntPtr webView, int loadEvent, IntPtr userData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate bool DecidePolicyCallback(IntPtr webView, IntPtr decision, int decisionType, IntPtr userData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void LoadFailedCallback(IntPtr webView, int loadEvent, IntPtr failingUri, IntPtr error, IntPtr userData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void NotifyCallback(IntPtr webView, IntPtr paramSpec, IntPtr userData);
|
||||
|
||||
private const string WebKit2Lib = "libwebkit2gtk-4.1.so.0";
|
||||
|
||||
private const string GtkLib = "libgtk-3.so.0";
|
||||
|
||||
private const string GObjectLib = "libgobject-2.0.so.0";
|
||||
|
||||
private const string GLibLib = "libglib-2.0.so.0";
|
||||
|
||||
public const int WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS = 0;
|
||||
|
||||
public const int WEBKIT_COOKIE_POLICY_ACCEPT_NEVER = 1;
|
||||
|
||||
public const int WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY = 2;
|
||||
|
||||
public const int WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT = 0;
|
||||
|
||||
public const int WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE = 1;
|
||||
|
||||
public const int WEBKIT_LOAD_STARTED = 0;
|
||||
|
||||
public const int WEBKIT_LOAD_REDIRECTED = 1;
|
||||
|
||||
public const int WEBKIT_LOAD_COMMITTED = 2;
|
||||
|
||||
public const int WEBKIT_LOAD_FINISHED = 3;
|
||||
|
||||
public const int WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION = 0;
|
||||
|
||||
public const int WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION = 1;
|
||||
|
||||
public const int WEBKIT_POLICY_DECISION_TYPE_RESPONSE = 2;
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gtk_init_check(ref int argc, ref IntPtr argv);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_main();
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_main_quit();
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gtk_events_pending();
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_main_iteration();
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gtk_main_iteration_do(bool blocking);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr gtk_window_new(int type);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_window_set_default_size(IntPtr window, int width, int height);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_window_set_decorated(IntPtr window, bool decorated);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_window_move(IntPtr window, int x, int y);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_window_resize(IntPtr window, int width, int height);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_widget_show_all(IntPtr widget);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_widget_show(IntPtr widget);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_widget_hide(IntPtr widget);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_widget_destroy(IntPtr widget);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_widget_set_size_request(IntPtr widget, int width, int height);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_widget_realize(IntPtr widget);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr gtk_widget_get_window(IntPtr widget);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_widget_set_can_focus(IntPtr widget, bool canFocus);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_container_add(IntPtr container, IntPtr widget);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gtk_container_remove(IntPtr container, IntPtr widget);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr gtk_plug_new(ulong socketId);
|
||||
|
||||
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern ulong gtk_plug_get_id(IntPtr plug);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_view_new();
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_view_new_with_context(IntPtr context);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_web_view_load_uri(IntPtr webView, [MarshalAs(UnmanagedType.LPUTF8Str)] string uri);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_web_view_load_html(IntPtr webView, [MarshalAs(UnmanagedType.LPUTF8Str)] string content, [MarshalAs(UnmanagedType.LPUTF8Str)] string? baseUri);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_web_view_reload(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_web_view_stop_loading(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_web_view_go_back(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_web_view_go_forward(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool webkit_web_view_can_go_back(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool webkit_web_view_can_go_forward(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_view_get_uri(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_view_get_title(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern double webkit_web_view_get_estimated_load_progress(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool webkit_web_view_is_loading(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_web_view_run_javascript(IntPtr webView, [MarshalAs(UnmanagedType.LPUTF8Str)] string script, IntPtr cancellable, IntPtr callback, IntPtr userData);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_view_run_javascript_finish(IntPtr webView, IntPtr result, out IntPtr error);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_view_get_settings(IntPtr webView);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_settings_set_enable_javascript(IntPtr settings, bool enabled);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_settings_set_user_agent(IntPtr settings, [MarshalAs(UnmanagedType.LPUTF8Str)] string userAgent);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_settings_get_user_agent(IntPtr settings);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_settings_set_enable_developer_extras(IntPtr settings, bool enabled);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_settings_set_javascript_can_access_clipboard(IntPtr settings, bool enabled);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_settings_set_enable_webgl(IntPtr settings, bool enabled);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_settings_set_allow_file_access_from_file_urls(IntPtr settings, bool enabled);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_settings_set_allow_universal_access_from_file_urls(IntPtr settings, bool enabled);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_context_get_default();
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_context_new();
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_web_context_get_cookie_manager(IntPtr context);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_cookie_manager_set_accept_policy(IntPtr cookieManager, int policy);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_cookie_manager_set_persistent_storage(IntPtr cookieManager, [MarshalAs(UnmanagedType.LPUTF8Str)] string filename, int storage);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_navigation_action_get_request(IntPtr action);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int webkit_navigation_action_get_navigation_type(IntPtr action);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr webkit_uri_request_get_uri(IntPtr request);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_policy_decision_use(IntPtr decision);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_policy_decision_ignore(IntPtr decision);
|
||||
|
||||
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void webkit_policy_decision_download(IntPtr decision);
|
||||
|
||||
[DllImport("libgobject-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern ulong g_signal_connect_data(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string detailedSignal, Delegate handler, IntPtr data, IntPtr destroyData, int connectFlags);
|
||||
|
||||
[DllImport("libgobject-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void g_signal_handler_disconnect(IntPtr instance, ulong handlerId);
|
||||
|
||||
[DllImport("libgobject-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void g_object_unref(IntPtr obj);
|
||||
|
||||
[DllImport("libglib-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void g_free(IntPtr mem);
|
||||
|
||||
public static string? PtrToStringUtf8(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return Marshal.PtrToStringUTF8(ptr);
|
||||
}
|
||||
|
||||
public static void ProcessGtkEvents()
|
||||
{
|
||||
while (gtk_events_pending())
|
||||
{
|
||||
gtk_main_iteration_do(blocking: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
442
Interop/X11.cs
442
Interop/X11.cs
@@ -1,442 +0,0 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
internal static class X11
|
||||
{
|
||||
private const string LibX11 = "libX11.so.6";
|
||||
|
||||
private const string LibXext = "libXext.so.6";
|
||||
|
||||
public const int ZPixmap = 2;
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XOpenDisplay(IntPtr displayName);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XCloseDisplay(IntPtr display);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XDefaultScreen(IntPtr display);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XRootWindow(IntPtr display, int screenNumber);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XDisplayWidth(IntPtr display, int screenNumber);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XDisplayHeight(IntPtr display, int screenNumber);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XDefaultDepth(IntPtr display, int screenNumber);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XDefaultVisual(IntPtr display, int screenNumber);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XDefaultColormap(IntPtr display, int screenNumber);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XFlush(IntPtr display);
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public static int XSync(IntPtr display, [MarshalAs(UnmanagedType.Bool)] bool discard)
|
||||
{
|
||||
int _discard_native = (discard ? 1 : 0);
|
||||
return __PInvoke(display, _discard_native);
|
||||
[DllImport("libX11.so.6", EntryPoint = "XSync", ExactSpelling = true)]
|
||||
static extern int __PInvoke(IntPtr __display_native, int __discard_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, uint width, uint height, uint borderWidth, ulong border, ulong background);
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public unsafe static IntPtr XCreateWindow(IntPtr display, IntPtr parent, int x, int y, uint width, uint height, uint borderWidth, int depth, uint windowClass, IntPtr visual, ulong valueMask, ref XSetWindowAttributes attributes)
|
||||
{
|
||||
IntPtr result;
|
||||
fixed (XSetWindowAttributes* _attributes_native = &attributes)
|
||||
{
|
||||
result = __PInvoke(display, parent, x, y, width, height, borderWidth, depth, windowClass, visual, valueMask, _attributes_native);
|
||||
}
|
||||
return result;
|
||||
[DllImport("libX11.so.6", EntryPoint = "XCreateWindow", ExactSpelling = true)]
|
||||
static extern unsafe IntPtr __PInvoke(IntPtr __display_native, IntPtr __parent_native, int __x_native, int __y_native, uint __width_native, uint __height_native, uint __borderWidth_native, int __depth_native, uint __windowClass_native, IntPtr __visual_native, ulong __valueMask_native, XSetWindowAttributes* __attributes_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XDestroyWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XMapWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XUnmapWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XMoveWindow(IntPtr display, IntPtr window, int x, int y);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XResizeWindow(IntPtr display, IntPtr window, uint width, uint height);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, uint width, uint height);
|
||||
|
||||
[LibraryImport("libX11.so.6", StringMarshalling = StringMarshalling.Utf8)]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public unsafe static int XStoreName(IntPtr display, IntPtr window, string windowName)
|
||||
{
|
||||
byte* ptr = default(byte*);
|
||||
int num = 0;
|
||||
Utf8StringMarshaller.ManagedToUnmanagedIn managedToUnmanagedIn = default(Utf8StringMarshaller.ManagedToUnmanagedIn);
|
||||
try
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[Utf8StringMarshaller.ManagedToUnmanagedIn.BufferSize];
|
||||
managedToUnmanagedIn.FromManaged(windowName, buffer);
|
||||
ptr = managedToUnmanagedIn.ToUnmanaged();
|
||||
return __PInvoke(display, window, ptr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
managedToUnmanagedIn.Free();
|
||||
}
|
||||
[DllImport("libX11.so.6", EntryPoint = "XStoreName", ExactSpelling = true)]
|
||||
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, byte* __windowName_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XRaiseWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XLowerWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XSelectInput(IntPtr display, IntPtr window, long eventMask);
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public unsafe static int XNextEvent(IntPtr display, out XEvent eventReturn)
|
||||
{
|
||||
eventReturn = default(XEvent);
|
||||
int result;
|
||||
fixed (XEvent* _eventReturn_native = &eventReturn)
|
||||
{
|
||||
result = __PInvoke(display, _eventReturn_native);
|
||||
}
|
||||
return result;
|
||||
[DllImport("libX11.so.6", EntryPoint = "XNextEvent", ExactSpelling = true)]
|
||||
static extern unsafe int __PInvoke(IntPtr __display_native, XEvent* __eventReturn_native);
|
||||
}
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public unsafe static int XPeekEvent(IntPtr display, out XEvent eventReturn)
|
||||
{
|
||||
eventReturn = default(XEvent);
|
||||
int result;
|
||||
fixed (XEvent* _eventReturn_native = &eventReturn)
|
||||
{
|
||||
result = __PInvoke(display, _eventReturn_native);
|
||||
}
|
||||
return result;
|
||||
[DllImport("libX11.so.6", EntryPoint = "XPeekEvent", ExactSpelling = true)]
|
||||
static extern unsafe int __PInvoke(IntPtr __display_native, XEvent* __eventReturn_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XPending(IntPtr display);
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public unsafe static bool XCheckTypedWindowEvent(IntPtr display, IntPtr window, int eventType, out XEvent eventReturn)
|
||||
{
|
||||
eventReturn = default(XEvent);
|
||||
int num;
|
||||
fixed (XEvent* _eventReturn_native = &eventReturn)
|
||||
{
|
||||
num = __PInvoke(display, window, eventType, _eventReturn_native);
|
||||
}
|
||||
return num != 0;
|
||||
[DllImport("libX11.so.6", EntryPoint = "XCheckTypedWindowEvent", ExactSpelling = true)]
|
||||
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, int __eventType_native, XEvent* __eventReturn_native);
|
||||
}
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public unsafe static int XSendEvent(IntPtr display, IntPtr window, [MarshalAs(UnmanagedType.Bool)] bool propagate, long eventMask, ref XEvent eventSend)
|
||||
{
|
||||
int _propagate_native = (propagate ? 1 : 0);
|
||||
int result;
|
||||
fixed (XEvent* _eventSend_native = &eventSend)
|
||||
{
|
||||
result = __PInvoke(display, window, _propagate_native, eventMask, _eventSend_native);
|
||||
}
|
||||
return result;
|
||||
[DllImport("libX11.so.6", EntryPoint = "XSendEvent", ExactSpelling = true)]
|
||||
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, int __propagate_native, long __eventMask_native, XEvent* __eventSend_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern ulong XKeycodeToKeysym(IntPtr display, int keycode, int index);
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public unsafe static int XLookupString(ref XKeyEvent keyEvent, IntPtr bufferReturn, int bytesBuffer, out ulong keysymReturn, IntPtr statusInOut)
|
||||
{
|
||||
keysymReturn = 0uL;
|
||||
int result;
|
||||
fixed (ulong* _keysymReturn_native = &keysymReturn)
|
||||
{
|
||||
fixed (XKeyEvent* _keyEvent_native = &keyEvent)
|
||||
{
|
||||
result = __PInvoke(_keyEvent_native, bufferReturn, bytesBuffer, _keysymReturn_native, statusInOut);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
[DllImport("libX11.so.6", EntryPoint = "XLookupString", ExactSpelling = true)]
|
||||
static extern unsafe int __PInvoke(XKeyEvent* __keyEvent_native, IntPtr __bufferReturn_native, int __bytesBuffer_native, ulong* __keysymReturn_native, IntPtr __statusInOut_native);
|
||||
}
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public static int XGrabKeyboard(IntPtr display, IntPtr grabWindow, [MarshalAs(UnmanagedType.Bool)] bool ownerEvents, int pointerMode, int keyboardMode, ulong time)
|
||||
{
|
||||
int _ownerEvents_native = (ownerEvents ? 1 : 0);
|
||||
return __PInvoke(display, grabWindow, _ownerEvents_native, pointerMode, keyboardMode, time);
|
||||
[DllImport("libX11.so.6", EntryPoint = "XGrabKeyboard", ExactSpelling = true)]
|
||||
static extern int __PInvoke(IntPtr __display_native, IntPtr __grabWindow_native, int __ownerEvents_native, int __pointerMode_native, int __keyboardMode_native, ulong __time_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XUngrabKeyboard(IntPtr display, ulong time);
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public static int XGrabPointer(IntPtr display, IntPtr grabWindow, [MarshalAs(UnmanagedType.Bool)] bool ownerEvents, uint eventMask, int pointerMode, int keyboardMode, IntPtr confineTo, IntPtr cursor, ulong time)
|
||||
{
|
||||
int _ownerEvents_native = (ownerEvents ? 1 : 0);
|
||||
return __PInvoke(display, grabWindow, _ownerEvents_native, eventMask, pointerMode, keyboardMode, confineTo, cursor, time);
|
||||
[DllImport("libX11.so.6", EntryPoint = "XGrabPointer", ExactSpelling = true)]
|
||||
static extern int __PInvoke(IntPtr __display_native, IntPtr __grabWindow_native, int __ownerEvents_native, uint __eventMask_native, int __pointerMode_native, int __keyboardMode_native, IntPtr __confineTo_native, IntPtr __cursor_native, ulong __time_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XUngrabPointer(IntPtr display, ulong time);
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public unsafe static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr rootReturn, out IntPtr childReturn, out int rootX, out int rootY, out int winX, out int winY, out uint maskReturn)
|
||||
{
|
||||
rootReturn = (IntPtr)0;
|
||||
childReturn = (IntPtr)0;
|
||||
rootX = 0;
|
||||
rootY = 0;
|
||||
winX = 0;
|
||||
winY = 0;
|
||||
maskReturn = 0u;
|
||||
int num;
|
||||
fixed (uint* _maskReturn_native = &maskReturn)
|
||||
{
|
||||
fixed (int* _winY_native = &winY)
|
||||
{
|
||||
fixed (int* _winX_native = &winX)
|
||||
{
|
||||
fixed (int* _rootY_native = &rootY)
|
||||
{
|
||||
fixed (int* _rootX_native = &rootX)
|
||||
{
|
||||
fixed (IntPtr* _childReturn_native = &childReturn)
|
||||
{
|
||||
fixed (IntPtr* _rootReturn_native = &rootReturn)
|
||||
{
|
||||
num = __PInvoke(display, window, _rootReturn_native, _childReturn_native, _rootX_native, _rootY_native, _winX_native, _winY_native, _maskReturn_native);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return num != 0;
|
||||
[DllImport("libX11.so.6", EntryPoint = "XQueryPointer", ExactSpelling = true)]
|
||||
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, IntPtr* __rootReturn_native, IntPtr* __childReturn_native, int* __rootX_native, int* __rootY_native, int* __winX_native, int* __winY_native, uint* __maskReturn_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XWarpPointer(IntPtr display, IntPtr srcWindow, IntPtr destWindow, int srcX, int srcY, uint srcWidth, uint srcHeight, int destX, int destY);
|
||||
|
||||
[LibraryImport("libX11.so.6", StringMarshalling = StringMarshalling.Utf8)]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public unsafe static IntPtr XInternAtom(IntPtr display, string atomName, [MarshalAs(UnmanagedType.Bool)] bool onlyIfExists)
|
||||
{
|
||||
byte* ptr = default(byte*);
|
||||
int num = 0;
|
||||
nint num2 = 0;
|
||||
Utf8StringMarshaller.ManagedToUnmanagedIn managedToUnmanagedIn = default(Utf8StringMarshaller.ManagedToUnmanagedIn);
|
||||
try
|
||||
{
|
||||
num = (onlyIfExists ? 1 : 0);
|
||||
Span<byte> buffer = stackalloc byte[Utf8StringMarshaller.ManagedToUnmanagedIn.BufferSize];
|
||||
managedToUnmanagedIn.FromManaged(atomName, buffer);
|
||||
ptr = managedToUnmanagedIn.ToUnmanaged();
|
||||
return __PInvoke(display, ptr, num);
|
||||
}
|
||||
finally
|
||||
{
|
||||
managedToUnmanagedIn.Free();
|
||||
}
|
||||
[DllImport("libX11.so.6", EntryPoint = "XInternAtom", ExactSpelling = true)]
|
||||
static extern unsafe IntPtr __PInvoke(IntPtr __display_native, byte* __atomName_native, int __onlyIfExists_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, int mode, IntPtr data, int nelements);
|
||||
|
||||
[LibraryImport("libX11.so.6")]
|
||||
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
|
||||
[SkipLocalsInit]
|
||||
public unsafe static int XGetWindowProperty(IntPtr display, IntPtr window, IntPtr property, long longOffset, long longLength, [MarshalAs(UnmanagedType.Bool)] bool delete, IntPtr reqType, out IntPtr actualTypeReturn, out int actualFormatReturn, out IntPtr nitemsReturn, out IntPtr bytesAfterReturn, out IntPtr propReturn)
|
||||
{
|
||||
actualTypeReturn = (IntPtr)0;
|
||||
actualFormatReturn = 0;
|
||||
nitemsReturn = (IntPtr)0;
|
||||
bytesAfterReturn = (IntPtr)0;
|
||||
propReturn = (IntPtr)0;
|
||||
int _delete_native = (delete ? 1 : 0);
|
||||
int result;
|
||||
fixed (IntPtr* _propReturn_native = &propReturn)
|
||||
{
|
||||
fixed (IntPtr* _bytesAfterReturn_native = &bytesAfterReturn)
|
||||
{
|
||||
fixed (IntPtr* _nitemsReturn_native = &nitemsReturn)
|
||||
{
|
||||
fixed (int* _actualFormatReturn_native = &actualFormatReturn)
|
||||
{
|
||||
fixed (IntPtr* _actualTypeReturn_native = &actualTypeReturn)
|
||||
{
|
||||
result = __PInvoke(display, window, property, longOffset, longLength, _delete_native, reqType, _actualTypeReturn_native, _actualFormatReturn_native, _nitemsReturn_native, _bytesAfterReturn_native, _propReturn_native);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
[DllImport("libX11.so.6", EntryPoint = "XGetWindowProperty", ExactSpelling = true)]
|
||||
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, IntPtr __property_native, long __longOffset_native, long __longLength_native, int __delete_native, IntPtr __reqType_native, IntPtr* __actualTypeReturn_native, int* __actualFormatReturn_native, IntPtr* __nitemsReturn_native, IntPtr* __bytesAfterReturn_native, IntPtr* __propReturn_native);
|
||||
}
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, ulong time);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, ulong time);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XFree(IntPtr data);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XCreateGC(IntPtr display, IntPtr drawable, ulong valueMask, IntPtr values);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XFreeGC(IntPtr display, IntPtr gc);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int srcX, int srcY, uint width, uint height, int destX, int destY);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XCreateFontCursor(IntPtr display, uint shape);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XFreeCursor(IntPtr display, IntPtr cursor);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XUndefineCursor(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XConnectionNumber(IntPtr display);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XCreateImage(IntPtr display, IntPtr visual, uint depth, int format, int offset, IntPtr data, uint width, uint height, int bitmapPad, int bytesPerLine);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XPutImage(IntPtr display, IntPtr drawable, IntPtr gc, IntPtr image, int srcX, int srcY, int destX, int destY, uint width, uint height);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern int XDestroyImage(IntPtr image);
|
||||
|
||||
[DllImport("libX11.so.6", ExactSpelling = true)]
|
||||
[LibraryImport("libX11.so.6")]
|
||||
public static extern IntPtr XDefaultGC(IntPtr display, int screen);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XButtonEvent
|
||||
{
|
||||
public int Type;
|
||||
|
||||
public ulong Serial;
|
||||
|
||||
public int SendEvent;
|
||||
|
||||
public IntPtr Display;
|
||||
|
||||
public IntPtr Window;
|
||||
|
||||
public IntPtr Root;
|
||||
|
||||
public IntPtr Subwindow;
|
||||
|
||||
public ulong Time;
|
||||
|
||||
public int X;
|
||||
|
||||
public int Y;
|
||||
|
||||
public int XRoot;
|
||||
|
||||
public int YRoot;
|
||||
|
||||
public uint State;
|
||||
|
||||
public uint Button;
|
||||
|
||||
public int SameScreen;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XClientMessageEvent
|
||||
{
|
||||
public int Type;
|
||||
|
||||
public ulong Serial;
|
||||
|
||||
public int SendEvent;
|
||||
|
||||
public IntPtr Display;
|
||||
|
||||
public IntPtr Window;
|
||||
|
||||
public IntPtr MessageType;
|
||||
|
||||
public int Format;
|
||||
|
||||
public ClientMessageData Data;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XConfigureEvent
|
||||
{
|
||||
public int Type;
|
||||
|
||||
public ulong Serial;
|
||||
|
||||
public int SendEvent;
|
||||
|
||||
public IntPtr Display;
|
||||
|
||||
public IntPtr Event;
|
||||
|
||||
public IntPtr Window;
|
||||
|
||||
public int X;
|
||||
|
||||
public int Y;
|
||||
|
||||
public int Width;
|
||||
|
||||
public int Height;
|
||||
|
||||
public int BorderWidth;
|
||||
|
||||
public IntPtr Above;
|
||||
|
||||
public int OverrideRedirect;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XCrossingEvent
|
||||
{
|
||||
public int Type;
|
||||
|
||||
public ulong Serial;
|
||||
|
||||
public int SendEvent;
|
||||
|
||||
public IntPtr Display;
|
||||
|
||||
public IntPtr Window;
|
||||
|
||||
public IntPtr Root;
|
||||
|
||||
public IntPtr Subwindow;
|
||||
|
||||
public ulong Time;
|
||||
|
||||
public int X;
|
||||
|
||||
public int Y;
|
||||
|
||||
public int XRoot;
|
||||
|
||||
public int YRoot;
|
||||
|
||||
public int Mode;
|
||||
|
||||
public int Detail;
|
||||
|
||||
public int SameScreen;
|
||||
|
||||
public int Focus;
|
||||
|
||||
public uint State;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public static class XCursorShape
|
||||
{
|
||||
public const uint XC_left_ptr = 68u;
|
||||
|
||||
public const uint XC_hand2 = 60u;
|
||||
|
||||
public const uint XC_xterm = 152u;
|
||||
|
||||
public const uint XC_watch = 150u;
|
||||
|
||||
public const uint XC_crosshair = 34u;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = 192)]
|
||||
public struct XEvent
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public int Type;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public XKeyEvent KeyEvent;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public XButtonEvent ButtonEvent;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public XMotionEvent MotionEvent;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public XConfigureEvent ConfigureEvent;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public XExposeEvent ExposeEvent;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public XClientMessageEvent ClientMessageEvent;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public XCrossingEvent CrossingEvent;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public XFocusChangeEvent FocusChangeEvent;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public static class XEventMask
|
||||
{
|
||||
public const long KeyPressMask = 1L;
|
||||
|
||||
public const long KeyReleaseMask = 2L;
|
||||
|
||||
public const long ButtonPressMask = 4L;
|
||||
|
||||
public const long ButtonReleaseMask = 8L;
|
||||
|
||||
public const long EnterWindowMask = 16L;
|
||||
|
||||
public const long LeaveWindowMask = 32L;
|
||||
|
||||
public const long PointerMotionMask = 64L;
|
||||
|
||||
public const long ExposureMask = 32768L;
|
||||
|
||||
public const long StructureNotifyMask = 131072L;
|
||||
|
||||
public const long FocusChangeMask = 2097152L;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public static class XEventType
|
||||
{
|
||||
public const int KeyPress = 2;
|
||||
|
||||
public const int KeyRelease = 3;
|
||||
|
||||
public const int ButtonPress = 4;
|
||||
|
||||
public const int ButtonRelease = 5;
|
||||
|
||||
public const int MotionNotify = 6;
|
||||
|
||||
public const int EnterNotify = 7;
|
||||
|
||||
public const int LeaveNotify = 8;
|
||||
|
||||
public const int FocusIn = 9;
|
||||
|
||||
public const int FocusOut = 10;
|
||||
|
||||
public const int Expose = 12;
|
||||
|
||||
public const int ConfigureNotify = 22;
|
||||
|
||||
public const int ClientMessage = 33;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XExposeEvent
|
||||
{
|
||||
public int Type;
|
||||
|
||||
public ulong Serial;
|
||||
|
||||
public int SendEvent;
|
||||
|
||||
public IntPtr Display;
|
||||
|
||||
public IntPtr Window;
|
||||
|
||||
public int X;
|
||||
|
||||
public int Y;
|
||||
|
||||
public int Width;
|
||||
|
||||
public int Height;
|
||||
|
||||
public int Count;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XFocusChangeEvent
|
||||
{
|
||||
public int Type;
|
||||
|
||||
public ulong Serial;
|
||||
|
||||
public int SendEvent;
|
||||
|
||||
public IntPtr Display;
|
||||
|
||||
public IntPtr Window;
|
||||
|
||||
public int Mode;
|
||||
|
||||
public int Detail;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XKeyEvent
|
||||
{
|
||||
public int Type;
|
||||
|
||||
public ulong Serial;
|
||||
|
||||
public int SendEvent;
|
||||
|
||||
public IntPtr Display;
|
||||
|
||||
public IntPtr Window;
|
||||
|
||||
public IntPtr Root;
|
||||
|
||||
public IntPtr Subwindow;
|
||||
|
||||
public ulong Time;
|
||||
|
||||
public int X;
|
||||
|
||||
public int Y;
|
||||
|
||||
public int XRoot;
|
||||
|
||||
public int YRoot;
|
||||
|
||||
public uint State;
|
||||
|
||||
public uint Keycode;
|
||||
|
||||
public int SameScreen;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XMotionEvent
|
||||
{
|
||||
public int Type;
|
||||
|
||||
public ulong Serial;
|
||||
|
||||
public int SendEvent;
|
||||
|
||||
public IntPtr Display;
|
||||
|
||||
public IntPtr Window;
|
||||
|
||||
public IntPtr Root;
|
||||
|
||||
public IntPtr Subwindow;
|
||||
|
||||
public ulong Time;
|
||||
|
||||
public int X;
|
||||
|
||||
public int Y;
|
||||
|
||||
public int XRoot;
|
||||
|
||||
public int YRoot;
|
||||
|
||||
public uint State;
|
||||
|
||||
public byte IsHint;
|
||||
|
||||
public int SameScreen;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public struct XSetWindowAttributes
|
||||
{
|
||||
public IntPtr BackgroundPixmap;
|
||||
|
||||
public ulong BackgroundPixel;
|
||||
|
||||
public IntPtr BorderPixmap;
|
||||
|
||||
public ulong BorderPixel;
|
||||
|
||||
public int BitGravity;
|
||||
|
||||
public int WinGravity;
|
||||
|
||||
public int BackingStore;
|
||||
|
||||
public ulong BackingPlanes;
|
||||
|
||||
public ulong BackingPixel;
|
||||
|
||||
public int SaveUnder;
|
||||
|
||||
public long EventMask;
|
||||
|
||||
public long DoNotPropagateMask;
|
||||
|
||||
public int OverrideRedirect;
|
||||
|
||||
public IntPtr Colormap;
|
||||
|
||||
public IntPtr Cursor;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||
|
||||
public static class XWindowClass
|
||||
{
|
||||
public const uint InputOutput = 1u;
|
||||
|
||||
public const uint InputOnly = 2u;
|
||||
}
|
||||
1435
LinuxApplication.cs
1435
LinuxApplication.cs
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux;
|
||||
|
||||
public class LinuxApplicationOptions
|
||||
{
|
||||
public string? Title { get; set; } = "MAUI Application";
|
||||
|
||||
public int Width { get; set; } = 800;
|
||||
|
||||
public int Height { get; set; } = 600;
|
||||
|
||||
public bool UseHardwareAcceleration { get; set; } = true;
|
||||
|
||||
public DisplayServerType DisplayServer { get; set; }
|
||||
|
||||
public bool ForceDemo { get; set; }
|
||||
|
||||
public string? IconPath { get; set; }
|
||||
|
||||
public bool UseGtk { get; set; }
|
||||
}
|
||||
@@ -46,6 +46,9 @@
|
||||
<!-- HarfBuzz for advanced text shaping -->
|
||||
<PackageReference Include="HarfBuzzSharp" Version="7.3.0.3" />
|
||||
<PackageReference Include="HarfBuzzSharp.NativeAssets.Linux" Version="7.3.0.3" />
|
||||
|
||||
<!-- SVG support for icon loading -->
|
||||
<PackageReference Include="Svg.Skia" Version="2.0.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Include README and icon in package -->
|
||||
|
||||
@@ -1,254 +1,232 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Manages dirty rectangles for optimized rendering.
|
||||
/// Only redraws areas that have been invalidated.
|
||||
/// </summary>
|
||||
public class DirtyRectManager
|
||||
{
|
||||
private readonly List<SKRect> _dirtyRects = new List<SKRect>();
|
||||
private readonly List<SKRect> _dirtyRects = new();
|
||||
private readonly object _lock = new();
|
||||
private bool _fullRedrawNeeded = true;
|
||||
private SKRect _bounds;
|
||||
private int _maxDirtyRects = 10;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of dirty rectangles to track before
|
||||
/// falling back to a full redraw.
|
||||
/// </summary>
|
||||
public int MaxDirtyRects
|
||||
{
|
||||
get => _maxDirtyRects;
|
||||
set => _maxDirtyRects = Math.Max(1, value);
|
||||
}
|
||||
|
||||
private bool _fullRedrawNeeded = true;
|
||||
/// <summary>
|
||||
/// Gets whether a full redraw is needed.
|
||||
/// </summary>
|
||||
public bool NeedsFullRedraw => _fullRedrawNeeded;
|
||||
|
||||
private SKRect _bounds;
|
||||
/// <summary>
|
||||
/// Gets the current dirty rectangles.
|
||||
/// </summary>
|
||||
public IReadOnlyList<SKRect> DirtyRects
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _dirtyRects.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int _maxDirtyRects = 10;
|
||||
/// <summary>
|
||||
/// Gets whether there are any dirty regions.
|
||||
/// </summary>
|
||||
public bool HasDirtyRegions
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _fullRedrawNeeded || _dirtyRects.Count > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxDirtyRects
|
||||
{
|
||||
get
|
||||
{
|
||||
return _maxDirtyRects;
|
||||
}
|
||||
set
|
||||
{
|
||||
_maxDirtyRects = Math.Max(1, value);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the rendering bounds.
|
||||
/// </summary>
|
||||
public void SetBounds(SKRect bounds)
|
||||
{
|
||||
if (_bounds != bounds)
|
||||
{
|
||||
_bounds = bounds;
|
||||
InvalidateAll();
|
||||
}
|
||||
}
|
||||
|
||||
public bool NeedsFullRedraw => _fullRedrawNeeded;
|
||||
/// <summary>
|
||||
/// Invalidates a specific region.
|
||||
/// </summary>
|
||||
public void Invalidate(SKRect rect)
|
||||
{
|
||||
if (rect.IsEmpty) return;
|
||||
|
||||
public IReadOnlyList<SKRect> DirtyRects
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _dirtyRects.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded) return;
|
||||
|
||||
public bool HasDirtyRegions
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _fullRedrawNeeded || _dirtyRects.Count > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clamp to bounds
|
||||
rect = SKRect.Intersect(rect, _bounds);
|
||||
if (rect.IsEmpty) return;
|
||||
|
||||
public void SetBounds(SKRect bounds)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: 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_0010: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (_bounds != bounds)
|
||||
{
|
||||
_bounds = bounds;
|
||||
InvalidateAll();
|
||||
}
|
||||
}
|
||||
// Try to merge with existing dirty rects
|
||||
for (int i = 0; i < _dirtyRects.Count; i++)
|
||||
{
|
||||
if (_dirtyRects[i].Contains(rect))
|
||||
{
|
||||
// Already covered
|
||||
return;
|
||||
}
|
||||
|
||||
public void Invalidate(SKRect rect)
|
||||
{
|
||||
//IL_0028: 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_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_0052: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0057: 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_014f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00e4: 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_0121: 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)
|
||||
if (((SKRect)(ref rect)).IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
rect = SKRect.Intersect(rect, _bounds);
|
||||
if (((SKRect)(ref rect)).IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < _dirtyRects.Count; i++)
|
||||
{
|
||||
SKRect val = _dirtyRects[i];
|
||||
if (((SKRect)(ref val)).Contains(rect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (((SKRect)(ref rect)).Contains(_dirtyRects[i]))
|
||||
{
|
||||
_dirtyRects[i] = rect;
|
||||
MergeDirtyRects();
|
||||
return;
|
||||
}
|
||||
SKRect val2 = SKRect.Intersect(_dirtyRects[i], rect);
|
||||
if (!((SKRect)(ref val2)).IsEmpty)
|
||||
{
|
||||
float num = ((SKRect)(ref val2)).Width * ((SKRect)(ref val2)).Height;
|
||||
val = _dirtyRects[i];
|
||||
float width = ((SKRect)(ref val)).Width;
|
||||
val = _dirtyRects[i];
|
||||
float num2 = Math.Min(width * ((SKRect)(ref val)).Height, ((SKRect)(ref rect)).Width * ((SKRect)(ref rect)).Height);
|
||||
if (num > num2 * 0.5f)
|
||||
{
|
||||
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], rect);
|
||||
MergeDirtyRects();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_dirtyRects.Add(rect);
|
||||
if (_dirtyRects.Count > _maxDirtyRects)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rect.Contains(_dirtyRects[i]))
|
||||
{
|
||||
// New rect covers existing
|
||||
_dirtyRects[i] = rect;
|
||||
MergeDirtyRects();
|
||||
return;
|
||||
}
|
||||
|
||||
public void InvalidateAll()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
// Check if they overlap significantly (50% overlap)
|
||||
var intersection = SKRect.Intersect(_dirtyRects[i], rect);
|
||||
if (!intersection.IsEmpty)
|
||||
{
|
||||
float intersectArea = intersection.Width * intersection.Height;
|
||||
float smallerArea = Math.Min(
|
||||
_dirtyRects[i].Width * _dirtyRects[i].Height,
|
||||
rect.Width * rect.Height);
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_fullRedrawNeeded = false;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
if (intersectArea > smallerArea * 0.5f)
|
||||
{
|
||||
// Merge the rectangles
|
||||
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], rect);
|
||||
MergeDirtyRects();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SKRect GetCombinedDirtyRect()
|
||||
{
|
||||
//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_0078: 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_003b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004a: 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)
|
||||
//IL_006a: 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)
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
SKRect val = _dirtyRects[0];
|
||||
for (int i = 1; i < _dirtyRects.Count; i++)
|
||||
{
|
||||
val = SKRect.Union(val, _dirtyRects[i]);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
// Add as new dirty rect
|
||||
_dirtyRects.Add(rect);
|
||||
|
||||
public void ApplyClipping(SKCanvas canvas)
|
||||
{
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002e: Expected O, but got Unknown
|
||||
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SKPath val = new SKPath();
|
||||
try
|
||||
{
|
||||
foreach (SKRect dirtyRect in _dirtyRects)
|
||||
{
|
||||
val.AddRect(dirtyRect, (SKPathDirection)0);
|
||||
}
|
||||
canvas.ClipPath(val, (SKClipOperation)1, false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val)?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if we have too many dirty rects
|
||||
if (_dirtyRects.Count > _maxDirtyRects)
|
||||
{
|
||||
// Fall back to full redraw
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MergeDirtyRects()
|
||||
{
|
||||
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001f: 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_0029: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
|
||||
bool flag;
|
||||
do
|
||||
{
|
||||
flag = false;
|
||||
for (int i = 0; i < _dirtyRects.Count - 1; i++)
|
||||
{
|
||||
for (int j = i + 1; j < _dirtyRects.Count; j++)
|
||||
{
|
||||
SKRect val = SKRect.Intersect(_dirtyRects[i], _dirtyRects[j]);
|
||||
if (!((SKRect)(ref val)).IsEmpty)
|
||||
{
|
||||
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], _dirtyRects[j]);
|
||||
_dirtyRects.RemoveAt(j);
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (flag);
|
||||
}
|
||||
/// <summary>
|
||||
/// Invalidates the entire rendering area.
|
||||
/// </summary>
|
||||
public void InvalidateAll()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all dirty regions after rendering.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_fullRedrawNeeded = false;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the combined dirty region as a single rectangle.
|
||||
/// </summary>
|
||||
public SKRect GetCombinedDirtyRect()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
var combined = _dirtyRects[0];
|
||||
for (int i = 1; i < _dirtyRects.Count; i++)
|
||||
{
|
||||
combined = SKRect.Union(combined, _dirtyRects[i]);
|
||||
}
|
||||
return combined;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies dirty region clipping to a canvas.
|
||||
/// </summary>
|
||||
public void ApplyClipping(SKCanvas canvas)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
|
||||
{
|
||||
// No clipping needed for full redraw
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a path from all dirty rects
|
||||
using var path = new SKPath();
|
||||
foreach (var rect in _dirtyRects)
|
||||
{
|
||||
path.AddRect(rect);
|
||||
}
|
||||
|
||||
canvas.ClipPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
private void MergeDirtyRects()
|
||||
{
|
||||
// Simple merge pass - could be optimized
|
||||
bool merged;
|
||||
do
|
||||
{
|
||||
merged = false;
|
||||
for (int i = 0; i < _dirtyRects.Count - 1; i++)
|
||||
{
|
||||
for (int j = i + 1; j < _dirtyRects.Count; j++)
|
||||
{
|
||||
var intersection = SKRect.Intersect(_dirtyRects[i], _dirtyRects[j]);
|
||||
if (!intersection.IsEmpty)
|
||||
{
|
||||
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], _dirtyRects[j]);
|
||||
_dirtyRects.RemoveAt(j);
|
||||
merged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (merged) break;
|
||||
}
|
||||
} while (merged);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Maui.Platform.Linux.Window;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
public class GpuRenderingEngine : IDisposable
|
||||
{
|
||||
private readonly X11Window _window;
|
||||
|
||||
private GRContext? _grContext;
|
||||
|
||||
private GRBackendRenderTarget? _renderTarget;
|
||||
|
||||
private SKSurface? _surface;
|
||||
|
||||
private SKCanvas? _canvas;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
private bool _gpuAvailable;
|
||||
|
||||
private int _width;
|
||||
|
||||
private int _height;
|
||||
|
||||
private SKBitmap? _softwareBitmap;
|
||||
|
||||
private SKCanvas? _softwareCanvas;
|
||||
|
||||
private readonly List<SKRect> _dirtyRegions = new List<SKRect>();
|
||||
|
||||
private readonly object _dirtyLock = new object();
|
||||
|
||||
private bool _fullRedrawNeeded = true;
|
||||
|
||||
private const int MaxDirtyRegions = 32;
|
||||
|
||||
public bool IsGpuAccelerated
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_gpuAvailable)
|
||||
{
|
||||
return _grContext != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public string BackendName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsGpuAccelerated)
|
||||
{
|
||||
return "Software";
|
||||
}
|
||||
return "OpenGL";
|
||||
}
|
||||
}
|
||||
|
||||
public int Width => _width;
|
||||
|
||||
public int Height => _height;
|
||||
|
||||
public GpuRenderingEngine(X11Window window)
|
||||
{
|
||||
_window = window;
|
||||
_width = window.Width;
|
||||
_height = window.Height;
|
||||
_gpuAvailable = TryInitializeGpu();
|
||||
if (!_gpuAvailable)
|
||||
{
|
||||
Console.WriteLine("[GpuRenderingEngine] GPU not available, using software rendering");
|
||||
InitializeSoftwareRendering();
|
||||
}
|
||||
_window.Resized += OnWindowResized;
|
||||
_window.Exposed += OnWindowExposed;
|
||||
}
|
||||
|
||||
private bool TryInitializeGpu()
|
||||
{
|
||||
try
|
||||
{
|
||||
GRGlInterface val = GRGlInterface.Create();
|
||||
if (val == null)
|
||||
{
|
||||
Console.WriteLine("[GpuRenderingEngine] Failed to create GL interface");
|
||||
return false;
|
||||
}
|
||||
_grContext = GRContext.CreateGl(val);
|
||||
if (_grContext == null)
|
||||
{
|
||||
Console.WriteLine("[GpuRenderingEngine] Failed to create GR context");
|
||||
((SKNativeObject)val).Dispose();
|
||||
return false;
|
||||
}
|
||||
CreateGpuSurface();
|
||||
Console.WriteLine("[GpuRenderingEngine] GPU acceleration enabled");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("[GpuRenderingEngine] GPU initialization failed: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateGpuSurface()
|
||||
{
|
||||
//IL_0058: 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)
|
||||
//IL_0063: Expected O, but got Unknown
|
||||
if (_grContext != null)
|
||||
{
|
||||
GRBackendRenderTarget? renderTarget = _renderTarget;
|
||||
if (renderTarget != null)
|
||||
{
|
||||
((SKNativeObject)renderTarget).Dispose();
|
||||
}
|
||||
SKSurface? surface = _surface;
|
||||
if (surface != null)
|
||||
{
|
||||
((SKNativeObject)surface).Dispose();
|
||||
}
|
||||
int num = Math.Max(1, _width);
|
||||
int num2 = Math.Max(1, _height);
|
||||
GRGlFramebufferInfo val = default(GRGlFramebufferInfo);
|
||||
((GRGlFramebufferInfo)(ref val))._002Ector(0u, SkiaExtensions.ToGlSizedFormat((SKColorType)4));
|
||||
_renderTarget = new GRBackendRenderTarget(num, num2, 0, 8, val);
|
||||
_surface = SKSurface.Create(_grContext, _renderTarget, (GRSurfaceOrigin)1, (SKColorType)4);
|
||||
if (_surface == null)
|
||||
{
|
||||
Console.WriteLine("[GpuRenderingEngine] Failed to create GPU surface, falling back to software");
|
||||
_gpuAvailable = false;
|
||||
InitializeSoftwareRendering();
|
||||
}
|
||||
else
|
||||
{
|
||||
_canvas = _surface.Canvas;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeSoftwareRendering()
|
||||
{
|
||||
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0053: Expected O, but got Unknown
|
||||
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0064: Expected O, but got Unknown
|
||||
int num = Math.Max(1, _width);
|
||||
int num2 = Math.Max(1, _height);
|
||||
SKBitmap? softwareBitmap = _softwareBitmap;
|
||||
if (softwareBitmap != null)
|
||||
{
|
||||
((SKNativeObject)softwareBitmap).Dispose();
|
||||
}
|
||||
SKCanvas? softwareCanvas = _softwareCanvas;
|
||||
if (softwareCanvas != null)
|
||||
{
|
||||
((SKNativeObject)softwareCanvas).Dispose();
|
||||
}
|
||||
SKImageInfo val = default(SKImageInfo);
|
||||
((SKImageInfo)(ref val))._002Ector(num, num2, (SKColorType)6, (SKAlphaType)2);
|
||||
_softwareBitmap = new SKBitmap(val);
|
||||
_softwareCanvas = new SKCanvas(_softwareBitmap);
|
||||
_canvas = _softwareCanvas;
|
||||
}
|
||||
|
||||
private void OnWindowResized(object? sender, (int Width, int Height) size)
|
||||
{
|
||||
(_width, _height) = size;
|
||||
if (_gpuAvailable && _grContext != null)
|
||||
{
|
||||
CreateGpuSurface();
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeSoftwareRendering();
|
||||
}
|
||||
_fullRedrawNeeded = true;
|
||||
}
|
||||
|
||||
private void OnWindowExposed(object? sender, EventArgs e)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
}
|
||||
|
||||
public void InvalidateRegion(SKRect region)
|
||||
{
|
||||
//IL_0026: 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_0049: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (((SKRect)(ref region)).IsEmpty || ((SKRect)(ref region)).Width <= 0f || ((SKRect)(ref region)).Height <= 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
region = SKRect.Intersect(region, new SKRect(0f, 0f, (float)Width, (float)Height));
|
||||
if (((SKRect)(ref region)).IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (_dirtyLock)
|
||||
{
|
||||
if (_dirtyRegions.Count >= 32)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRegions.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
_dirtyRegions.Add(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateAll()
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
}
|
||||
|
||||
public void Render(SkiaView rootView)
|
||||
{
|
||||
//IL_001f: 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_003f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (_canvas == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SKSize availableSize = default(SKSize);
|
||||
((SKSize)(ref availableSize))._002Ector((float)Width, (float)Height);
|
||||
rootView.Measure(availableSize);
|
||||
rootView.Arrange(new SKRect(0f, 0f, (float)Width, (float)Height));
|
||||
bool flag;
|
||||
List<SKRect> list;
|
||||
lock (_dirtyLock)
|
||||
{
|
||||
flag = _fullRedrawNeeded || _dirtyRegions.Count == 0;
|
||||
if (flag)
|
||||
{
|
||||
list = new List<SKRect>
|
||||
{
|
||||
new SKRect(0f, 0f, (float)Width, (float)Height)
|
||||
};
|
||||
_dirtyRegions.Clear();
|
||||
_fullRedrawNeeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
list = new List<SKRect>(_dirtyRegions);
|
||||
_dirtyRegions.Clear();
|
||||
}
|
||||
}
|
||||
foreach (SKRect item in list)
|
||||
{
|
||||
_canvas.Save();
|
||||
if (!flag)
|
||||
{
|
||||
_canvas.ClipRect(item, (SKClipOperation)1, false);
|
||||
}
|
||||
_canvas.Clear(SKColors.White);
|
||||
rootView.Draw(_canvas);
|
||||
_canvas.Restore();
|
||||
}
|
||||
SkiaView.DrawPopupOverlays(_canvas);
|
||||
if (LinuxDialogService.HasActiveDialog)
|
||||
{
|
||||
LinuxDialogService.DrawDialogs(_canvas, new SKRect(0f, 0f, (float)Width, (float)Height));
|
||||
}
|
||||
_canvas.Flush();
|
||||
if (_gpuAvailable && _grContext != null)
|
||||
{
|
||||
_grContext.Submit(false);
|
||||
}
|
||||
else if (_softwareBitmap != null)
|
||||
{
|
||||
IntPtr pixels = _softwareBitmap.GetPixels();
|
||||
if (pixels != IntPtr.Zero)
|
||||
{
|
||||
_window.DrawPixels(pixels, Width, Height, _softwareBitmap.RowBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GpuStats GetStats()
|
||||
{
|
||||
if (_grContext == null)
|
||||
{
|
||||
return new GpuStats
|
||||
{
|
||||
IsGpuAccelerated = false
|
||||
};
|
||||
}
|
||||
int num = default(int);
|
||||
long resourceCacheLimitBytes = default(long);
|
||||
_grContext.GetResourceCacheLimits(ref num, ref resourceCacheLimitBytes);
|
||||
return new GpuStats
|
||||
{
|
||||
IsGpuAccelerated = true,
|
||||
MaxTextureSize = 4096,
|
||||
ResourceCacheUsedBytes = 0L,
|
||||
ResourceCacheLimitBytes = resourceCacheLimitBytes
|
||||
};
|
||||
}
|
||||
|
||||
public void PurgeResources()
|
||||
{
|
||||
GRContext? grContext = _grContext;
|
||||
if (grContext != null)
|
||||
{
|
||||
grContext.PurgeResources();
|
||||
}
|
||||
}
|
||||
|
||||
public SKCanvas? GetCanvas()
|
||||
{
|
||||
return _canvas;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (disposing)
|
||||
{
|
||||
_window.Resized -= OnWindowResized;
|
||||
_window.Exposed -= OnWindowExposed;
|
||||
SKSurface? surface = _surface;
|
||||
if (surface != null)
|
||||
{
|
||||
((SKNativeObject)surface).Dispose();
|
||||
}
|
||||
GRBackendRenderTarget? renderTarget = _renderTarget;
|
||||
if (renderTarget != null)
|
||||
{
|
||||
((SKNativeObject)renderTarget).Dispose();
|
||||
}
|
||||
GRContext? grContext = _grContext;
|
||||
if (grContext != null)
|
||||
{
|
||||
((SKNativeObject)grContext).Dispose();
|
||||
}
|
||||
SKBitmap? softwareBitmap = _softwareBitmap;
|
||||
if (softwareBitmap != null)
|
||||
{
|
||||
((SKNativeObject)softwareBitmap).Dispose();
|
||||
}
|
||||
SKCanvas? softwareCanvas = _softwareCanvas;
|
||||
if (softwareCanvas != null)
|
||||
{
|
||||
((SKNativeObject)softwareCanvas).Dispose();
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
public class GpuStats
|
||||
{
|
||||
public bool IsGpuAccelerated { get; init; }
|
||||
|
||||
public int MaxTextureSize { get; init; }
|
||||
|
||||
public long ResourceCacheUsedBytes { get; init; }
|
||||
|
||||
public long ResourceCacheLimitBytes { get; init; }
|
||||
|
||||
public double ResourceCacheUsedMB => (double)ResourceCacheUsedBytes / 1048576.0;
|
||||
|
||||
public double ResourceCacheLimitMB => (double)ResourceCacheLimitBytes / 1048576.0;
|
||||
}
|
||||
@@ -1,455 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Maui.Platform.Linux.Native;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
public sealed class GtkSkiaSurfaceWidget : IDisposable
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate bool DrawCallback(IntPtr widget, IntPtr cairoContext, IntPtr userData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate bool ConfigureCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate bool ButtonEventCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate bool MotionEventCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate bool KeyEventCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate bool ScrollEventCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
|
||||
|
||||
private struct GdkEventButton
|
||||
{
|
||||
public int type;
|
||||
|
||||
public IntPtr window;
|
||||
|
||||
public sbyte send_event;
|
||||
|
||||
public uint time;
|
||||
|
||||
public double x;
|
||||
|
||||
public double y;
|
||||
|
||||
public IntPtr axes;
|
||||
|
||||
public uint state;
|
||||
|
||||
public uint button;
|
||||
}
|
||||
|
||||
private struct GdkEventMotion
|
||||
{
|
||||
public int type;
|
||||
|
||||
public IntPtr window;
|
||||
|
||||
public sbyte send_event;
|
||||
|
||||
public uint time;
|
||||
|
||||
public double x;
|
||||
|
||||
public double y;
|
||||
}
|
||||
|
||||
private struct GdkEventKey
|
||||
{
|
||||
public int type;
|
||||
|
||||
public IntPtr window;
|
||||
|
||||
public sbyte send_event;
|
||||
|
||||
public uint time;
|
||||
|
||||
public uint state;
|
||||
|
||||
public uint keyval;
|
||||
|
||||
public int length;
|
||||
|
||||
public IntPtr str;
|
||||
|
||||
public ushort hardware_keycode;
|
||||
}
|
||||
|
||||
private struct GdkEventScroll
|
||||
{
|
||||
public int type;
|
||||
|
||||
public IntPtr window;
|
||||
|
||||
public sbyte send_event;
|
||||
|
||||
public uint time;
|
||||
|
||||
public double x;
|
||||
|
||||
public double y;
|
||||
|
||||
public uint state;
|
||||
|
||||
public int direction;
|
||||
|
||||
public IntPtr device;
|
||||
|
||||
public double x_root;
|
||||
|
||||
public double y_root;
|
||||
|
||||
public double delta_x;
|
||||
|
||||
public double delta_y;
|
||||
}
|
||||
|
||||
private IntPtr _widget;
|
||||
|
||||
private SKImageInfo _imageInfo;
|
||||
|
||||
private SKBitmap? _bitmap;
|
||||
|
||||
private SKCanvas? _canvas;
|
||||
|
||||
private IntPtr _cairoSurface;
|
||||
|
||||
private readonly DrawCallback _drawCallback;
|
||||
|
||||
private readonly ConfigureCallback _configureCallback;
|
||||
|
||||
private ulong _drawSignalId;
|
||||
|
||||
private ulong _configureSignalId;
|
||||
|
||||
private bool _isTransparent;
|
||||
|
||||
private readonly ButtonEventCallback _buttonPressCallback;
|
||||
|
||||
private readonly ButtonEventCallback _buttonReleaseCallback;
|
||||
|
||||
private readonly MotionEventCallback _motionCallback;
|
||||
|
||||
private readonly KeyEventCallback _keyPressCallback;
|
||||
|
||||
private readonly KeyEventCallback _keyReleaseCallback;
|
||||
|
||||
private readonly ScrollEventCallback _scrollCallback;
|
||||
|
||||
public IntPtr Widget => _widget;
|
||||
|
||||
public SKCanvas? Canvas => _canvas;
|
||||
|
||||
public SKImageInfo ImageInfo => _imageInfo;
|
||||
|
||||
public int Width => ((SKImageInfo)(ref _imageInfo)).Width;
|
||||
|
||||
public int Height => ((SKImageInfo)(ref _imageInfo)).Height;
|
||||
|
||||
public bool IsTransparent => _isTransparent;
|
||||
|
||||
public event EventHandler? DrawRequested;
|
||||
|
||||
public event EventHandler<(int Width, int Height)>? Resized;
|
||||
|
||||
public event EventHandler<(double X, double Y, int Button)>? PointerPressed;
|
||||
|
||||
public event EventHandler<(double X, double Y, int Button)>? PointerReleased;
|
||||
|
||||
public event EventHandler<(double X, double Y)>? PointerMoved;
|
||||
|
||||
public event EventHandler<(uint KeyVal, uint KeyCode, uint State)>? KeyPressed;
|
||||
|
||||
public event EventHandler<(uint KeyVal, uint KeyCode, uint State)>? KeyReleased;
|
||||
|
||||
public event EventHandler<(double X, double Y, double DeltaX, double DeltaY)>? Scrolled;
|
||||
|
||||
public event EventHandler<string>? TextInput;
|
||||
|
||||
public GtkSkiaSurfaceWidget(int width, int height)
|
||||
{
|
||||
_widget = GtkNative.gtk_drawing_area_new();
|
||||
if (_widget == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to create GTK drawing area");
|
||||
}
|
||||
GtkNative.gtk_widget_set_size_request(_widget, width, height);
|
||||
GtkNative.gtk_widget_add_events(_widget, 10551046);
|
||||
GtkNative.gtk_widget_set_can_focus(_widget, canFocus: true);
|
||||
CreateBuffer(width, height);
|
||||
_drawCallback = OnDraw;
|
||||
_configureCallback = OnConfigure;
|
||||
_buttonPressCallback = OnButtonPress;
|
||||
_buttonReleaseCallback = OnButtonRelease;
|
||||
_motionCallback = OnMotion;
|
||||
_keyPressCallback = OnKeyPress;
|
||||
_keyReleaseCallback = OnKeyRelease;
|
||||
_scrollCallback = OnScroll;
|
||||
_drawSignalId = GtkNative.g_signal_connect_data(_widget, "draw", Marshal.GetFunctionPointerForDelegate(_drawCallback), IntPtr.Zero, IntPtr.Zero, 0);
|
||||
_configureSignalId = GtkNative.g_signal_connect_data(_widget, "configure-event", Marshal.GetFunctionPointerForDelegate(_configureCallback), IntPtr.Zero, IntPtr.Zero, 0);
|
||||
GtkNative.g_signal_connect_data(_widget, "button-press-event", Marshal.GetFunctionPointerForDelegate(_buttonPressCallback), IntPtr.Zero, IntPtr.Zero, 0);
|
||||
GtkNative.g_signal_connect_data(_widget, "button-release-event", Marshal.GetFunctionPointerForDelegate(_buttonReleaseCallback), IntPtr.Zero, IntPtr.Zero, 0);
|
||||
GtkNative.g_signal_connect_data(_widget, "motion-notify-event", Marshal.GetFunctionPointerForDelegate(_motionCallback), IntPtr.Zero, IntPtr.Zero, 0);
|
||||
GtkNative.g_signal_connect_data(_widget, "key-press-event", Marshal.GetFunctionPointerForDelegate(_keyPressCallback), IntPtr.Zero, IntPtr.Zero, 0);
|
||||
GtkNative.g_signal_connect_data(_widget, "key-release-event", Marshal.GetFunctionPointerForDelegate(_keyReleaseCallback), IntPtr.Zero, IntPtr.Zero, 0);
|
||||
GtkNative.g_signal_connect_data(_widget, "scroll-event", Marshal.GetFunctionPointerForDelegate(_scrollCallback), IntPtr.Zero, IntPtr.Zero, 0);
|
||||
Console.WriteLine($"[GtkSkiaSurfaceWidget] Created with size {width}x{height}");
|
||||
}
|
||||
|
||||
private void CreateBuffer(int width, int height)
|
||||
{
|
||||
//IL_005c: 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_0068: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0077: Expected O, but got Unknown
|
||||
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0088: Expected O, but got Unknown
|
||||
width = Math.Max(1, width);
|
||||
height = Math.Max(1, height);
|
||||
SKCanvas? canvas = _canvas;
|
||||
if (canvas != null)
|
||||
{
|
||||
((SKNativeObject)canvas).Dispose();
|
||||
}
|
||||
SKBitmap? bitmap = _bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
if (_cairoSurface != IntPtr.Zero)
|
||||
{
|
||||
CairoNative.cairo_surface_destroy(_cairoSurface);
|
||||
_cairoSurface = IntPtr.Zero;
|
||||
}
|
||||
_imageInfo = new SKImageInfo(width, height, (SKColorType)6, (SKAlphaType)2);
|
||||
_bitmap = new SKBitmap(_imageInfo);
|
||||
_canvas = new SKCanvas(_bitmap);
|
||||
IntPtr pixels = _bitmap.GetPixels();
|
||||
_cairoSurface = CairoNative.cairo_image_surface_create_for_data(pixels, CairoNative.cairo_format_t.CAIRO_FORMAT_ARGB32, ((SKImageInfo)(ref _imageInfo)).Width, ((SKImageInfo)(ref _imageInfo)).Height, ((SKImageInfo)(ref _imageInfo)).RowBytes);
|
||||
Console.WriteLine($"[GtkSkiaSurfaceWidget] Created buffer {width}x{height}, stride={((SKImageInfo)(ref _imageInfo)).RowBytes}");
|
||||
}
|
||||
|
||||
public void Resize(int width, int height)
|
||||
{
|
||||
if (width != ((SKImageInfo)(ref _imageInfo)).Width || height != ((SKImageInfo)(ref _imageInfo)).Height)
|
||||
{
|
||||
CreateBuffer(width, height);
|
||||
this.Resized?.Invoke(this, (width, height));
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderFrame(Action<SKCanvas, SKImageInfo> render)
|
||||
{
|
||||
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (_canvas != null && _bitmap != null)
|
||||
{
|
||||
render(_canvas, _imageInfo);
|
||||
_canvas.Flush();
|
||||
CairoNative.cairo_surface_flush(_cairoSurface);
|
||||
CairoNative.cairo_surface_mark_dirty(_cairoSurface);
|
||||
GtkNative.gtk_widget_queue_draw(_widget);
|
||||
}
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
GtkNative.gtk_widget_queue_draw(_widget);
|
||||
}
|
||||
|
||||
public void SetTransparent(bool transparent)
|
||||
{
|
||||
_isTransparent = transparent;
|
||||
}
|
||||
|
||||
private bool OnDraw(IntPtr widget, IntPtr cairoContext, IntPtr userData)
|
||||
{
|
||||
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (_cairoSurface == IntPtr.Zero || cairoContext == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_isTransparent)
|
||||
{
|
||||
SKCanvas? canvas = _canvas;
|
||||
if (canvas != null)
|
||||
{
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
}
|
||||
}
|
||||
this.DrawRequested?.Invoke(this, EventArgs.Empty);
|
||||
SKCanvas? canvas2 = _canvas;
|
||||
if (canvas2 != null)
|
||||
{
|
||||
canvas2.Flush();
|
||||
}
|
||||
CairoNative.cairo_surface_flush(_cairoSurface);
|
||||
CairoNative.cairo_surface_mark_dirty(_cairoSurface);
|
||||
CairoNative.cairo_set_source_surface(cairoContext, _cairoSurface, 0.0, 0.0);
|
||||
CairoNative.cairo_paint(cairoContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnConfigure(IntPtr widget, IntPtr eventData, IntPtr userData)
|
||||
{
|
||||
GtkNative.gtk_widget_get_allocation(widget, out var allocation);
|
||||
if (allocation.Width > 0 && allocation.Height > 0 && (allocation.Width != ((SKImageInfo)(ref _imageInfo)).Width || allocation.Height != ((SKImageInfo)(ref _imageInfo)).Height))
|
||||
{
|
||||
Resize(allocation.Width, allocation.Height);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OnButtonPress(IntPtr widget, IntPtr eventData, IntPtr userData)
|
||||
{
|
||||
GtkNative.gtk_widget_grab_focus(_widget);
|
||||
var (num, num2, num3) = ParseButtonEvent(eventData);
|
||||
Console.WriteLine($"[GtkSkiaSurfaceWidget] ButtonPress at ({num}, {num2}), button={num3}");
|
||||
this.PointerPressed?.Invoke(this, (num, num2, num3));
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnButtonRelease(IntPtr widget, IntPtr eventData, IntPtr userData)
|
||||
{
|
||||
var (item, item2, item3) = ParseButtonEvent(eventData);
|
||||
this.PointerReleased?.Invoke(this, (item, item2, item3));
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnMotion(IntPtr widget, IntPtr eventData, IntPtr userData)
|
||||
{
|
||||
var (item, item2) = ParseMotionEvent(eventData);
|
||||
this.PointerMoved?.Invoke(this, (item, item2));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void RaisePointerPressed(double x, double y, int button)
|
||||
{
|
||||
Console.WriteLine($"[GtkSkiaSurfaceWidget] RaisePointerPressed at ({x}, {y}), button={button}");
|
||||
this.PointerPressed?.Invoke(this, (x, y, button));
|
||||
}
|
||||
|
||||
public void RaisePointerReleased(double x, double y, int button)
|
||||
{
|
||||
this.PointerReleased?.Invoke(this, (x, y, button));
|
||||
}
|
||||
|
||||
public void RaisePointerMoved(double x, double y)
|
||||
{
|
||||
this.PointerMoved?.Invoke(this, (x, y));
|
||||
}
|
||||
|
||||
private bool OnKeyPress(IntPtr widget, IntPtr eventData, IntPtr userData)
|
||||
{
|
||||
var (num, item, item2) = ParseKeyEvent(eventData);
|
||||
this.KeyPressed?.Invoke(this, (num, item, item2));
|
||||
uint num2 = GdkNative.gdk_keyval_to_unicode(num);
|
||||
if (num2 != 0 && num2 < 65536)
|
||||
{
|
||||
char c = (char)num2;
|
||||
if (!char.IsControl(c) || c == '\r' || c == '\n' || c == '\t')
|
||||
{
|
||||
string text = c.ToString();
|
||||
Console.WriteLine($"[GtkSkiaSurfaceWidget] TextInput: '{text}' (keyval={num}, unicode={num2})");
|
||||
this.TextInput?.Invoke(this, text);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnKeyRelease(IntPtr widget, IntPtr eventData, IntPtr userData)
|
||||
{
|
||||
var (item, item2, item3) = ParseKeyEvent(eventData);
|
||||
this.KeyReleased?.Invoke(this, (item, item2, item3));
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnScroll(IntPtr widget, IntPtr eventData, IntPtr userData)
|
||||
{
|
||||
var (item, item2, item3, item4) = ParseScrollEvent(eventData);
|
||||
this.Scrolled?.Invoke(this, (item, item2, item3, item4));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static (double x, double y, int button) ParseButtonEvent(IntPtr eventData)
|
||||
{
|
||||
GdkEventButton gdkEventButton = Marshal.PtrToStructure<GdkEventButton>(eventData);
|
||||
return (x: gdkEventButton.x, y: gdkEventButton.y, button: (int)gdkEventButton.button);
|
||||
}
|
||||
|
||||
private static (double x, double y) ParseMotionEvent(IntPtr eventData)
|
||||
{
|
||||
GdkEventMotion gdkEventMotion = Marshal.PtrToStructure<GdkEventMotion>(eventData);
|
||||
return (x: gdkEventMotion.x, y: gdkEventMotion.y);
|
||||
}
|
||||
|
||||
private static (uint keyval, uint keycode, uint state) ParseKeyEvent(IntPtr eventData)
|
||||
{
|
||||
GdkEventKey gdkEventKey = Marshal.PtrToStructure<GdkEventKey>(eventData);
|
||||
return (keyval: gdkEventKey.keyval, keycode: gdkEventKey.hardware_keycode, state: gdkEventKey.state);
|
||||
}
|
||||
|
||||
private static (double x, double y, double deltaX, double deltaY) ParseScrollEvent(IntPtr eventData)
|
||||
{
|
||||
GdkEventScroll gdkEventScroll = Marshal.PtrToStructure<GdkEventScroll>(eventData);
|
||||
double item = 0.0;
|
||||
double item2 = 0.0;
|
||||
if (gdkEventScroll.direction == 4)
|
||||
{
|
||||
item = gdkEventScroll.delta_x;
|
||||
item2 = gdkEventScroll.delta_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (gdkEventScroll.direction)
|
||||
{
|
||||
case 0:
|
||||
item2 = -1.0;
|
||||
break;
|
||||
case 1:
|
||||
item2 = 1.0;
|
||||
break;
|
||||
case 2:
|
||||
item = -1.0;
|
||||
break;
|
||||
case 3:
|
||||
item = 1.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (x: gdkEventScroll.x, y: gdkEventScroll.y, deltaX: item, deltaY: item2);
|
||||
}
|
||||
|
||||
public void GrabFocus()
|
||||
{
|
||||
GtkNative.gtk_widget_grab_focus(_widget);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
SKCanvas? canvas = _canvas;
|
||||
if (canvas != null)
|
||||
{
|
||||
((SKNativeObject)canvas).Dispose();
|
||||
}
|
||||
_canvas = null;
|
||||
SKBitmap? bitmap = _bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
_bitmap = null;
|
||||
if (_cairoSurface != IntPtr.Zero)
|
||||
{
|
||||
CairoNative.cairo_surface_destroy(_cairoSurface);
|
||||
_cairoSurface = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
public class LayeredRenderer : IDisposable
|
||||
{
|
||||
private readonly Dictionary<int, RenderLayer> _layers = new Dictionary<int, RenderLayer>();
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public RenderLayer GetLayer(int zIndex)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_layers.TryGetValue(zIndex, out RenderLayer value))
|
||||
{
|
||||
value = new RenderLayer(zIndex);
|
||||
_layers[zIndex] = value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveLayer(int zIndex)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_layers.TryGetValue(zIndex, out RenderLayer value))
|
||||
{
|
||||
value.Dispose();
|
||||
_layers.Remove(zIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Composite(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (RenderLayer item in _layers.Values.OrderBy((RenderLayer l) => l.ZIndex))
|
||||
{
|
||||
item.DrawTo(canvas, bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateAll()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (RenderLayer value in _layers.Values)
|
||||
{
|
||||
value.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_disposed = true;
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (RenderLayer value in _layers.Values)
|
||||
{
|
||||
value.Dispose();
|
||||
}
|
||||
_layers.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,230 +1,526 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Caches rendered content for views that don't change frequently.
|
||||
/// Improves performance by avoiding redundant rendering.
|
||||
/// </summary>
|
||||
public class RenderCache : IDisposable
|
||||
{
|
||||
private class CacheEntry
|
||||
{
|
||||
public string Key { get; set; } = string.Empty;
|
||||
private readonly Dictionary<string, CacheEntry> _cache = new();
|
||||
private readonly object _lock = new();
|
||||
private long _maxCacheSize = 50 * 1024 * 1024; // 50 MB default
|
||||
private long _currentCacheSize;
|
||||
private bool _disposed;
|
||||
|
||||
public SKBitmap? Bitmap { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum cache size in bytes.
|
||||
/// </summary>
|
||||
public long MaxCacheSize
|
||||
{
|
||||
get => _maxCacheSize;
|
||||
set
|
||||
{
|
||||
_maxCacheSize = Math.Max(1024 * 1024, value); // Minimum 1 MB
|
||||
TrimCache();
|
||||
}
|
||||
}
|
||||
|
||||
public long Size { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the current cache size in bytes.
|
||||
/// </summary>
|
||||
public long CurrentCacheSize => _currentCacheSize;
|
||||
|
||||
public DateTime Created { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the number of cached items.
|
||||
/// </summary>
|
||||
public int CachedItemCount
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _cache.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime LastAccessed { get; set; }
|
||||
/// <summary>
|
||||
/// Tries to get a cached bitmap for the given key.
|
||||
/// </summary>
|
||||
public bool TryGet(string key, out SKBitmap? bitmap)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out var entry))
|
||||
{
|
||||
entry.LastAccessed = DateTime.UtcNow;
|
||||
entry.AccessCount++;
|
||||
bitmap = entry.Bitmap;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int AccessCount { get; set; }
|
||||
}
|
||||
bitmap = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, CacheEntry> _cache = new Dictionary<string, CacheEntry>();
|
||||
/// <summary>
|
||||
/// Caches a bitmap with the given key.
|
||||
/// </summary>
|
||||
public void Set(string key, SKBitmap bitmap)
|
||||
{
|
||||
if (bitmap == null) return;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
long bitmapSize = bitmap.ByteCount;
|
||||
|
||||
private long _maxCacheSize = 52428800L;
|
||||
// Don't cache if bitmap is larger than max size
|
||||
if (bitmapSize > _maxCacheSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
private long _currentCacheSize;
|
||||
lock (_lock)
|
||||
{
|
||||
// Remove existing entry if present
|
||||
if (_cache.TryGetValue(key, out var existing))
|
||||
{
|
||||
_currentCacheSize -= existing.Size;
|
||||
existing.Bitmap?.Dispose();
|
||||
}
|
||||
|
||||
private bool _disposed;
|
||||
// Create copy of bitmap for cache
|
||||
var cachedBitmap = bitmap.Copy();
|
||||
if (cachedBitmap == null) return;
|
||||
|
||||
public long MaxCacheSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return _maxCacheSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
_maxCacheSize = Math.Max(1048576L, value);
|
||||
TrimCache();
|
||||
}
|
||||
}
|
||||
var entry = new CacheEntry
|
||||
{
|
||||
Key = key,
|
||||
Bitmap = cachedBitmap,
|
||||
Size = bitmapSize,
|
||||
Created = DateTime.UtcNow,
|
||||
LastAccessed = DateTime.UtcNow,
|
||||
AccessCount = 1
|
||||
};
|
||||
|
||||
public long CurrentCacheSize => _currentCacheSize;
|
||||
_cache[key] = entry;
|
||||
_currentCacheSize += bitmapSize;
|
||||
|
||||
public int CachedItemCount
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _cache.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Trim cache if needed
|
||||
TrimCache();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGet(string key, out SKBitmap? bitmap)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out CacheEntry value))
|
||||
{
|
||||
value.LastAccessed = DateTime.UtcNow;
|
||||
value.AccessCount++;
|
||||
bitmap = value.Bitmap;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bitmap = null;
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Invalidates a cached entry.
|
||||
/// </summary>
|
||||
public void Invalidate(string key)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out var entry))
|
||||
{
|
||||
_currentCacheSize -= entry.Size;
|
||||
entry.Bitmap?.Dispose();
|
||||
_cache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(string key, SKBitmap bitmap)
|
||||
{
|
||||
if (bitmap == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
long num = bitmap.ByteCount;
|
||||
if (num > _maxCacheSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out CacheEntry value))
|
||||
{
|
||||
_currentCacheSize -= value.Size;
|
||||
SKBitmap? bitmap2 = value.Bitmap;
|
||||
if (bitmap2 != null)
|
||||
{
|
||||
((SKNativeObject)bitmap2).Dispose();
|
||||
}
|
||||
}
|
||||
SKBitmap val = bitmap.Copy();
|
||||
if (val != null)
|
||||
{
|
||||
CacheEntry value2 = new CacheEntry
|
||||
{
|
||||
Key = key,
|
||||
Bitmap = val,
|
||||
Size = num,
|
||||
Created = DateTime.UtcNow,
|
||||
LastAccessed = DateTime.UtcNow,
|
||||
AccessCount = 1
|
||||
};
|
||||
_cache[key] = value2;
|
||||
_currentCacheSize += num;
|
||||
TrimCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Invalidates all entries matching a prefix.
|
||||
/// </summary>
|
||||
public void InvalidatePrefix(string prefix)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
var keysToRemove = _cache.Keys
|
||||
.Where(k => k.StartsWith(prefix, StringComparison.Ordinal))
|
||||
.ToList();
|
||||
|
||||
public void Invalidate(string key)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out CacheEntry value))
|
||||
{
|
||||
_currentCacheSize -= value.Size;
|
||||
SKBitmap? bitmap = value.Bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
_cache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var key in keysToRemove)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out var entry))
|
||||
{
|
||||
_currentCacheSize -= entry.Size;
|
||||
entry.Bitmap?.Dispose();
|
||||
_cache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidatePrefix(string prefix)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (string item in _cache.Keys.Where((string k) => k.StartsWith(prefix, StringComparison.Ordinal)).ToList())
|
||||
{
|
||||
if (_cache.TryGetValue(item, out CacheEntry value))
|
||||
{
|
||||
_currentCacheSize -= value.Size;
|
||||
SKBitmap? bitmap = value.Bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
_cache.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Clears all cached content.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var entry in _cache.Values)
|
||||
{
|
||||
entry.Bitmap?.Dispose();
|
||||
}
|
||||
_cache.Clear();
|
||||
_currentCacheSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (CacheEntry value in _cache.Values)
|
||||
{
|
||||
SKBitmap? bitmap = value.Bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
}
|
||||
_cache.Clear();
|
||||
_currentCacheSize = 0L;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Renders content with caching.
|
||||
/// </summary>
|
||||
public SKBitmap GetOrCreate(string key, int width, int height, Action<SKCanvas> render)
|
||||
{
|
||||
// Check cache first
|
||||
if (TryGet(key, out var cached) && cached != null &&
|
||||
cached.Width == width && cached.Height == height)
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
|
||||
public SKBitmap GetOrCreate(string key, int width, int height, Action<SKCanvas> render)
|
||||
{
|
||||
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002c: Expected O, but got Unknown
|
||||
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0033: Expected O, but got Unknown
|
||||
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (TryGet(key, out SKBitmap bitmap) && bitmap != null && bitmap.Width == width && bitmap.Height == height)
|
||||
{
|
||||
return bitmap;
|
||||
}
|
||||
SKBitmap val = new SKBitmap(width, height, (SKColorType)4, (SKAlphaType)2);
|
||||
SKCanvas val2 = new SKCanvas(val);
|
||||
try
|
||||
{
|
||||
val2.Clear(SKColors.Transparent);
|
||||
render(val2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val2)?.Dispose();
|
||||
}
|
||||
Set(key, val);
|
||||
return val;
|
||||
}
|
||||
// Create new bitmap
|
||||
var bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using (var canvas = new SKCanvas(bitmap))
|
||||
{
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
render(canvas);
|
||||
}
|
||||
|
||||
private void TrimCache()
|
||||
{
|
||||
if (_currentCacheSize <= _maxCacheSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (CacheEntry item in (from e in _cache.Values
|
||||
orderby e.LastAccessed, e.AccessCount
|
||||
select e).ToList())
|
||||
{
|
||||
if ((double)_currentCacheSize <= (double)_maxCacheSize * 0.8)
|
||||
{
|
||||
break;
|
||||
}
|
||||
_currentCacheSize -= item.Size;
|
||||
SKBitmap? bitmap = item.Bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
_cache.Remove(item.Key);
|
||||
}
|
||||
}
|
||||
// Cache it
|
||||
Set(key, bitmap);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private void TrimCache()
|
||||
{
|
||||
if (_currentCacheSize <= _maxCacheSize) return;
|
||||
|
||||
// Remove least recently used entries until under limit
|
||||
var entries = _cache.Values
|
||||
.OrderBy(e => e.LastAccessed)
|
||||
.ThenBy(e => e.AccessCount)
|
||||
.ToList();
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
if (_currentCacheSize <= _maxCacheSize * 0.8) // Target 80% usage
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_currentCacheSize -= entry.Size;
|
||||
entry.Bitmap?.Dispose();
|
||||
_cache.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
Clear();
|
||||
}
|
||||
|
||||
private class CacheEntry
|
||||
{
|
||||
public string Key { get; set; } = string.Empty;
|
||||
public SKBitmap? Bitmap { get; set; }
|
||||
public long Size { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastAccessed { get; set; }
|
||||
public int AccessCount { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides layered rendering for separating static and dynamic content.
|
||||
/// </summary>
|
||||
public class LayeredRenderer : IDisposable
|
||||
{
|
||||
private readonly Dictionary<int, RenderLayer> _layers = new();
|
||||
private readonly object _lock = new();
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or creates a render layer.
|
||||
/// </summary>
|
||||
public RenderLayer GetLayer(int zIndex)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_layers.TryGetValue(zIndex, out var layer))
|
||||
{
|
||||
layer = new RenderLayer(zIndex);
|
||||
_layers[zIndex] = layer;
|
||||
}
|
||||
return layer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a render layer.
|
||||
/// </summary>
|
||||
public void RemoveLayer(int zIndex)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_layers.TryGetValue(zIndex, out var layer))
|
||||
{
|
||||
layer.Dispose();
|
||||
_layers.Remove(zIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Composites all layers onto the target canvas.
|
||||
/// </summary>
|
||||
public void Composite(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var layer in _layers.Values.OrderBy(l => l.ZIndex))
|
||||
{
|
||||
layer.DrawTo(canvas, bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates all layers.
|
||||
/// </summary>
|
||||
public void InvalidateAll()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var layer in _layers.Values)
|
||||
{
|
||||
layer.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var layer in _layers.Values)
|
||||
{
|
||||
layer.Dispose();
|
||||
}
|
||||
_layers.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single render layer with its own bitmap buffer.
|
||||
/// </summary>
|
||||
public class RenderLayer : IDisposable
|
||||
{
|
||||
private SKBitmap? _bitmap;
|
||||
private SKCanvas? _canvas;
|
||||
private bool _isDirty = true;
|
||||
private SKRect _bounds;
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Z-index of this layer.
|
||||
/// </summary>
|
||||
public int ZIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this layer needs to be redrawn.
|
||||
/// </summary>
|
||||
public bool IsDirty => _isDirty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this layer is visible.
|
||||
/// </summary>
|
||||
public bool IsVisible { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the layer opacity (0-1).
|
||||
/// </summary>
|
||||
public float Opacity { get; set; } = 1f;
|
||||
|
||||
public RenderLayer(int zIndex)
|
||||
{
|
||||
ZIndex = zIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares the layer for rendering.
|
||||
/// </summary>
|
||||
public SKCanvas BeginDraw(SKRect bounds)
|
||||
{
|
||||
if (_bitmap == null || _bounds != bounds)
|
||||
{
|
||||
_bitmap?.Dispose();
|
||||
_canvas?.Dispose();
|
||||
|
||||
int width = Math.Max(1, (int)bounds.Width);
|
||||
int height = Math.Max(1, (int)bounds.Height);
|
||||
|
||||
_bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
_canvas = new SKCanvas(_bitmap);
|
||||
_bounds = bounds;
|
||||
}
|
||||
|
||||
_canvas!.Clear(SKColors.Transparent);
|
||||
_isDirty = false;
|
||||
return _canvas;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the layer as needing redraw.
|
||||
/// </summary>
|
||||
public void Invalidate()
|
||||
{
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws this layer to the target canvas.
|
||||
/// </summary>
|
||||
public void DrawTo(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
if (!IsVisible || _bitmap == null) return;
|
||||
|
||||
using var paint = new SKPaint
|
||||
{
|
||||
Color = SKColors.White.WithAlpha((byte)(Opacity * 255))
|
||||
};
|
||||
|
||||
canvas.DrawBitmap(_bitmap, bounds.Left, bounds.Top, paint);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
_canvas?.Dispose();
|
||||
_bitmap?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides text rendering optimization with glyph caching.
|
||||
/// </summary>
|
||||
public class TextRenderCache : IDisposable
|
||||
{
|
||||
private readonly Dictionary<TextCacheKey, SKBitmap> _cache = new();
|
||||
private readonly object _lock = new();
|
||||
private int _maxEntries = 500;
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of cached text entries.
|
||||
/// </summary>
|
||||
public int MaxEntries
|
||||
{
|
||||
get => _maxEntries;
|
||||
set => _maxEntries = Math.Max(10, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a cached text bitmap or creates one.
|
||||
/// </summary>
|
||||
public SKBitmap GetOrCreate(string text, SKPaint paint)
|
||||
{
|
||||
var key = new TextCacheKey(text, paint);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out var cached))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
|
||||
// Create text bitmap
|
||||
var bounds = new SKRect();
|
||||
paint.MeasureText(text, ref bounds);
|
||||
|
||||
int width = Math.Max(1, (int)Math.Ceiling(bounds.Width) + 2);
|
||||
int height = Math.Max(1, (int)Math.Ceiling(bounds.Height) + 2);
|
||||
|
||||
var bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using (var canvas = new SKCanvas(bitmap))
|
||||
{
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
canvas.DrawText(text, -bounds.Left + 1, -bounds.Top + 1, paint);
|
||||
}
|
||||
|
||||
// Trim cache if needed
|
||||
if (_cache.Count >= _maxEntries)
|
||||
{
|
||||
var oldest = _cache.First();
|
||||
oldest.Value.Dispose();
|
||||
_cache.Remove(oldest.Key);
|
||||
}
|
||||
|
||||
_cache[key] = bitmap;
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all cached text.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var entry in _cache.Values)
|
||||
{
|
||||
entry.Dispose();
|
||||
}
|
||||
_cache.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
Clear();
|
||||
}
|
||||
|
||||
private readonly struct TextCacheKey : IEquatable<TextCacheKey>
|
||||
{
|
||||
private readonly string _text;
|
||||
private readonly float _textSize;
|
||||
private readonly SKColor _color;
|
||||
private readonly int _weight;
|
||||
private readonly int _hashCode;
|
||||
|
||||
public TextCacheKey(string text, SKPaint paint)
|
||||
{
|
||||
_text = text;
|
||||
_textSize = paint.TextSize;
|
||||
_color = paint.Color;
|
||||
_weight = paint.Typeface?.FontWeight ?? (int)SKFontStyleWeight.Normal;
|
||||
_hashCode = HashCode.Combine(_text, _textSize, _color, _weight);
|
||||
}
|
||||
|
||||
public bool Equals(TextCacheKey other)
|
||||
{
|
||||
return _text == other._text &&
|
||||
Math.Abs(_textSize - other._textSize) < 0.001f &&
|
||||
_color == other._color &&
|
||||
_weight == other._weight;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) => obj is TextCacheKey other && Equals(other);
|
||||
public override int GetHashCode() => _hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
using System;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
public class RenderLayer : IDisposable
|
||||
{
|
||||
private SKBitmap? _bitmap;
|
||||
|
||||
private SKCanvas? _canvas;
|
||||
|
||||
private bool _isDirty = true;
|
||||
|
||||
private SKRect _bounds;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public int ZIndex { get; }
|
||||
|
||||
public bool IsDirty => _isDirty;
|
||||
|
||||
public bool IsVisible { get; set; } = true;
|
||||
|
||||
public float Opacity { get; set; } = 1f;
|
||||
|
||||
public RenderLayer(int zIndex)
|
||||
{
|
||||
ZIndex = zIndex;
|
||||
}
|
||||
|
||||
public SKCanvas BeginDraw(SKRect bounds)
|
||||
{
|
||||
//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_0083: 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_0065: Expected O, but got Unknown
|
||||
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0076: Expected O, but got Unknown
|
||||
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (_bitmap == null || _bounds != bounds)
|
||||
{
|
||||
SKBitmap? bitmap = _bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
SKCanvas? canvas = _canvas;
|
||||
if (canvas != null)
|
||||
{
|
||||
((SKNativeObject)canvas).Dispose();
|
||||
}
|
||||
int num = Math.Max(1, (int)((SKRect)(ref bounds)).Width);
|
||||
int num2 = Math.Max(1, (int)((SKRect)(ref bounds)).Height);
|
||||
_bitmap = new SKBitmap(num, num2, (SKColorType)4, (SKAlphaType)2);
|
||||
_canvas = new SKCanvas(_bitmap);
|
||||
_bounds = bounds;
|
||||
}
|
||||
_canvas.Clear(SKColors.Transparent);
|
||||
_isDirty = false;
|
||||
return _canvas;
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
public void DrawTo(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
//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_0029: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0034: Expected O, but got Unknown
|
||||
if (!IsVisible || _bitmap == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SKPaint val = new SKPaint
|
||||
{
|
||||
Color = ((SKColor)(ref SKColors.White)).WithAlpha((byte)(Opacity * 255f))
|
||||
};
|
||||
try
|
||||
{
|
||||
canvas.DrawBitmap(_bitmap, ((SKRect)(ref bounds)).Left, ((SKRect)(ref bounds)).Top, val);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val)?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
SKCanvas? canvas = _canvas;
|
||||
if (canvas != null)
|
||||
{
|
||||
((SKNativeObject)canvas).Dispose();
|
||||
}
|
||||
SKBitmap? bitmap = _bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
public class ResourceCache : IDisposable
|
||||
{
|
||||
private readonly Dictionary<string, SKTypeface> _typefaces = new Dictionary<string, SKTypeface>();
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public SKTypeface GetTypeface(string fontFamily, SKFontStyle style)
|
||||
{
|
||||
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
|
||||
string key = $"{fontFamily}_{style.Weight}_{style.Width}_{style.Slant}";
|
||||
if (!_typefaces.TryGetValue(key, out SKTypeface value))
|
||||
{
|
||||
value = SKTypeface.FromFamilyName(fontFamily, style) ?? SKTypeface.Default;
|
||||
_typefaces[key] = value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (SKTypeface value in _typefaces.Values)
|
||||
{
|
||||
((SKNativeObject)value).Dispose();
|
||||
}
|
||||
_typefaces.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
Clear();
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,372 +1,165 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Maui.Platform.Linux.Window;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using SkiaSharp;
|
||||
using Microsoft.Maui.Platform.Linux.Window;
|
||||
using Microsoft.Maui.Platform;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Manages Skia rendering to an X11 window.
|
||||
/// </summary>
|
||||
public class SkiaRenderingEngine : IDisposable
|
||||
{
|
||||
private readonly X11Window _window;
|
||||
private readonly X11Window _window;
|
||||
private SKBitmap? _bitmap;
|
||||
private SKCanvas? _canvas;
|
||||
private SKImageInfo _imageInfo;
|
||||
private bool _disposed;
|
||||
private bool _fullRedrawNeeded = true;
|
||||
|
||||
private SKBitmap? _bitmap;
|
||||
public static SkiaRenderingEngine? Current { get; private set; }
|
||||
public ResourceCache ResourceCache { get; }
|
||||
public int Width => _imageInfo.Width;
|
||||
public int Height => _imageInfo.Height;
|
||||
|
||||
private SKBitmap? _backBuffer;
|
||||
public SkiaRenderingEngine(X11Window window)
|
||||
{
|
||||
_window = window;
|
||||
ResourceCache = new ResourceCache();
|
||||
Current = this;
|
||||
|
||||
private SKCanvas? _canvas;
|
||||
CreateSurface(window.Width, window.Height);
|
||||
|
||||
private SKImageInfo _imageInfo;
|
||||
_window.Resized += OnWindowResized;
|
||||
_window.Exposed += OnWindowExposed;
|
||||
}
|
||||
|
||||
private bool _disposed;
|
||||
private void CreateSurface(int width, int height)
|
||||
{
|
||||
_bitmap?.Dispose();
|
||||
_canvas?.Dispose();
|
||||
|
||||
private bool _fullRedrawNeeded = true;
|
||||
_imageInfo = new SKImageInfo(
|
||||
Math.Max(1, width),
|
||||
Math.Max(1, height),
|
||||
SKColorType.Bgra8888,
|
||||
SKAlphaType.Premul);
|
||||
|
||||
private readonly List<SKRect> _dirtyRegions = new List<SKRect>();
|
||||
_bitmap = new SKBitmap(_imageInfo);
|
||||
_canvas = new SKCanvas(_bitmap);
|
||||
_fullRedrawNeeded = true;
|
||||
|
||||
}
|
||||
|
||||
private readonly object _dirtyLock = new object();
|
||||
private void OnWindowResized(object? sender, (int Width, int Height) size)
|
||||
{
|
||||
CreateSurface(size.Width, size.Height);
|
||||
}
|
||||
|
||||
private const int MaxDirtyRegions = 32;
|
||||
private void OnWindowExposed(object? sender, EventArgs e)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
}
|
||||
|
||||
private const float RegionMergeThreshold = 0.3f;
|
||||
public void InvalidateAll()
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
}
|
||||
|
||||
public static SkiaRenderingEngine? Current { get; private set; }
|
||||
public void Render(SkiaView rootView)
|
||||
{
|
||||
if (_canvas == null || _bitmap == null)
|
||||
return;
|
||||
|
||||
public ResourceCache ResourceCache { get; }
|
||||
_canvas.Clear(SKColors.White);
|
||||
|
||||
// Measure first, then arrange
|
||||
var availableSize = new SKSize(Width, Height);
|
||||
rootView.Measure(availableSize);
|
||||
|
||||
rootView.Arrange(new SKRect(0, 0, Width, Height));
|
||||
|
||||
// Draw the view tree
|
||||
rootView.Draw(_canvas);
|
||||
|
||||
// Draw popup overlays (dropdowns, calendars, etc.) on top
|
||||
SkiaView.DrawPopupOverlays(_canvas);
|
||||
|
||||
public int Width => ((SKImageInfo)(ref _imageInfo)).Width;
|
||||
// Draw modal dialogs on top of everything
|
||||
if (LinuxDialogService.HasActiveDialog)
|
||||
{
|
||||
LinuxDialogService.DrawDialogs(_canvas, new SKRect(0, 0, Width, Height));
|
||||
}
|
||||
|
||||
public int Height => ((SKImageInfo)(ref _imageInfo)).Height;
|
||||
_canvas.Flush();
|
||||
|
||||
public bool EnableDirtyRegionOptimization { get; set; } = true;
|
||||
// Present to X11 window
|
||||
PresentToWindow();
|
||||
}
|
||||
|
||||
public int DirtyRegionCount
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_dirtyLock)
|
||||
{
|
||||
return _dirtyRegions.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void PresentToWindow()
|
||||
{
|
||||
if (_bitmap == null) return;
|
||||
|
||||
public SkiaRenderingEngine(X11Window window)
|
||||
{
|
||||
_window = window;
|
||||
ResourceCache = new ResourceCache();
|
||||
Current = this;
|
||||
CreateSurface(window.Width, window.Height);
|
||||
_window.Resized += OnWindowResized;
|
||||
_window.Exposed += OnWindowExposed;
|
||||
}
|
||||
var pixels = _bitmap.GetPixels();
|
||||
if (pixels == IntPtr.Zero) return;
|
||||
|
||||
private void CreateSurface(int width, int height)
|
||||
{
|
||||
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0049: 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_0055: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_005f: Expected O, but got Unknown
|
||||
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0070: Expected O, but got Unknown
|
||||
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0081: Expected O, but got Unknown
|
||||
SKBitmap? bitmap = _bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
SKBitmap? backBuffer = _backBuffer;
|
||||
if (backBuffer != null)
|
||||
{
|
||||
((SKNativeObject)backBuffer).Dispose();
|
||||
}
|
||||
SKCanvas? canvas = _canvas;
|
||||
if (canvas != null)
|
||||
{
|
||||
((SKNativeObject)canvas).Dispose();
|
||||
}
|
||||
_imageInfo = new SKImageInfo(Math.Max(1, width), Math.Max(1, height), (SKColorType)6, (SKAlphaType)2);
|
||||
_bitmap = new SKBitmap(_imageInfo);
|
||||
_backBuffer = new SKBitmap(_imageInfo);
|
||||
_canvas = new SKCanvas(_bitmap);
|
||||
_fullRedrawNeeded = true;
|
||||
lock (_dirtyLock)
|
||||
{
|
||||
_dirtyRegions.Clear();
|
||||
}
|
||||
}
|
||||
_window.DrawPixels(pixels, _imageInfo.Width, _imageInfo.Height, _imageInfo.RowBytes);
|
||||
}
|
||||
|
||||
private void OnWindowResized(object? sender, (int Width, int Height) size)
|
||||
{
|
||||
CreateSurface(size.Width, size.Height);
|
||||
}
|
||||
public SKCanvas? GetCanvas() => _canvas;
|
||||
|
||||
private void OnWindowExposed(object? sender, EventArgs e)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
}
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_window.Resized -= OnWindowResized;
|
||||
_window.Exposed -= OnWindowExposed;
|
||||
_canvas?.Dispose();
|
||||
_bitmap?.Dispose();
|
||||
ResourceCache.Dispose();
|
||||
if (Current == this) Current = null;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateAll()
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
}
|
||||
|
||||
public void InvalidateRegion(SKRect region)
|
||||
{
|
||||
//IL_0026: 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_0049: 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)
|
||||
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (((SKRect)(ref region)).IsEmpty || ((SKRect)(ref region)).Width <= 0f || ((SKRect)(ref region)).Height <= 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
region = SKRect.Intersect(region, new SKRect(0f, 0f, (float)Width, (float)Height));
|
||||
if (((SKRect)(ref region)).IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (_dirtyLock)
|
||||
{
|
||||
if (_dirtyRegions.Count >= 32)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRegions.Clear();
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < _dirtyRegions.Count; i++)
|
||||
{
|
||||
SKRect val = _dirtyRegions[i];
|
||||
if (ShouldMergeRegions(val, region))
|
||||
{
|
||||
_dirtyRegions[i] = SKRect.Union(val, region);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_dirtyRegions.Add(region);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldMergeRegions(SKRect a, SKRect b)
|
||||
{
|
||||
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
|
||||
SKRect val = SKRect.Intersect(a, b);
|
||||
if (((SKRect)(ref val)).IsEmpty)
|
||||
{
|
||||
SKRect val2 = default(SKRect);
|
||||
((SKRect)(ref val2))._002Ector(((SKRect)(ref a)).Left - 4f, ((SKRect)(ref a)).Top - 4f, ((SKRect)(ref a)).Right + 4f, ((SKRect)(ref a)).Bottom + 4f);
|
||||
return ((SKRect)(ref val2)).IntersectsWith(b);
|
||||
}
|
||||
float num = ((SKRect)(ref val)).Width * ((SKRect)(ref val)).Height;
|
||||
float val3 = ((SKRect)(ref a)).Width * ((SKRect)(ref a)).Height;
|
||||
float val4 = ((SKRect)(ref b)).Width * ((SKRect)(ref b)).Height;
|
||||
float num2 = Math.Min(val3, val4);
|
||||
return num / num2 >= 0.3f;
|
||||
}
|
||||
|
||||
public void Render(SkiaView rootView)
|
||||
{
|
||||
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0028: 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_0099: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (_canvas == null || _bitmap == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SKSize availableSize = default(SKSize);
|
||||
((SKSize)(ref availableSize))._002Ector((float)Width, (float)Height);
|
||||
rootView.Measure(availableSize);
|
||||
rootView.Arrange(new SKRect(0f, 0f, (float)Width, (float)Height));
|
||||
bool flag = _fullRedrawNeeded || !EnableDirtyRegionOptimization;
|
||||
List<SKRect> list;
|
||||
lock (_dirtyLock)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
list = new List<SKRect>
|
||||
{
|
||||
new SKRect(0f, 0f, (float)Width, (float)Height)
|
||||
};
|
||||
_dirtyRegions.Clear();
|
||||
_fullRedrawNeeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_dirtyRegions.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
list = MergeOverlappingRegions(_dirtyRegions.ToList());
|
||||
_dirtyRegions.Clear();
|
||||
}
|
||||
}
|
||||
foreach (SKRect item in list)
|
||||
{
|
||||
RenderRegion(rootView, item, flag);
|
||||
}
|
||||
SkiaView.DrawPopupOverlays(_canvas);
|
||||
if (LinuxDialogService.HasActiveDialog)
|
||||
{
|
||||
LinuxDialogService.DrawDialogs(_canvas, new SKRect(0f, 0f, (float)Width, (float)Height));
|
||||
}
|
||||
_canvas.Flush();
|
||||
PresentToWindow();
|
||||
}
|
||||
|
||||
private void RenderRegion(SkiaView rootView, SKRect region, bool isFullRedraw)
|
||||
{
|
||||
//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)
|
||||
//IL_002c: 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_003e: Expected O, but got Unknown
|
||||
//IL_001e: 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)
|
||||
if (_canvas == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_canvas.Save();
|
||||
if (!isFullRedraw)
|
||||
{
|
||||
_canvas.ClipRect(region, (SKClipOperation)1, false);
|
||||
}
|
||||
SKPaint val = new SKPaint
|
||||
{
|
||||
Color = SKColors.White,
|
||||
Style = (SKPaintStyle)0
|
||||
};
|
||||
try
|
||||
{
|
||||
_canvas.DrawRect(region, val);
|
||||
rootView.Draw(_canvas);
|
||||
_canvas.Restore();
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val)?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private List<SKRect> MergeOverlappingRegions(List<SKRect> regions)
|
||||
{
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0043: 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_007f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_005c: 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 (regions.Count <= 1)
|
||||
{
|
||||
return regions;
|
||||
}
|
||||
List<SKRect> list = new List<SKRect>();
|
||||
bool[] array = new bool[regions.Count];
|
||||
for (int i = 0; i < regions.Count; i++)
|
||||
{
|
||||
if (array[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SKRect val = regions[i];
|
||||
array[i] = true;
|
||||
bool flag;
|
||||
do
|
||||
{
|
||||
flag = false;
|
||||
for (int j = i + 1; j < regions.Count; j++)
|
||||
{
|
||||
if (!array[j] && ShouldMergeRegions(val, regions[j]))
|
||||
{
|
||||
val = SKRect.Union(val, regions[j]);
|
||||
array[j] = true;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (flag);
|
||||
list.Add(val);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void PresentToWindow()
|
||||
{
|
||||
if (_bitmap != null)
|
||||
{
|
||||
IntPtr pixels = _bitmap.GetPixels();
|
||||
if (pixels != IntPtr.Zero)
|
||||
{
|
||||
_window.DrawPixels(pixels, ((SKImageInfo)(ref _imageInfo)).Width, ((SKImageInfo)(ref _imageInfo)).Height, ((SKImageInfo)(ref _imageInfo)).RowBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SKCanvas? GetCanvas()
|
||||
{
|
||||
return _canvas;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (disposing)
|
||||
{
|
||||
_window.Resized -= OnWindowResized;
|
||||
_window.Exposed -= OnWindowExposed;
|
||||
SKCanvas? canvas = _canvas;
|
||||
if (canvas != null)
|
||||
{
|
||||
((SKNativeObject)canvas).Dispose();
|
||||
}
|
||||
SKBitmap? bitmap = _bitmap;
|
||||
if (bitmap != null)
|
||||
{
|
||||
((SKNativeObject)bitmap).Dispose();
|
||||
}
|
||||
SKBitmap? backBuffer = _backBuffer;
|
||||
if (backBuffer != null)
|
||||
{
|
||||
((SKNativeObject)backBuffer).Dispose();
|
||||
}
|
||||
ResourceCache.Dispose();
|
||||
if (Current == this)
|
||||
{
|
||||
Current = null;
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class ResourceCache : IDisposable
|
||||
{
|
||||
private readonly Dictionary<string, SKTypeface> _typefaces = new();
|
||||
private bool _disposed;
|
||||
|
||||
public SKTypeface GetTypeface(string fontFamily, SKFontStyle style)
|
||||
{
|
||||
var key = $"{fontFamily}_{style.Weight}_{style.Width}_{style.Slant}";
|
||||
if (!_typefaces.TryGetValue(key, out var typeface))
|
||||
{
|
||||
typeface = SKTypeface.FromFamilyName(fontFamily, style) ?? SKTypeface.Default;
|
||||
_typefaces[key] = typeface;
|
||||
}
|
||||
return typeface;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var tf in _typefaces.Values) tf.Dispose();
|
||||
_typefaces.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed) { Clear(); _disposed = true; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
public class TextRenderCache : IDisposable
|
||||
{
|
||||
private readonly struct TextCacheKey : IEquatable<TextCacheKey>
|
||||
{
|
||||
private readonly string _text;
|
||||
|
||||
private readonly float _textSize;
|
||||
|
||||
private readonly SKColor _color;
|
||||
|
||||
private readonly int _weight;
|
||||
|
||||
private readonly int _hashCode;
|
||||
|
||||
public TextCacheKey(string text, SKPaint paint)
|
||||
{
|
||||
//IL_0015: 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_0049: Unknown result type (might be due to invalid IL or missing references)
|
||||
_text = text;
|
||||
_textSize = paint.TextSize;
|
||||
_color = paint.Color;
|
||||
SKTypeface typeface = paint.Typeface;
|
||||
_weight = ((typeface != null) ? typeface.FontWeight : 400);
|
||||
_hashCode = HashCode.Combine<string, float, SKColor, int>(_text, _textSize, _color, _weight);
|
||||
}
|
||||
|
||||
public bool Equals(TextCacheKey other)
|
||||
{
|
||||
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (_text == other._text && Math.Abs(_textSize - other._textSize) < 0.001f && _color == other._color)
|
||||
{
|
||||
return _weight == other._weight;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is TextCacheKey other)
|
||||
{
|
||||
return Equals(other);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<TextCacheKey, SKBitmap> _cache = new Dictionary<TextCacheKey, SKBitmap>();
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private int _maxEntries = 500;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public int MaxEntries
|
||||
{
|
||||
get
|
||||
{
|
||||
return _maxEntries;
|
||||
}
|
||||
set
|
||||
{
|
||||
_maxEntries = Math.Max(10, value);
|
||||
}
|
||||
}
|
||||
|
||||
public SKBitmap GetOrCreate(string text, SKPaint paint)
|
||||
{
|
||||
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_007d: Expected O, but got Unknown
|
||||
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0086: Expected O, but got Unknown
|
||||
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
|
||||
TextCacheKey key = new TextCacheKey(text, paint);
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out SKBitmap value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
SKRect val = default(SKRect);
|
||||
paint.MeasureText(text, ref val);
|
||||
int num = Math.Max(1, (int)Math.Ceiling(((SKRect)(ref val)).Width) + 2);
|
||||
int num2 = Math.Max(1, (int)Math.Ceiling(((SKRect)(ref val)).Height) + 2);
|
||||
SKBitmap val2 = new SKBitmap(num, num2, (SKColorType)4, (SKAlphaType)2);
|
||||
SKCanvas val3 = new SKCanvas(val2);
|
||||
try
|
||||
{
|
||||
val3.Clear(SKColors.Transparent);
|
||||
val3.DrawText(text, 0f - ((SKRect)(ref val)).Left + 1f, 0f - ((SKRect)(ref val)).Top + 1f, paint);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val3)?.Dispose();
|
||||
}
|
||||
if (_cache.Count >= _maxEntries)
|
||||
{
|
||||
KeyValuePair<TextCacheKey, SKBitmap> keyValuePair = _cache.First();
|
||||
((SKNativeObject)keyValuePair.Value).Dispose();
|
||||
_cache.Remove(keyValuePair.Key);
|
||||
}
|
||||
_cache[key] = val2;
|
||||
return val2;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (SKBitmap value in _cache.Values)
|
||||
{
|
||||
((SKNativeObject)value).Dispose();
|
||||
}
|
||||
_cache.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
internal class _003CFontFallbackManager_003EFAC9D2911A2850E174CCA7662C668F37C2FBBA325CAF5C11AFE3FA59C16CC64ED__StringBuilder
|
||||
{
|
||||
private readonly List<char> _chars = new List<char>();
|
||||
|
||||
public int Length => _chars.Count;
|
||||
|
||||
public void Append(string s)
|
||||
{
|
||||
_chars.AddRange(s);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_chars.Clear();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return new string(_chars.ToArray());
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
public static class AccessibilityServiceFactory
|
||||
{
|
||||
private static IAccessibilityService? _instance;
|
||||
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
public static IAccessibilityService Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = CreateService();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static IAccessibilityService CreateService()
|
||||
{
|
||||
try
|
||||
{
|
||||
AtSpi2AccessibilityService atSpi2AccessibilityService = new AtSpi2AccessibilityService();
|
||||
atSpi2AccessibilityService.Initialize();
|
||||
return atSpi2AccessibilityService;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("AccessibilityServiceFactory: Failed to create AT-SPI2 service - " + ex.Message);
|
||||
return new NullAccessibilityService();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_instance?.Shutdown();
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
public class AccessibleAction
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
public string? KeyBinding { get; set; }
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
public enum AccessibleProperty
|
||||
{
|
||||
Name,
|
||||
Description,
|
||||
Role,
|
||||
Value,
|
||||
Parent,
|
||||
Children
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
public struct AccessibleRect
|
||||
{
|
||||
public int X { get; set; }
|
||||
|
||||
public int Y { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
|
||||
public AccessibleRect(int x, int y, int width, int height)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
public enum AccessibleRole
|
||||
{
|
||||
Unknown,
|
||||
Window,
|
||||
Application,
|
||||
Panel,
|
||||
Frame,
|
||||
Button,
|
||||
CheckBox,
|
||||
RadioButton,
|
||||
ComboBox,
|
||||
Entry,
|
||||
Label,
|
||||
List,
|
||||
ListItem,
|
||||
Menu,
|
||||
MenuBar,
|
||||
MenuItem,
|
||||
ScrollBar,
|
||||
Slider,
|
||||
SpinButton,
|
||||
StatusBar,
|
||||
Tab,
|
||||
TabPanel,
|
||||
Text,
|
||||
ToggleButton,
|
||||
ToolBar,
|
||||
ToolTip,
|
||||
Tree,
|
||||
TreeItem,
|
||||
Image,
|
||||
ProgressBar,
|
||||
Separator,
|
||||
Link,
|
||||
Table,
|
||||
TableCell,
|
||||
TableRow,
|
||||
TableColumnHeader,
|
||||
TableRowHeader,
|
||||
PageTab,
|
||||
PageTabList,
|
||||
Dialog,
|
||||
Alert,
|
||||
Filler,
|
||||
Icon,
|
||||
Canvas
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
public enum AccessibleState
|
||||
{
|
||||
Active,
|
||||
Armed,
|
||||
Busy,
|
||||
Checked,
|
||||
Collapsed,
|
||||
Defunct,
|
||||
Editable,
|
||||
Enabled,
|
||||
Expandable,
|
||||
Expanded,
|
||||
Focusable,
|
||||
Focused,
|
||||
Horizontal,
|
||||
Iconified,
|
||||
Modal,
|
||||
MultiLine,
|
||||
Opaque,
|
||||
Pressed,
|
||||
Resizable,
|
||||
Selectable,
|
||||
Selected,
|
||||
Sensitive,
|
||||
Showing,
|
||||
SingleLine,
|
||||
Stale,
|
||||
Transient,
|
||||
Vertical,
|
||||
Visible,
|
||||
ManagesDescendants,
|
||||
Indeterminate,
|
||||
Required,
|
||||
InvalidEntry,
|
||||
ReadOnly
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
[Flags]
|
||||
public enum AccessibleStates : long
|
||||
{
|
||||
None = 0L,
|
||||
Active = 1L,
|
||||
Armed = 2L,
|
||||
Busy = 4L,
|
||||
Checked = 8L,
|
||||
Collapsed = 0x10L,
|
||||
Defunct = 0x20L,
|
||||
Editable = 0x40L,
|
||||
Enabled = 0x80L,
|
||||
Expandable = 0x100L,
|
||||
Expanded = 0x200L,
|
||||
Focusable = 0x400L,
|
||||
Focused = 0x800L,
|
||||
HasToolTip = 0x1000L,
|
||||
Horizontal = 0x2000L,
|
||||
Iconified = 0x4000L,
|
||||
Modal = 0x8000L,
|
||||
MultiLine = 0x10000L,
|
||||
MultiSelectable = 0x20000L,
|
||||
Opaque = 0x40000L,
|
||||
Pressed = 0x80000L,
|
||||
Resizable = 0x100000L,
|
||||
Selectable = 0x200000L,
|
||||
Selected = 0x400000L,
|
||||
Sensitive = 0x800000L,
|
||||
Showing = 0x1000000L,
|
||||
SingleLine = 0x2000000L,
|
||||
Stale = 0x4000000L,
|
||||
Transient = 0x8000000L,
|
||||
Vertical = 0x10000000L,
|
||||
Visible = 0x20000000L,
|
||||
ManagesDescendants = 0x40000000L,
|
||||
Indeterminate = 0x80000000L,
|
||||
Required = 0x100000000L,
|
||||
Truncated = 0x200000000L,
|
||||
Animated = 0x400000000L,
|
||||
InvalidEntry = 0x800000000L,
|
||||
SupportsAutocompletion = 0x1000000000L,
|
||||
SelectableText = 0x2000000000L,
|
||||
IsDefault = 0x4000000000L,
|
||||
Visited = 0x8000000000L,
|
||||
ReadOnly = 0x10000000000L
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||
|
||||
public enum AnnouncementPriority
|
||||
{
|
||||
Polite,
|
||||
Assertive
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user