Update with recovered code from VM binaries (Jan 1)
Recovered from decompiled OpenMaui.Controls.Linux.dll: - SkiaShell.cs: FlyoutHeader, FlyoutFooter, scroll support (918 -> 1325 lines) - X11Window.cs: Cursor support (XCreateFontCursor, XDefineCursor) - All handlers with dark mode support - All services with latest implementations - LinuxApplication with theme change handling
This commit is contained in:
@@ -1,464 +1,458 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using SkiaSharp;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for Skia-rendered pages.
|
||||
/// </summary>
|
||||
public class SkiaPage : SkiaView
|
||||
{
|
||||
private SkiaView? _content;
|
||||
private string _title = "";
|
||||
private SKColor _titleBarColor = new SKColor(0x21, 0x96, 0xF3); // Material Blue
|
||||
private SKColor _titleTextColor = SKColors.White;
|
||||
private bool _showNavigationBar = false;
|
||||
private float _navigationBarHeight = 56;
|
||||
private SkiaView? _content;
|
||||
|
||||
// Padding
|
||||
private float _paddingLeft;
|
||||
private float _paddingTop;
|
||||
private float _paddingRight;
|
||||
private float _paddingBottom;
|
||||
private string _title = "";
|
||||
|
||||
public SkiaView? Content
|
||||
{
|
||||
get => _content;
|
||||
set
|
||||
{
|
||||
if (_content != null)
|
||||
{
|
||||
_content.Parent = null;
|
||||
}
|
||||
_content = value;
|
||||
if (_content != null)
|
||||
{
|
||||
_content.Parent = this;
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
private SKColor _titleBarColor = new SKColor((byte)33, (byte)150, (byte)243);
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set
|
||||
{
|
||||
_title = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
private SKColor _titleTextColor = SKColors.White;
|
||||
|
||||
public SKColor TitleBarColor
|
||||
{
|
||||
get => _titleBarColor;
|
||||
set
|
||||
{
|
||||
_titleBarColor = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
private bool _showNavigationBar;
|
||||
|
||||
public SKColor TitleTextColor
|
||||
{
|
||||
get => _titleTextColor;
|
||||
set
|
||||
{
|
||||
_titleTextColor = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
private float _navigationBarHeight = 56f;
|
||||
|
||||
public bool ShowNavigationBar
|
||||
{
|
||||
get => _showNavigationBar;
|
||||
set
|
||||
{
|
||||
_showNavigationBar = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
private float _paddingLeft;
|
||||
|
||||
public float NavigationBarHeight
|
||||
{
|
||||
get => _navigationBarHeight;
|
||||
set
|
||||
{
|
||||
_navigationBarHeight = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
private float _paddingTop;
|
||||
|
||||
public float PaddingLeft
|
||||
{
|
||||
get => _paddingLeft;
|
||||
set { _paddingLeft = value; Invalidate(); }
|
||||
}
|
||||
private float _paddingRight;
|
||||
|
||||
public float PaddingTop
|
||||
{
|
||||
get => _paddingTop;
|
||||
set { _paddingTop = value; Invalidate(); }
|
||||
}
|
||||
private float _paddingBottom;
|
||||
|
||||
public float PaddingRight
|
||||
{
|
||||
get => _paddingRight;
|
||||
set { _paddingRight = value; Invalidate(); }
|
||||
}
|
||||
public SkiaView? Content
|
||||
{
|
||||
get
|
||||
{
|
||||
return _content;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_content != null)
|
||||
{
|
||||
_content.Parent = null;
|
||||
}
|
||||
_content = value;
|
||||
if (_content != null)
|
||||
{
|
||||
_content.Parent = this;
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public float PaddingBottom
|
||||
{
|
||||
get => _paddingBottom;
|
||||
set { _paddingBottom = value; Invalidate(); }
|
||||
}
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return _title;
|
||||
}
|
||||
set
|
||||
{
|
||||
_title = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsBusy { get; set; }
|
||||
public SKColor TitleBarColor
|
||||
{
|
||||
get
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
return _titleBarColor;
|
||||
}
|
||||
set
|
||||
{
|
||||
//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)
|
||||
_titleBarColor = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler? Appearing;
|
||||
public event EventHandler? Disappearing;
|
||||
public SKColor TitleTextColor
|
||||
{
|
||||
get
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
return _titleTextColor;
|
||||
}
|
||||
set
|
||||
{
|
||||
//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)
|
||||
_titleTextColor = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDraw(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
// Draw background
|
||||
if (BackgroundColor != SKColors.Transparent)
|
||||
{
|
||||
using var bgPaint = new SKPaint
|
||||
{
|
||||
Color = BackgroundColor,
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(bounds, bgPaint);
|
||||
}
|
||||
public bool ShowNavigationBar
|
||||
{
|
||||
get
|
||||
{
|
||||
return _showNavigationBar;
|
||||
}
|
||||
set
|
||||
{
|
||||
_showNavigationBar = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
var contentTop = bounds.Top;
|
||||
public float NavigationBarHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return _navigationBarHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
_navigationBarHeight = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw navigation bar if visible
|
||||
if (_showNavigationBar)
|
||||
{
|
||||
DrawNavigationBar(canvas, new SKRect(bounds.Left, bounds.Top, bounds.Right, bounds.Top + _navigationBarHeight));
|
||||
contentTop = bounds.Top + _navigationBarHeight;
|
||||
}
|
||||
public float PaddingLeft
|
||||
{
|
||||
get
|
||||
{
|
||||
return _paddingLeft;
|
||||
}
|
||||
set
|
||||
{
|
||||
_paddingLeft = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate content bounds with padding
|
||||
var contentBounds = new SKRect(
|
||||
bounds.Left + _paddingLeft,
|
||||
contentTop + _paddingTop,
|
||||
bounds.Right - _paddingRight,
|
||||
bounds.Bottom - _paddingBottom);
|
||||
public float PaddingTop
|
||||
{
|
||||
get
|
||||
{
|
||||
return _paddingTop;
|
||||
}
|
||||
set
|
||||
{
|
||||
_paddingTop = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw content
|
||||
if (_content != null)
|
||||
{
|
||||
// Apply content's margin to the content bounds
|
||||
var margin = _content.Margin;
|
||||
var adjustedBounds = new SKRect(
|
||||
contentBounds.Left + (float)margin.Left,
|
||||
contentBounds.Top + (float)margin.Top,
|
||||
contentBounds.Right - (float)margin.Right,
|
||||
contentBounds.Bottom - (float)margin.Bottom);
|
||||
public float PaddingRight
|
||||
{
|
||||
get
|
||||
{
|
||||
return _paddingRight;
|
||||
}
|
||||
set
|
||||
{
|
||||
_paddingRight = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// Measure and arrange the content before drawing
|
||||
var availableSize = new SKSize(adjustedBounds.Width, adjustedBounds.Height);
|
||||
_content.Measure(availableSize);
|
||||
_content.Arrange(adjustedBounds);
|
||||
Console.WriteLine($"[SkiaPage] Drawing content: {_content.GetType().Name}, Bounds={_content.Bounds}, IsVisible={_content.IsVisible}");
|
||||
_content.Draw(canvas);
|
||||
}
|
||||
public float PaddingBottom
|
||||
{
|
||||
get
|
||||
{
|
||||
return _paddingBottom;
|
||||
}
|
||||
set
|
||||
{
|
||||
_paddingBottom = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw busy indicator overlay
|
||||
if (IsBusy)
|
||||
{
|
||||
DrawBusyIndicator(canvas, bounds);
|
||||
}
|
||||
}
|
||||
public bool IsBusy { get; set; }
|
||||
|
||||
protected virtual void DrawNavigationBar(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
// Draw navigation bar background
|
||||
using var barPaint = new SKPaint
|
||||
{
|
||||
Color = _titleBarColor,
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(bounds, barPaint);
|
||||
public event EventHandler? Appearing;
|
||||
|
||||
// Draw title
|
||||
if (!string.IsNullOrEmpty(_title))
|
||||
{
|
||||
using var font = new SKFont(SKTypeface.Default, 20);
|
||||
using var textPaint = new SKPaint(font)
|
||||
{
|
||||
Color = _titleTextColor,
|
||||
IsAntialias = true
|
||||
};
|
||||
public event EventHandler? Disappearing;
|
||||
|
||||
var textBounds = new SKRect();
|
||||
textPaint.MeasureText(_title, ref textBounds);
|
||||
protected override void OnDraw(SKCanvas canvas, 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_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_0019: 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_002b: Expected O, but got Unknown
|
||||
//IL_0074: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_01df: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (base.BackgroundColor != SKColors.Transparent)
|
||||
{
|
||||
SKPaint val = new SKPaint
|
||||
{
|
||||
Color = base.BackgroundColor,
|
||||
Style = (SKPaintStyle)0
|
||||
};
|
||||
try
|
||||
{
|
||||
canvas.DrawRect(bounds, val);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val)?.Dispose();
|
||||
}
|
||||
}
|
||||
float num = ((SKRect)(ref bounds)).Top;
|
||||
if (_showNavigationBar)
|
||||
{
|
||||
DrawNavigationBar(canvas, new SKRect(((SKRect)(ref bounds)).Left, ((SKRect)(ref bounds)).Top, ((SKRect)(ref bounds)).Right, ((SKRect)(ref bounds)).Top + _navigationBarHeight));
|
||||
num = ((SKRect)(ref bounds)).Top + _navigationBarHeight;
|
||||
}
|
||||
SKRect val2 = default(SKRect);
|
||||
((SKRect)(ref val2))._002Ector(((SKRect)(ref bounds)).Left + _paddingLeft, num + _paddingTop, ((SKRect)(ref bounds)).Right - _paddingRight, ((SKRect)(ref bounds)).Bottom - _paddingBottom);
|
||||
if (_content != null)
|
||||
{
|
||||
Thickness margin = _content.Margin;
|
||||
SKRect bounds2 = default(SKRect);
|
||||
((SKRect)(ref bounds2))._002Ector(((SKRect)(ref val2)).Left + (float)((Thickness)(ref margin)).Left, ((SKRect)(ref val2)).Top + (float)((Thickness)(ref margin)).Top, ((SKRect)(ref val2)).Right - (float)((Thickness)(ref margin)).Right, ((SKRect)(ref val2)).Bottom - (float)((Thickness)(ref margin)).Bottom);
|
||||
SKSize availableSize = default(SKSize);
|
||||
((SKSize)(ref availableSize))._002Ector(((SKRect)(ref bounds2)).Width, ((SKRect)(ref bounds2)).Height);
|
||||
_content.Measure(availableSize);
|
||||
_content.Arrange(bounds2);
|
||||
Console.WriteLine($"[SkiaPage] Drawing content: {((object)_content).GetType().Name}, Bounds={_content.Bounds}, IsVisible={_content.IsVisible}");
|
||||
_content.Draw(canvas);
|
||||
}
|
||||
if (IsBusy)
|
||||
{
|
||||
DrawBusyIndicator(canvas, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
var x = bounds.Left + 16;
|
||||
var y = bounds.MidY - textBounds.MidY;
|
||||
canvas.DrawText(_title, x, y, textPaint);
|
||||
}
|
||||
protected virtual void DrawNavigationBar(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
//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_0007: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0019: Expected O, but got Unknown
|
||||
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ce: 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_00df: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00f1: Expected O, but got Unknown
|
||||
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004b: Expected O, but got Unknown
|
||||
//IL_0114: 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_0051: 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_005d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0065: Expected O, but got Unknown
|
||||
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
|
||||
SKPaint val = new SKPaint
|
||||
{
|
||||
Color = _titleBarColor,
|
||||
Style = (SKPaintStyle)0
|
||||
};
|
||||
try
|
||||
{
|
||||
canvas.DrawRect(bounds, val);
|
||||
if (!string.IsNullOrEmpty(_title))
|
||||
{
|
||||
SKFont val2 = new SKFont(SKTypeface.Default, 20f, 1f, 0f);
|
||||
try
|
||||
{
|
||||
SKPaint val3 = new SKPaint(val2)
|
||||
{
|
||||
Color = _titleTextColor,
|
||||
IsAntialias = true
|
||||
};
|
||||
try
|
||||
{
|
||||
SKRect val4 = default(SKRect);
|
||||
val3.MeasureText(_title, ref val4);
|
||||
float num = ((SKRect)(ref bounds)).Left + 16f;
|
||||
float num2 = ((SKRect)(ref bounds)).MidY - ((SKRect)(ref val4)).MidY;
|
||||
canvas.DrawText(_title, num, num2, val3);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val3)?.Dispose();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val2)?.Dispose();
|
||||
}
|
||||
}
|
||||
SKPaint val5 = new SKPaint
|
||||
{
|
||||
Color = new SKColor((byte)0, (byte)0, (byte)0, (byte)30),
|
||||
Style = (SKPaintStyle)0,
|
||||
MaskFilter = SKMaskFilter.CreateBlur((SKBlurStyle)0, 2f)
|
||||
};
|
||||
try
|
||||
{
|
||||
canvas.DrawRect(new SKRect(((SKRect)(ref bounds)).Left, ((SKRect)(ref bounds)).Bottom, ((SKRect)(ref bounds)).Right, ((SKRect)(ref bounds)).Bottom + 4f), val5);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val5)?.Dispose();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val)?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw shadow
|
||||
using var shadowPaint = new SKPaint
|
||||
{
|
||||
Color = new SKColor(0, 0, 0, 30),
|
||||
Style = SKPaintStyle.Fill,
|
||||
MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 2)
|
||||
};
|
||||
canvas.DrawRect(new SKRect(bounds.Left, bounds.Bottom, bounds.Right, bounds.Bottom + 4), shadowPaint);
|
||||
}
|
||||
private void DrawBusyIndicator(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
//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_001a: 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_002c: Expected O, but got Unknown
|
||||
//IL_002d: 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)
|
||||
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0045: 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_0057: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0066: Expected O, but got Unknown
|
||||
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0084: Expected O, but got Unknown
|
||||
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
|
||||
SKPaint val = new SKPaint
|
||||
{
|
||||
Color = new SKColor(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)180),
|
||||
Style = (SKPaintStyle)0
|
||||
};
|
||||
try
|
||||
{
|
||||
canvas.DrawRect(bounds, val);
|
||||
SKPaint val2 = new SKPaint
|
||||
{
|
||||
Color = _titleBarColor,
|
||||
Style = (SKPaintStyle)1,
|
||||
StrokeWidth = 4f,
|
||||
IsAntialias = true,
|
||||
StrokeCap = (SKStrokeCap)1
|
||||
};
|
||||
try
|
||||
{
|
||||
float midX = ((SKRect)(ref bounds)).MidX;
|
||||
float midY = ((SKRect)(ref bounds)).MidY;
|
||||
float num = 20f;
|
||||
SKPath val3 = new SKPath();
|
||||
try
|
||||
{
|
||||
val3.AddArc(new SKRect(midX - num, midY - num, midX + num, midY + num), 0f, 270f);
|
||||
canvas.DrawPath(val3, val2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val3)?.Dispose();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val2)?.Dispose();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val)?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBusyIndicator(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
// Draw semi-transparent overlay
|
||||
using var overlayPaint = new SKPaint
|
||||
{
|
||||
Color = new SKColor(255, 255, 255, 180),
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(bounds, overlayPaint);
|
||||
public void OnAppearing()
|
||||
{
|
||||
Console.WriteLine($"[SkiaPage] OnAppearing called for: {Title}, HasListeners={this.Appearing != null}");
|
||||
this.Appearing?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
// Draw spinning indicator (simplified - would animate in real impl)
|
||||
using var indicatorPaint = new SKPaint
|
||||
{
|
||||
Color = _titleBarColor,
|
||||
Style = SKPaintStyle.Stroke,
|
||||
StrokeWidth = 4,
|
||||
IsAntialias = true,
|
||||
StrokeCap = SKStrokeCap.Round
|
||||
};
|
||||
public void OnDisappearing()
|
||||
{
|
||||
this.Disappearing?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
var centerX = bounds.MidX;
|
||||
var centerY = bounds.MidY;
|
||||
var radius = 20f;
|
||||
protected override SKSize MeasureOverride(SKSize availableSize)
|
||||
{
|
||||
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
||||
return availableSize;
|
||||
}
|
||||
|
||||
using var path = new SKPath();
|
||||
path.AddArc(new SKRect(centerX - radius, centerY - radius, centerX + radius, centerY + radius), 0, 270);
|
||||
canvas.DrawPath(path, indicatorPaint);
|
||||
}
|
||||
public override void OnPointerPressed(PointerEventArgs e)
|
||||
{
|
||||
float num = (_showNavigationBar ? _navigationBarHeight : 0f);
|
||||
if (e.Y > num && _content != null)
|
||||
{
|
||||
PointerEventArgs e2 = new PointerEventArgs(e.X - _paddingLeft, e.Y - num - _paddingTop, e.Button);
|
||||
_content.OnPointerPressed(e2);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAppearing()
|
||||
{
|
||||
Console.WriteLine($"[SkiaPage] OnAppearing called for: {Title}, HasListeners={Appearing != null}");
|
||||
Appearing?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
public override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
float num = (_showNavigationBar ? _navigationBarHeight : 0f);
|
||||
if (e.Y > num && _content != null)
|
||||
{
|
||||
PointerEventArgs e2 = new PointerEventArgs(e.X - _paddingLeft, e.Y - num - _paddingTop, e.Button);
|
||||
_content.OnPointerMoved(e2);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDisappearing()
|
||||
{
|
||||
Disappearing?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
public override void OnPointerReleased(PointerEventArgs e)
|
||||
{
|
||||
float num = (_showNavigationBar ? _navigationBarHeight : 0f);
|
||||
if (e.Y > num && _content != null)
|
||||
{
|
||||
PointerEventArgs e2 = new PointerEventArgs(e.X - _paddingLeft, e.Y - num - _paddingTop, e.Button);
|
||||
_content.OnPointerReleased(e2);
|
||||
}
|
||||
}
|
||||
|
||||
protected override SKSize MeasureOverride(SKSize availableSize)
|
||||
{
|
||||
// Page takes all available space
|
||||
return availableSize;
|
||||
}
|
||||
public override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
_content?.OnKeyDown(e);
|
||||
}
|
||||
|
||||
public override void OnPointerPressed(PointerEventArgs e)
|
||||
{
|
||||
// Adjust coordinates for content
|
||||
var contentTop = _showNavigationBar ? _navigationBarHeight : 0;
|
||||
if (e.Y > contentTop && _content != null)
|
||||
{
|
||||
var contentE = new PointerEventArgs(e.X - _paddingLeft, e.Y - contentTop - _paddingTop, e.Button);
|
||||
_content.OnPointerPressed(contentE);
|
||||
}
|
||||
}
|
||||
public override void OnKeyUp(KeyEventArgs e)
|
||||
{
|
||||
_content?.OnKeyUp(e);
|
||||
}
|
||||
|
||||
public override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
var contentTop = _showNavigationBar ? _navigationBarHeight : 0;
|
||||
if (e.Y > contentTop && _content != null)
|
||||
{
|
||||
var contentE = new PointerEventArgs(e.X - _paddingLeft, e.Y - contentTop - _paddingTop, e.Button);
|
||||
_content.OnPointerMoved(contentE);
|
||||
}
|
||||
}
|
||||
public override void OnScroll(ScrollEventArgs e)
|
||||
{
|
||||
_content?.OnScroll(e);
|
||||
}
|
||||
|
||||
public override void OnPointerReleased(PointerEventArgs e)
|
||||
{
|
||||
var contentTop = _showNavigationBar ? _navigationBarHeight : 0;
|
||||
if (e.Y > contentTop && _content != null)
|
||||
{
|
||||
var contentE = new PointerEventArgs(e.X - _paddingLeft, e.Y - contentTop - _paddingTop, e.Button);
|
||||
_content.OnPointerReleased(contentE);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
_content?.OnKeyDown(e);
|
||||
}
|
||||
|
||||
public override void OnKeyUp(KeyEventArgs e)
|
||||
{
|
||||
_content?.OnKeyUp(e);
|
||||
}
|
||||
|
||||
public override void OnScroll(ScrollEventArgs e)
|
||||
{
|
||||
_content?.OnScroll(e);
|
||||
}
|
||||
|
||||
public override SkiaView? HitTest(float x, float y)
|
||||
{
|
||||
if (!IsVisible)
|
||||
return null;
|
||||
|
||||
// Don't check Bounds.Contains for page - it may not be set
|
||||
// Just forward to content
|
||||
|
||||
// Check content
|
||||
if (_content != null)
|
||||
{
|
||||
var hit = _content.HitTest(x, y);
|
||||
if (hit != null)
|
||||
return hit;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple content page view with toolbar items support.
|
||||
/// </summary>
|
||||
public class SkiaContentPage : SkiaPage
|
||||
{
|
||||
private readonly List<SkiaToolbarItem> _toolbarItems = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the toolbar items for this page.
|
||||
/// </summary>
|
||||
public IList<SkiaToolbarItem> ToolbarItems => _toolbarItems;
|
||||
|
||||
protected override void DrawNavigationBar(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
// Draw navigation bar background
|
||||
using var barPaint = new SKPaint
|
||||
{
|
||||
Color = TitleBarColor,
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(bounds, barPaint);
|
||||
|
||||
// Draw title
|
||||
if (!string.IsNullOrEmpty(Title))
|
||||
{
|
||||
using var font = new SKFont(SKTypeface.Default, 20);
|
||||
using var textPaint = new SKPaint(font)
|
||||
{
|
||||
Color = TitleTextColor,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
var textBounds = new SKRect();
|
||||
textPaint.MeasureText(Title, ref textBounds);
|
||||
|
||||
var x = bounds.Left + 56; // Leave space for back button
|
||||
var y = bounds.MidY - textBounds.MidY;
|
||||
canvas.DrawText(Title, x, y, textPaint);
|
||||
}
|
||||
|
||||
// Draw toolbar items on the right
|
||||
DrawToolbarItems(canvas, bounds);
|
||||
|
||||
// Draw shadow
|
||||
using var shadowPaint = new SKPaint
|
||||
{
|
||||
Color = new SKColor(0, 0, 0, 30),
|
||||
Style = SKPaintStyle.Fill,
|
||||
MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 2)
|
||||
};
|
||||
canvas.DrawRect(new SKRect(bounds.Left, bounds.Bottom, bounds.Right, bounds.Bottom + 4), shadowPaint);
|
||||
}
|
||||
|
||||
private void DrawToolbarItems(SKCanvas canvas, SKRect navBarBounds)
|
||||
{
|
||||
var primaryItems = _toolbarItems.Where(t => t.Order == SkiaToolbarItemOrder.Primary).ToList();
|
||||
Console.WriteLine($"[SkiaContentPage] DrawToolbarItems: {primaryItems.Count} primary items, navBarBounds={navBarBounds}");
|
||||
if (primaryItems.Count == 0) return;
|
||||
|
||||
using var font = new SKFont(SKTypeface.Default, 14);
|
||||
using var textPaint = new SKPaint(font)
|
||||
{
|
||||
Color = TitleTextColor,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
float rightEdge = navBarBounds.Right - 16;
|
||||
|
||||
foreach (var item in primaryItems.AsEnumerable().Reverse())
|
||||
{
|
||||
var textBounds = new SKRect();
|
||||
textPaint.MeasureText(item.Text, ref textBounds);
|
||||
|
||||
var itemWidth = textBounds.Width + 24; // Padding
|
||||
var itemLeft = rightEdge - itemWidth;
|
||||
|
||||
// Store hit area for click handling
|
||||
item.HitBounds = new SKRect(itemLeft, navBarBounds.Top, rightEdge, navBarBounds.Bottom);
|
||||
Console.WriteLine($"[SkiaContentPage] Toolbar item '{item.Text}' HitBounds set to {item.HitBounds}");
|
||||
|
||||
// Draw text
|
||||
var x = itemLeft + 12;
|
||||
var y = navBarBounds.MidY - textBounds.MidY;
|
||||
canvas.DrawText(item.Text, x, y, textPaint);
|
||||
|
||||
rightEdge = itemLeft - 8; // Gap between items
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPointerPressed(PointerEventArgs e)
|
||||
{
|
||||
Console.WriteLine($"[SkiaContentPage] OnPointerPressed at ({e.X}, {e.Y}), ShowNavigationBar={ShowNavigationBar}, NavigationBarHeight={NavigationBarHeight}");
|
||||
Console.WriteLine($"[SkiaContentPage] ToolbarItems count: {_toolbarItems.Count}");
|
||||
|
||||
// Check toolbar item clicks
|
||||
if (ShowNavigationBar && e.Y < NavigationBarHeight)
|
||||
{
|
||||
Console.WriteLine($"[SkiaContentPage] In navigation bar area, checking toolbar items");
|
||||
foreach (var item in _toolbarItems.Where(t => t.Order == SkiaToolbarItemOrder.Primary))
|
||||
{
|
||||
var bounds = item.HitBounds;
|
||||
var contains = bounds.Contains(e.X, e.Y);
|
||||
Console.WriteLine($"[SkiaContentPage] Checking item '{item.Text}', HitBounds=({bounds.Left},{bounds.Top},{bounds.Right},{bounds.Bottom}), Click=({e.X},{e.Y}), Contains={contains}, Command={item.Command != null}");
|
||||
if (contains)
|
||||
{
|
||||
Console.WriteLine($"[SkiaContentPage] Toolbar item clicked: {item.Text}");
|
||||
item.Command?.Execute(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"[SkiaContentPage] No toolbar item hit");
|
||||
}
|
||||
|
||||
base.OnPointerPressed(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a toolbar item in the navigation bar.
|
||||
/// </summary>
|
||||
public class SkiaToolbarItem
|
||||
{
|
||||
public string Text { get; set; } = "";
|
||||
public SkiaToolbarItemOrder Order { get; set; } = SkiaToolbarItemOrder.Primary;
|
||||
public System.Windows.Input.ICommand? Command { get; set; }
|
||||
public SKRect HitBounds { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Order of toolbar items.
|
||||
/// </summary>
|
||||
public enum SkiaToolbarItemOrder
|
||||
{
|
||||
Primary,
|
||||
Secondary
|
||||
public override SkiaView? HitTest(float x, float y)
|
||||
{
|
||||
if (!base.IsVisible)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (_content != null)
|
||||
{
|
||||
SkiaView skiaView = _content.HitTest(x, y);
|
||||
if (skiaView != null)
|
||||
{
|
||||
return skiaView;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user