From 7d2ac327a3232e88288125d2236cd7b4c99de8e2 Mon Sep 17 00:00:00 2001 From: logikonline Date: Sat, 17 Jan 2026 05:22:37 +0000 Subject: [PATCH] More fixes --- Handlers/GtkWebViewProxy.cs | 7 +- Handlers/WindowHandler.cs | 4 +- LinuxApplication.cs | 10 +- Rendering/GpuRenderingEngine.cs | 5 +- Rendering/SkiaRenderingEngine.cs | 5 +- Services/HotkeyKey.cs | 60 ++++++-- Views/LinuxDialogService.cs | 5 +- Views/SkiaActivityIndicator.cs | 4 +- Views/SkiaAlertDialog.cs | 2 +- Views/SkiaBorder.cs | 36 ++--- Views/SkiaBoxView.cs | 16 +- Views/SkiaButton.cs | 4 +- Views/SkiaCarouselView.cs | 24 +-- Views/SkiaCheckBox.cs | 6 +- Views/SkiaCollectionView.cs | 6 +- Views/SkiaContentPresenter.cs | 44 +++--- Views/SkiaDatePicker.cs | 11 +- Views/SkiaEditor.cs | 22 +-- Views/SkiaEntry.cs | 14 +- Views/SkiaFlexLayout.cs | 50 ++++--- Views/SkiaFlyoutPage.cs | 27 ++-- Views/SkiaGraphicsView.cs | 10 +- Views/SkiaImage.cs | 58 ++++---- Views/SkiaImageButton.cs | 61 ++++---- Views/SkiaIndicatorView.cs | 21 +-- Views/SkiaItemsView.cs | 48 +++--- Views/SkiaLabel.cs | 26 ++-- Views/SkiaLayoutView.cs | 126 ++++++++-------- Views/SkiaMenuBar.cs | 17 ++- Views/SkiaNavigationPage.cs | 12 +- Views/SkiaPage.cs | 6 +- Views/SkiaPicker.cs | 17 ++- Views/SkiaProgressBar.cs | 6 +- Views/SkiaRadioButton.cs | 4 +- Views/SkiaRefreshView.cs | 12 +- Views/SkiaScrollView.cs | 165 +++++++++++---------- Views/SkiaSearchBar.cs | 6 +- Views/SkiaShell.cs | 42 +++--- Views/SkiaSlider.cs | 6 +- Views/SkiaStepper.cs | 6 +- Views/SkiaSwipeView.cs | 12 +- Views/SkiaSwitch.cs | 8 +- Views/SkiaTabbedPage.cs | 68 ++++----- Views/SkiaTemplatedView.cs | 11 +- Views/SkiaTimePicker.cs | 11 +- Views/SkiaView.cs | 83 +++++++---- Views/SkiaWebView.cs | 6 +- tests/OpenMaui.Controls.Linux.Tests.csproj | 4 +- tests/Views/SkiaButtonTests.cs | 9 +- tests/Views/SkiaCarouselViewTests.cs | 23 +-- tests/Views/SkiaEntryTests.cs | 9 +- tests/Views/SkiaIndicatorViewTests.cs | 35 ++--- tests/Views/SkiaMenuBarTests.cs | 45 +++--- tests/Views/SkiaRefreshViewTests.cs | 15 +- tests/Views/SkiaScrollViewTests.cs | 23 +-- tests/Views/SkiaSliderTests.cs | 5 +- tests/Views/SkiaStackLayoutTests.cs | 25 ++-- tests/Views/SkiaSwipeViewTests.cs | 17 ++- 58 files changed, 754 insertions(+), 666 deletions(-) diff --git a/Handlers/GtkWebViewProxy.cs b/Handlers/GtkWebViewProxy.cs index ace5afd..7400fc7 100644 --- a/Handlers/GtkWebViewProxy.cs +++ b/Handlers/GtkWebViewProxy.cs @@ -1,6 +1,7 @@ // 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.Graphics; using Microsoft.Maui.Platform; using SkiaSharp; @@ -24,12 +25,12 @@ public class GtkWebViewProxy : SkiaView _platformView = platformView; } - public override void Arrange(SKRect bounds) + public override void Arrange(Rect bounds) { base.Arrange(bounds); // Bounds are already in absolute window coordinates - use them directly // The Skia layout system uses absolute coordinates throughout - _handler.RegisterWithHost(Bounds); + _handler.RegisterWithHost(new SKRect((float)Bounds.Left, (float)Bounds.Top, (float)Bounds.Right, (float)Bounds.Bottom)); } public override void Draw(SKCanvas canvas) @@ -40,7 +41,7 @@ public class GtkWebViewProxy : SkiaView Color = new SKColor(0, 0, 0, 0), Style = SKPaintStyle.Fill }; - canvas.DrawRect(Bounds, paint); + canvas.DrawRect(new SKRect((float)Bounds.Left, (float)Bounds.Top, (float)Bounds.Right, (float)Bounds.Bottom), paint); } public void Navigate(string url) diff --git a/Handlers/WindowHandler.cs b/Handlers/WindowHandler.cs index 7dc08aa..f584158 100644 --- a/Handlers/WindowHandler.cs +++ b/Handlers/WindowHandler.cs @@ -177,8 +177,8 @@ public class SkiaWindow // Draw main content if (_content != null) { - _content.Measure(new SKSize(_width, _height)); - _content.Arrange(new SKRect(0, 0, _width, _height)); + _content.Measure(new Size(_width, _height)); + _content.Arrange(new Rect(0, 0, _width, _height)); _content.Draw(canvas); } diff --git a/LinuxApplication.cs b/LinuxApplication.cs index 8d1d883..1cb5a04 100644 --- a/LinuxApplication.cs +++ b/LinuxApplication.cs @@ -156,7 +156,7 @@ public class LinuxApplication : IDisposable _rootView = value; if (_rootView != null && _mainWindow != null) { - _rootView.Arrange(new SkiaSharp.SKRect( + _rootView.Arrange(new Microsoft.Maui.Graphics.Rect( 0, 0, _mainWindow.Width, _mainWindow.Height)); @@ -542,8 +542,8 @@ public class LinuxApplication : IDisposable { if (_rootView != null) { - _rootView.Measure(new SKSize(width, height)); - _rootView.Arrange(new SKRect(0, 0, width, height)); + _rootView.Measure(new Size(width, height)); + _rootView.Arrange(new Rect(0, 0, width, height)); } } @@ -569,9 +569,9 @@ public class LinuxApplication : IDisposable if (_rootView != null) { // Re-measure with new available size, then arrange - var availableSize = new SkiaSharp.SKSize(size.Width, size.Height); + var availableSize = new Size(size.Width, size.Height); _rootView.Measure(availableSize); - _rootView.Arrange(new SkiaSharp.SKRect(0, 0, size.Width, size.Height)); + _rootView.Arrange(new Rect(0, 0, size.Width, size.Height)); } _renderingEngine?.InvalidateAll(); } diff --git a/Rendering/GpuRenderingEngine.cs b/Rendering/GpuRenderingEngine.cs index 8d0c52e..b253cbb 100644 --- a/Rendering/GpuRenderingEngine.cs +++ b/Rendering/GpuRenderingEngine.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using SkiaSharp; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform.Linux.Window; using System.Runtime.InteropServices; @@ -207,9 +208,9 @@ public class GpuRenderingEngine : IDisposable if (_canvas == null) return; // Measure and arrange - var availableSize = new SKSize(Width, Height); + var availableSize = new Size(Width, Height); rootView.Measure(availableSize); - rootView.Arrange(new SKRect(0, 0, Width, Height)); + rootView.Arrange(new Rect(0, 0, Width, Height)); // Determine regions to redraw List regionsToRedraw; diff --git a/Rendering/SkiaRenderingEngine.cs b/Rendering/SkiaRenderingEngine.cs index 0d5848e..0cf6ee8 100644 --- a/Rendering/SkiaRenderingEngine.cs +++ b/Rendering/SkiaRenderingEngine.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using SkiaSharp; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform.Linux.Window; using Microsoft.Maui.Platform; using System.Runtime.InteropServices; @@ -167,9 +168,9 @@ public class SkiaRenderingEngine : IDisposable return; // Measure and arrange - var availableSize = new SKSize(Width, Height); + var availableSize = new Size(Width, Height); rootView.Measure(availableSize); - rootView.Arrange(new SKRect(0, 0, Width, Height)); + rootView.Arrange(new Rect(0, 0, Width, Height)); // Determine what to redraw List regionsToRedraw; diff --git a/Services/HotkeyKey.cs b/Services/HotkeyKey.cs index 8568981..f686c2b 100644 --- a/Services/HotkeyKey.cs +++ b/Services/HotkeyKey.cs @@ -3,15 +3,55 @@ namespace Microsoft.Maui.Platform.Linux.Services; -public enum HotkeyKey +/// +/// X11 keysym values for global hotkey registration. +/// +public enum HotkeyKey : uint { - None, - A, B, C, D, E, F, G, H, I, J, K, L, M, - N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, - F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - Space, Enter, Escape, Tab, Backspace, Delete, Insert, - Home, End, PageUp, PageDown, - Left, Right, Up, Down, - PrintScreen, Pause, NumLock, ScrollLock, CapsLock + None = 0, + + // Letters (lowercase X11 keysyms) + A = 0x61, B = 0x62, C = 0x63, D = 0x64, E = 0x65, + F = 0x66, G = 0x67, H = 0x68, I = 0x69, J = 0x6A, + K = 0x6B, L = 0x6C, M = 0x6D, N = 0x6E, O = 0x6F, + P = 0x70, Q = 0x71, R = 0x72, S = 0x73, T = 0x74, + U = 0x75, V = 0x76, W = 0x77, X = 0x78, Y = 0x79, + Z = 0x7A, + + // Digits + D0 = 0x30, D1 = 0x31, D2 = 0x32, D3 = 0x33, D4 = 0x34, + D5 = 0x35, D6 = 0x36, D7 = 0x37, D8 = 0x38, D9 = 0x39, + + // Function keys + F1 = 0xFFBE, F2 = 0xFFBF, F3 = 0xFFC0, F4 = 0xFFC1, + F5 = 0xFFC2, F6 = 0xFFC3, F7 = 0xFFC4, F8 = 0xFFC5, + F9 = 0xFFC6, F10 = 0xFFC7, F11 = 0xFFC8, F12 = 0xFFC9, + + // Special keys + Space = 0x20, + Enter = 0xFF0D, + Escape = 0xFF1B, + Tab = 0xFF09, + Backspace = 0xFF08, + Delete = 0xFFFF, + Insert = 0xFF63, + + // Navigation keys + Home = 0xFF50, + End = 0xFF57, + PageUp = 0xFF55, + PageDown = 0xFF56, + + // Arrow keys + Left = 0xFF51, + Right = 0xFF53, + Up = 0xFF52, + Down = 0xFF54, + + // Lock keys + PrintScreen = 0xFF61, + Pause = 0xFF13, + NumLock = 0xFF7F, + ScrollLock = 0xFF14, + CapsLock = 0xFFE5 } diff --git a/Views/LinuxDialogService.cs b/Views/LinuxDialogService.cs index a93aad2..9ac4287 100644 --- a/Views/LinuxDialogService.cs +++ b/Views/LinuxDialogService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Maui.Graphics; using SkiaSharp; namespace Microsoft.Maui.Platform; @@ -64,8 +65,8 @@ public static class LinuxDialogService { foreach (var dialog in _activeDialogs) { - dialog.Measure(new SKSize(bounds.Width, bounds.Height)); - dialog.Arrange(bounds); + dialog.Measure(new Size(bounds.Width, bounds.Height)); + dialog.Arrange(new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height)); dialog.Draw(canvas); } } diff --git a/Views/SkiaActivityIndicator.cs b/Views/SkiaActivityIndicator.cs index 9bb3b98..e52241f 100644 --- a/Views/SkiaActivityIndicator.cs +++ b/Views/SkiaActivityIndicator.cs @@ -284,11 +284,11 @@ public class SkiaActivityIndicator : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { var size = (float)Size; var strokeWidth = (float)StrokeWidth; - return new SKSize(size + strokeWidth * 2, size + strokeWidth * 2); + return new Size(size + strokeWidth * 2, size + strokeWidth * 2); } #endregion diff --git a/Views/SkiaAlertDialog.cs b/Views/SkiaAlertDialog.cs index 4f31c05..e8a8ebd 100644 --- a/Views/SkiaAlertDialog.cs +++ b/Views/SkiaAlertDialog.cs @@ -311,7 +311,7 @@ public class SkiaAlertDialog : SkiaView _tcs.TrySetResult(result); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { // Dialog takes full screen for the overlay return availableSize; diff --git a/Views/SkiaBorder.cs b/Views/SkiaBorder.cs index 03c2fc6..75bc3b9 100644 --- a/Views/SkiaBorder.cs +++ b/Views/SkiaBorder.cs @@ -423,7 +423,7 @@ public class SkiaBorder : SkiaLayoutView protected override SKRect GetContentBounds() { - return GetContentBounds(Bounds); + return GetContentBounds(new SKRect((float)Bounds.Left, (float)Bounds.Top, (float)Bounds.Right, (float)Bounds.Bottom)); } protected new SKRect GetContentBounds(SKRect bounds) @@ -437,7 +437,7 @@ public class SkiaBorder : SkiaLayoutView bounds.Bottom - (float)padding.Bottom - strokeThickness); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { float strokeThickness = (float)StrokeThickness; var padding = BorderPadding; @@ -445,43 +445,43 @@ public class SkiaBorder : SkiaLayoutView float paddingHeight = (float)(padding.Top + padding.Bottom) + strokeThickness * 2f; // Respect explicit size requests - var requestedWidth = WidthRequest >= 0.0 ? (float)WidthRequest : availableSize.Width; - var requestedHeight = HeightRequest >= 0.0 ? (float)HeightRequest : availableSize.Height; + var requestedWidth = WidthRequest >= 0.0 ? (float)WidthRequest : (float)availableSize.Width; + var requestedHeight = HeightRequest >= 0.0 ? (float)HeightRequest : (float)availableSize.Height; - var childAvailable = new SKSize( + var childAvailable = new Size( Math.Max(0f, requestedWidth - paddingWidth), Math.Max(0f, requestedHeight - paddingHeight)); - var maxChildSize = SKSize.Empty; + var maxChildSize = Size.Zero; foreach (var child in Children) { var childSize = child.Measure(childAvailable); - maxChildSize = new SKSize( + maxChildSize = new Size( Math.Max(maxChildSize.Width, childSize.Width), Math.Max(maxChildSize.Height, childSize.Height)); } // Use requested size if set, otherwise use child size + padding - var width = WidthRequest >= 0.0 ? (float)WidthRequest : maxChildSize.Width + paddingWidth; - var height = HeightRequest >= 0.0 ? (float)HeightRequest : maxChildSize.Height + paddingHeight; + var width = WidthRequest >= 0.0 ? (float)WidthRequest : (float)maxChildSize.Width + paddingWidth; + var height = HeightRequest >= 0.0 ? (float)HeightRequest : (float)maxChildSize.Height + paddingHeight; - return new SKSize(width, height); + return new Size(width, height); } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { - var contentBounds = GetContentBounds(bounds); + var contentBounds = GetContentBounds(new SKRect((float)bounds.Left, (float)bounds.Top, (float)bounds.Right, (float)bounds.Bottom)); foreach (var child in Children) { // Apply child's margin var margin = child.Margin; - var marginedBounds = new SKRect( - contentBounds.Left + (float)margin.Left, - contentBounds.Top + (float)margin.Top, - contentBounds.Right - (float)margin.Right, - contentBounds.Bottom - (float)margin.Bottom); + var marginedBounds = new Rect( + contentBounds.Left + margin.Left, + contentBounds.Top + margin.Top, + contentBounds.Width - margin.Left - margin.Right, + contentBounds.Height - margin.Top - margin.Bottom); child.Arrange(marginedBounds); } @@ -515,7 +515,7 @@ public class SkiaBorder : SkiaLayoutView if (IsVisible && IsEnabled) { var bounds = Bounds; - if (bounds.Contains(new SKPoint(x, y))) + if (bounds.Contains(x, y)) { if (HasTapGestureRecognizers()) { diff --git a/Views/SkiaBoxView.cs b/Views/SkiaBoxView.cs index c4f0a45..cecc095 100644 --- a/Views/SkiaBoxView.cs +++ b/Views/SkiaBoxView.cs @@ -103,19 +103,19 @@ public class SkiaBoxView : SkiaView #region Measurement - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { // BoxView uses explicit size or a default size when in unbounded context - var width = WidthRequest >= 0 ? (float)WidthRequest : - (float.IsInfinity(availableSize.Width) ? 40f : availableSize.Width); - var height = HeightRequest >= 0 ? (float)HeightRequest : - (float.IsInfinity(availableSize.Height) ? 40f : availableSize.Height); + var width = WidthRequest >= 0 ? WidthRequest : + (double.IsInfinity(availableSize.Width) ? 40.0 : availableSize.Width); + var height = HeightRequest >= 0 ? HeightRequest : + (double.IsInfinity(availableSize.Height) ? 40.0 : availableSize.Height); // Ensure no NaN values - if (float.IsNaN(width)) width = 40f; - if (float.IsNaN(height)) height = 40f; + if (double.IsNaN(width)) width = 40.0; + if (double.IsNaN(height)) height = 40.0; - return new SKSize(width, height); + return new Size(width, height); } #endregion diff --git a/Views/SkiaButton.cs b/Views/SkiaButton.cs index ab214ae..d0a8296 100644 --- a/Views/SkiaButton.cs +++ b/Views/SkiaButton.cs @@ -940,7 +940,7 @@ public class SkiaButton : SkiaView, IButtonController #region Measurement - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { var padding = Padding; float paddingH = (float)(padding.Left + padding.Right); @@ -1037,7 +1037,7 @@ public class SkiaButton : SkiaView, IButtonController height = (float)HeightRequest; } - return new SKSize(Math.Max(width, 44f), Math.Max(height, 30f)); + return new Size(Math.Max(width, 44f), Math.Max(height, 30f)); } #endregion diff --git a/Views/SkiaCarouselView.cs b/Views/SkiaCarouselView.cs index 201f777..53dac66 100644 --- a/Views/SkiaCarouselView.cs +++ b/Views/SkiaCarouselView.cs @@ -204,39 +204,39 @@ public class SkiaCarouselView : SkiaLayoutView private float GetOffsetForPosition(int position) { - float itemWidth = Bounds.Width - (float)PeekAreaInsets * 2; + float itemWidth = (float)Bounds.Width - (float)PeekAreaInsets * 2; return position * (itemWidth + (float)ItemSpacing); } private int GetPositionForOffset(float offset) { - float itemWidth = Bounds.Width - (float)PeekAreaInsets * 2; + float itemWidth = (float)Bounds.Width - (float)PeekAreaInsets * 2; if (itemWidth <= 0) return 0; return Math.Clamp((int)Math.Round(offset / (itemWidth + (float)ItemSpacing)), 0, Math.Max(0, _items.Count - 1)); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - float itemWidth = availableSize.Width - (float)PeekAreaInsets * 2; - float itemHeight = availableSize.Height - (ShowIndicators ? 30 : 0); + float itemWidth = (float)availableSize.Width - (float)PeekAreaInsets * 2; + float itemHeight = (float)availableSize.Height - (ShowIndicators ? 30 : 0); foreach (var item in _items) { - item.Measure(new SKSize(itemWidth, itemHeight)); + item.Measure(new Size(itemWidth, itemHeight)); } return availableSize; } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { - float itemWidth = bounds.Width - (float)PeekAreaInsets * 2; - float itemHeight = bounds.Height - (ShowIndicators ? 30 : 0); + float itemWidth = (float)bounds.Width - (float)PeekAreaInsets * 2; + float itemHeight = (float)bounds.Height - (ShowIndicators ? 30 : 0); for (int i = 0; i < _items.Count; i++) { - float x = bounds.Left + (float)PeekAreaInsets + i * (itemWidth + (float)ItemSpacing) - _scrollOffset; - var itemBounds = new SKRect(x, bounds.Top, x + itemWidth, bounds.Top + itemHeight); + float x = (float)bounds.Left + (float)PeekAreaInsets + i * (itemWidth + (float)ItemSpacing) - _scrollOffset; + var itemBounds = new Rect(x, bounds.Top, itemWidth, itemHeight); _items[i].Arrange(itemBounds); } @@ -389,7 +389,7 @@ public class SkiaCarouselView : SkiaLayoutView _isDragging = false; // Determine target position based on velocity and position - float itemWidth = Bounds.Width - (float)PeekAreaInsets * 2; + float itemWidth = (float)Bounds.Width - (float)PeekAreaInsets * 2; int targetPosition = GetPositionForOffset(_scrollOffset); // Apply velocity influence diff --git a/Views/SkiaCheckBox.cs b/Views/SkiaCheckBox.cs index 0e142d8..d2b27fc 100644 --- a/Views/SkiaCheckBox.cs +++ b/Views/SkiaCheckBox.cs @@ -431,10 +431,10 @@ public class SkiaCheckBox : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - var boxSize = (float)BoxSize; - return new SKSize(boxSize + 8f, boxSize + 8f); + var boxSize = BoxSize; + return new Size(boxSize + 8.0, boxSize + 8.0); } #endregion diff --git a/Views/SkiaCollectionView.cs b/Views/SkiaCollectionView.cs index cee8663..d60a39b 100644 --- a/Views/SkiaCollectionView.cs +++ b/Views/SkiaCollectionView.cs @@ -420,10 +420,10 @@ public class SkiaCollectionView : SkiaItemsView { try { - var availableSize = new SKSize(bounds.Width, float.MaxValue); + var availableSize = new Size(bounds.Width, float.MaxValue); var measuredSize = itemView.Measure(availableSize); - var rawHeight = measuredSize.Height; + var rawHeight = (float)measuredSize.Height; if (float.IsNaN(rawHeight) || float.IsInfinity(rawHeight) || rawHeight > 10000f) { rawHeight = ItemHeight; @@ -437,7 +437,7 @@ public class SkiaCollectionView : SkiaItemsView } var actualBounds = new SKRect(bounds.Left, bounds.Top, bounds.Right, bounds.Top + measuredHeight); - itemView.Arrange(actualBounds); + itemView.Arrange(new Rect(actualBounds.Left, actualBounds.Top, actualBounds.Width, actualBounds.Height)); itemView.Draw(canvas); if (isSelected) diff --git a/Views/SkiaContentPresenter.cs b/Views/SkiaContentPresenter.cs index 8981cd0..deee3de 100644 --- a/Views/SkiaContentPresenter.cs +++ b/Views/SkiaContentPresenter.cs @@ -125,42 +125,42 @@ public class SkiaContentPresenter : SkiaView Content?.Draw(canvas); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { var padding = Padding; - var paddingLeft = (float)padding.Left; - var paddingTop = (float)padding.Top; - var paddingRight = (float)padding.Right; - var paddingBottom = (float)padding.Bottom; + var paddingLeft = padding.Left; + var paddingTop = padding.Top; + var paddingRight = padding.Right; + var paddingBottom = padding.Bottom; if (Content == null) - return new SKSize(paddingLeft + paddingRight, paddingTop + paddingBottom); + return new Size(paddingLeft + paddingRight, paddingTop + paddingBottom); // When alignment is not Fill, give content unlimited size in that dimension // so it can measure its natural size without truncation var measureWidth = HorizontalContentAlignment == LayoutAlignment.Fill - ? Math.Max(0, availableSize.Width - paddingLeft - paddingRight) + ? (float)Math.Max(0, availableSize.Width - paddingLeft - paddingRight) : float.PositiveInfinity; var measureHeight = VerticalContentAlignment == LayoutAlignment.Fill - ? Math.Max(0, availableSize.Height - paddingTop - paddingBottom) + ? (float)Math.Max(0, availableSize.Height - paddingTop - paddingBottom) : float.PositiveInfinity; - var contentSize = Content.Measure(new SKSize(measureWidth, measureHeight)); - return new SKSize( + var contentSize = Content.Measure(new Size(measureWidth, measureHeight)); + return new Size( contentSize.Width + paddingLeft + paddingRight, contentSize.Height + paddingTop + paddingBottom); } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { if (Content != null) { var padding = Padding; - var contentBounds = new SKRect( - bounds.Left + (float)padding.Left, - bounds.Top + (float)padding.Top, - bounds.Right - (float)padding.Right, - bounds.Bottom - (float)padding.Bottom); + var contentBounds = new Rect( + bounds.Left + padding.Left, + bounds.Top + padding.Top, + bounds.Width - padding.Left - padding.Right, + bounds.Height - padding.Top - padding.Bottom); // Apply alignment var contentSize = Content.DesiredSize; @@ -171,12 +171,12 @@ public class SkiaContentPresenter : SkiaView return bounds; } - private static SKRect ApplyAlignment(SKRect availableBounds, SKSize contentSize, LayoutAlignment horizontal, LayoutAlignment vertical) + private static Rect ApplyAlignment(Rect availableBounds, Size contentSize, LayoutAlignment horizontal, LayoutAlignment vertical) { - float x = availableBounds.Left; - float y = availableBounds.Top; - float width = horizontal == LayoutAlignment.Fill ? availableBounds.Width : contentSize.Width; - float height = vertical == LayoutAlignment.Fill ? availableBounds.Height : contentSize.Height; + double x = availableBounds.Left; + double y = availableBounds.Top; + double width = horizontal == LayoutAlignment.Fill ? availableBounds.Width : contentSize.Width; + double height = vertical == LayoutAlignment.Fill ? availableBounds.Height : contentSize.Height; // Horizontal alignment switch (horizontal) @@ -200,7 +200,7 @@ public class SkiaContentPresenter : SkiaView break; } - return new SKRect(x, y, x + width, y + height); + return new Rect(x, y, width, height); } public override SkiaView? HitTest(float x, float y) diff --git a/Views/SkiaDatePicker.cs b/Views/SkiaDatePicker.cs index e14a803..9a81e98 100644 --- a/Views/SkiaDatePicker.cs +++ b/Views/SkiaDatePicker.cs @@ -299,7 +299,8 @@ public class SkiaDatePicker : SkiaView { if (_isOpen) { - DrawCalendar(canvas, ScreenBounds); + var skScreenBounds = new SKRect((float)ScreenBounds.Left, (float)ScreenBounds.Top, (float)(ScreenBounds.Left + ScreenBounds.Width), (float)(ScreenBounds.Top + ScreenBounds.Height)); + DrawCalendar(canvas, skScreenBounds); } } @@ -579,7 +580,7 @@ public class SkiaDatePicker : SkiaView if (IsOpen) { - SKRect screenBounds = ScreenBounds; + SKRect screenBounds = new SKRect((float)ScreenBounds.Left, (float)ScreenBounds.Top, (float)(ScreenBounds.Left + ScreenBounds.Width), (float)(ScreenBounds.Top + ScreenBounds.Height)); SKRect calendarRect = GetCalendarRect(screenBounds); SKRect headerRect = new SKRect(calendarRect.Left, calendarRect.Top, calendarRect.Right, calendarRect.Top + 48f); @@ -680,14 +681,14 @@ public class SkiaDatePicker : SkiaView } } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - return new SKSize(availableSize.Width < float.MaxValue ? Math.Min(availableSize.Width, 200f) : 200f, 40f); + return new Size(availableSize.Width < double.MaxValue ? Math.Min(availableSize.Width, 200.0) : 200.0, 40.0); } protected override bool HitTestPopupArea(float x, float y) { - SKRect screenBounds = ScreenBounds; + SKRect screenBounds = new SKRect((float)ScreenBounds.Left, (float)ScreenBounds.Top, (float)(ScreenBounds.Left + ScreenBounds.Width), (float)(ScreenBounds.Top + ScreenBounds.Height)); if (screenBounds.Contains(x, y)) { return true; diff --git a/Views/SkiaEditor.cs b/Views/SkiaEditor.cs index ebb9e94..ad52832 100644 --- a/Views/SkiaEditor.cs +++ b/Views/SkiaEditor.cs @@ -1075,9 +1075,9 @@ public class SkiaEditor : SkiaView, IInputContext { _scrollOffsetY = cursorY; } - else if (cursorY + lineSpacing > _scrollOffsetY + viewHeight) + else if (cursorY + lineSpacing > _scrollOffsetY + (float)viewHeight) { - _scrollOffsetY = cursorY + lineSpacing - viewHeight; + _scrollOffsetY = cursorY + lineSpacing - (float)viewHeight; } } @@ -1377,7 +1377,7 @@ public class SkiaEditor : SkiaView, IInputContext var lineHeight = (float)LineHeight; var lineSpacing = fontSize * lineHeight; var totalHeight = _lines.Count * lineSpacing; - var viewHeight = Bounds.Height - (float)(Padding.Top + Padding.Bottom); + var viewHeight = (float)Bounds.Height - (float)(Padding.Top + Padding.Bottom); var maxScroll = Math.Max(0, totalHeight - viewHeight); _scrollOffsetY = Math.Clamp(_scrollOffsetY - e.DeltaY * 3, 0, maxScroll); @@ -1578,22 +1578,22 @@ public class SkiaEditor : SkiaView, IInputContext _inputMethodService.SetCursorLocation(x, y, 2, height); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { if (AutoSize) { var fontSize = (float)FontSize; var lineHeight = (float)LineHeight; var lineSpacing = fontSize * lineHeight; - var verticalPadding = (float)(Padding.Top + Padding.Bottom); + var verticalPadding = Padding.Top + Padding.Bottom; var height = Math.Max(lineSpacing + verticalPadding, _lines.Count * lineSpacing + verticalPadding); - return new SKSize( - availableSize.Width < float.MaxValue ? availableSize.Width : 200, - (float)Math.Min(height, availableSize.Height < float.MaxValue ? availableSize.Height : 200)); + return new Size( + availableSize.Width < double.MaxValue ? availableSize.Width : 200, + Math.Min(height, availableSize.Height < double.MaxValue ? availableSize.Height : 200)); } - return new SKSize( - availableSize.Width < float.MaxValue ? Math.Min(availableSize.Width, 200) : 200, - availableSize.Height < float.MaxValue ? Math.Min(availableSize.Height, 150) : 150); + return new Size( + availableSize.Width < double.MaxValue ? Math.Min(availableSize.Width, 200) : 200, + availableSize.Height < double.MaxValue ? Math.Min(availableSize.Height, 150) : 150); } } diff --git a/Views/SkiaEntry.cs b/Views/SkiaEntry.cs index de2edfa..402da67 100644 --- a/Views/SkiaEntry.cs +++ b/Views/SkiaEntry.cs @@ -1367,8 +1367,8 @@ public class SkiaEntry : SkiaView, IInputContext { var clearButtonSize = 20f; var clearButtonMargin = 8f; - var clearCenterX = Bounds.Right - clearButtonMargin - clearButtonSize / 2; - var clearCenterY = Bounds.MidY; + var clearCenterX = (float)(Bounds.Left + Bounds.Width) - clearButtonMargin - clearButtonSize / 2; + var clearCenterY = (float)(Bounds.Top + Bounds.Height / 2); var dx = e.X - clearCenterX; var dy = e.Y - clearCenterY; @@ -1385,7 +1385,7 @@ public class SkiaEntry : SkiaView, IInputContext // Calculate cursor position from click using screen coordinates var screenBounds = ScreenBounds; - var clickX = e.X - screenBounds.Left - (float)Padding.Left + _scrollOffset; + var clickX = e.X - (float)screenBounds.Left - (float)Padding.Left + _scrollOffset; _cursorPosition = GetCharacterIndexAtX(clickX); // Check for double-click (select word) @@ -1446,7 +1446,7 @@ public class SkiaEntry : SkiaView, IInputContext // Extend selection to current mouse position var screenBounds = ScreenBounds; - var clickX = e.X - screenBounds.Left - (float)Padding.Left + _scrollOffset; + var clickX = e.X - (float)screenBounds.Left - (float)Padding.Left + _scrollOffset; var newPosition = GetCharacterIndexAtX(clickX); if (newPosition != _cursorPosition) @@ -1675,7 +1675,7 @@ public class SkiaEntry : SkiaView, IInputContext _inputMethodService.SetCursorLocation(x, y, 2, height); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { var fontStyle = GetFontStyle(); var typeface = SkiaRenderingEngine.Current?.ResourceCache.GetTypeface(GetEffectiveFontFamily(), fontStyle) @@ -1688,9 +1688,9 @@ public class SkiaEntry : SkiaView, IInputContext var metrics = font.Metrics; var textHeight = metrics.Descent - metrics.Ascent + metrics.Leading; - return new SKSize( + return new Size( 200, // Default width, will be overridden by layout - textHeight + (float)Padding.Top + (float)Padding.Bottom + (float)BorderWidth * 2); + textHeight + Padding.Top + Padding.Bottom + BorderWidth * 2); } } diff --git a/Views/SkiaFlexLayout.cs b/Views/SkiaFlexLayout.cs index bc894d9..c30dd8d 100644 --- a/Views/SkiaFlexLayout.cs +++ b/Views/SkiaFlexLayout.cs @@ -88,34 +88,36 @@ public class SkiaFlexLayout : SkiaLayoutView public static FlexAlignSelf GetAlignSelf(SkiaView view) => (FlexAlignSelf)view.GetValue(AlignSelfProperty); public static void SetAlignSelf(SkiaView view, FlexAlignSelf value) => view.SetValue(AlignSelfProperty, value); - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { bool isRow = Direction == FlexDirection.Row || Direction == FlexDirection.RowReverse; float totalMain = 0f; float maxCross = 0f; + var sizeAvailable = new Size(availableSize.Width, availableSize.Height); + foreach (var child in Children) { if (!child.IsVisible) continue; - var childSize = child.Measure(availableSize); + var childSize = child.Measure(sizeAvailable); if (isRow) { - totalMain += childSize.Width; - maxCross = Math.Max(maxCross, childSize.Height); + totalMain += (float)childSize.Width; + maxCross = Math.Max(maxCross, (float)childSize.Height); } else { - totalMain += childSize.Height; - maxCross = Math.Max(maxCross, childSize.Width); + totalMain += (float)childSize.Height; + maxCross = Math.Max(maxCross, (float)childSize.Width); } } - return isRow ? new SKSize(totalMain, maxCross) : new SKSize(maxCross, totalMain); + return isRow ? new Size(totalMain, maxCross) : new Size(maxCross, totalMain); } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { if (Children.Count == 0) return bounds; @@ -127,10 +129,10 @@ public class SkiaFlexLayout : SkiaLayoutView if (orderedChildren.Count == 0) return bounds; - float mainSize = isRow ? bounds.Width : bounds.Height; - float crossSize = isRow ? bounds.Height : bounds.Width; + float mainSize = isRow ? (float)bounds.Width : (float)bounds.Height; + float crossSize = isRow ? (float)bounds.Height : (float)bounds.Width; - var childInfos = new List<(SkiaView child, SKSize size, float grow, float shrink)>(); + var childInfos = new List<(SkiaView child, Size size, float grow, float shrink)>(); float totalBasis = 0f; float totalGrow = 0f; float totalShrink = 0f; @@ -141,21 +143,21 @@ public class SkiaFlexLayout : SkiaLayoutView float grow = GetGrow(child); float shrink = GetShrink(child); - SKSize size; + Size size; if (basis.IsAuto) { - size = child.Measure(new SKSize(bounds.Width, bounds.Height)); + size = child.Measure(new Size(bounds.Width, bounds.Height)); } else { float length = basis.Length; size = isRow - ? child.Measure(new SKSize(length, bounds.Height)) - : child.Measure(new SKSize(bounds.Width, length)); + ? child.Measure(new Size(length, bounds.Height)) + : child.Measure(new Size(bounds.Width, length)); } childInfos.Add((child, size, grow, shrink)); - totalBasis += isRow ? size.Width : size.Height; + totalBasis += isRow ? (float)size.Width : (float)size.Height; totalGrow += grow; totalShrink += shrink; } @@ -165,8 +167,8 @@ public class SkiaFlexLayout : SkiaLayoutView var resolvedSizes = new List<(SkiaView child, float mainSize, float crossSize)>(); foreach (var (child, size, grow, shrink) in childInfos) { - float childMainSize = isRow ? size.Width : size.Height; - float childCrossSize = isRow ? size.Height : size.Width; + float childMainSize = isRow ? (float)size.Width : (float)size.Height; + float childCrossSize = isRow ? (float)size.Height : (float)size.Width; if (freeSpace > 0f && totalGrow > 0f) { @@ -183,7 +185,7 @@ public class SkiaFlexLayout : SkiaLayoutView float usedSpace = resolvedSizes.Sum(s => s.mainSize); float remainingSpace = Math.Max(0f, mainSize - usedSpace); - float position = isRow ? bounds.Left : bounds.Top; + float position = isRow ? (float)bounds.Left : (float)bounds.Top; float spacing = 0f; switch (JustifyContent) @@ -221,13 +223,13 @@ public class SkiaFlexLayout : SkiaLayoutView var alignSelf = GetAlignSelf(child); var effectiveAlign = alignSelf == FlexAlignSelf.Auto ? AlignItems : (FlexAlignItems)alignSelf; - float crossPos = isRow ? bounds.Top : bounds.Left; + float crossPos = isRow ? (float)bounds.Top : (float)bounds.Left; float finalCrossSize = childCrossSize; switch (effectiveAlign) { case FlexAlignItems.End: - crossPos = (isRow ? bounds.Bottom : bounds.Right) - finalCrossSize; + crossPos = (isRow ? (float)bounds.Bottom : (float)bounds.Right) - finalCrossSize; break; case FlexAlignItems.Center: crossPos += (crossSize - finalCrossSize) / 2f; @@ -237,14 +239,14 @@ public class SkiaFlexLayout : SkiaLayoutView break; } - SKRect childBounds; + Rect childBounds; if (isRow) { - childBounds = new SKRect(position, crossPos, position + childMainSize, crossPos + finalCrossSize); + childBounds = new Rect(position, crossPos, childMainSize, finalCrossSize); } else { - childBounds = new SKRect(crossPos, position, crossPos + finalCrossSize, position + childMainSize); + childBounds = new Rect(crossPos, position, finalCrossSize, childMainSize); } child.Arrange(childBounds); diff --git a/Views/SkiaFlyoutPage.cs b/Views/SkiaFlyoutPage.cs index ac8f4d2..70d539d 100644 --- a/Views/SkiaFlyoutPage.cs +++ b/Views/SkiaFlyoutPage.cs @@ -154,40 +154,36 @@ public class SkiaFlyoutPage : SkiaLayoutView /// public event EventHandler? IsPresentedChanged; - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { // Measure flyout if (_flyout != null) { - _flyout.Measure(new SKSize(FlyoutWidth, availableSize.Height)); + _flyout.Measure(new Size(FlyoutWidth, availableSize.Height)); } // Measure detail to full size if (_detail != null) { - _detail.Measure(availableSize); + _detail.Measure(new Size(availableSize.Width, availableSize.Height)); } return availableSize; } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { // Arrange detail to fill the entire area if (_detail != null) { - _detail.Arrange(bounds); + _detail.Arrange(new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height)); } // Arrange flyout (positioned based on animation progress) if (_flyout != null) { - float flyoutX = bounds.Left - FlyoutWidth + (FlyoutWidth * _flyoutAnimationProgress); - var flyoutBounds = new SKRect( - flyoutX, - bounds.Top, - flyoutX + FlyoutWidth, - bounds.Bottom); + float flyoutX = (float)bounds.Left - FlyoutWidth + (FlyoutWidth * _flyoutAnimationProgress); + var flyoutBounds = new Rect(flyoutX, bounds.Top, FlyoutWidth, bounds.Height); _flyout.Arrange(flyoutBounds); } @@ -211,7 +207,8 @@ public class SkiaFlyoutPage : SkiaLayoutView Color = _scrimColorSK.WithAlpha((byte)(_scrimColorSK.Alpha * _flyoutAnimationProgress)), Style = SKPaintStyle.Fill }; - canvas.DrawRect(Bounds, scrimPaint); + var skBounds = new SKRect((float)Bounds.Left, (float)Bounds.Top, (float)(Bounds.Left + Bounds.Width), (float)(Bounds.Top + Bounds.Height)); + canvas.DrawRect(skBounds, scrimPaint); // Draw flyout shadow if (_flyout != null && ShadowWidth > 0) @@ -230,12 +227,12 @@ public class SkiaFlyoutPage : SkiaLayoutView { if (_flyout == null) return; - float shadowRight = _flyout.Bounds.Right; + float shadowRight = (float)(_flyout.Bounds.Left + _flyout.Bounds.Width); var shadowRect = new SKRect( shadowRight, - Bounds.Top, + (float)Bounds.Top, shadowRight + ShadowWidth, - Bounds.Bottom); + (float)(Bounds.Top + Bounds.Height)); using var shadowPaint = new SKPaint { diff --git a/Views/SkiaGraphicsView.cs b/Views/SkiaGraphicsView.cs index 8e83cd9..a2f5613 100644 --- a/Views/SkiaGraphicsView.cs +++ b/Views/SkiaGraphicsView.cs @@ -49,17 +49,17 @@ public class SkiaGraphicsView : SkiaView } } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { // Graphics view takes all available space by default - if (availableSize.Width < float.MaxValue && availableSize.Height < float.MaxValue) + if (availableSize.Width < double.MaxValue && availableSize.Height < double.MaxValue) { return availableSize; } // Return a reasonable default size - return new SKSize( - availableSize.Width < float.MaxValue ? availableSize.Width : 100, - availableSize.Height < float.MaxValue ? availableSize.Height : 100); + return new Size( + availableSize.Width < double.MaxValue ? availableSize.Width : 100, + availableSize.Height < double.MaxValue ? availableSize.Height : 100); } } diff --git a/Views/SkiaImage.cs b/Views/SkiaImage.cs index 93aeb0a..bd0b11e 100644 --- a/Views/SkiaImage.cs +++ b/Views/SkiaImage.cs @@ -1028,7 +1028,7 @@ public class SkiaImage : SkiaView Invalidate(); } - public override void Arrange(SKRect bounds) + public override void Arrange(Rect bounds) { base.Arrange(bounds); @@ -1037,21 +1037,21 @@ public class SkiaImage : SkiaView { if (_isSvg && !string.IsNullOrEmpty(_currentFilePath) && !_isLoading) { - float width = bounds.Width; - float height = bounds.Height; + float width = (float)bounds.Width; + float height = (float)bounds.Height; if ((width > _svgLoadedWidth * 1.1 || height > _svgLoadedHeight * 1.1) && width > 0f && height > 0f && (width != _lastArrangedBounds.Width || height != _lastArrangedBounds.Height)) { - _lastArrangedBounds = bounds; + _lastArrangedBounds = new SKRect((float)bounds.Left, (float)bounds.Top, (float)bounds.Right, (float)bounds.Bottom); _ = LoadSvgAtSizeAsync(_currentFilePath, width, height); } } } } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { var desiredWidth = DesiredSize.Width; var desiredHeight = DesiredSize.Height; @@ -1059,38 +1059,38 @@ public class SkiaImage : SkiaView if (desiredWidth > 0 && desiredHeight > 0 && (desiredWidth < bounds.Width || desiredHeight < bounds.Height)) { - float finalWidth = Math.Min(desiredWidth, bounds.Width); - float finalHeight = Math.Min(desiredHeight, bounds.Height); + double finalWidth = Math.Min(desiredWidth, bounds.Width); + double finalHeight = Math.Min(desiredHeight, bounds.Height); - float x = bounds.Left; + double x = bounds.Left; var hAlignValue = (int)HorizontalOptions.Alignment; if (hAlignValue == 1) x = bounds.Left + (bounds.Width - finalWidth) / 2; else if (hAlignValue == 2) x = bounds.Right - finalWidth; - float y = bounds.Top; + double y = bounds.Top; var vAlignValue = (int)VerticalOptions.Alignment; if (vAlignValue == 1) y = bounds.Top + (bounds.Height - finalHeight) / 2; else if (vAlignValue == 2) y = bounds.Bottom - finalHeight; - return new SKRect(x, y, x + finalWidth, y + finalHeight); + return new Rect(x, y, finalWidth, finalHeight); } return bounds; } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { double widthRequest = base.WidthRequest; double heightRequest = base.HeightRequest; if (widthRequest > 0.0 && heightRequest > 0.0) - return new SKSize((float)widthRequest, (float)heightRequest); + return new Size(widthRequest, heightRequest); if (_image == null) { - if (widthRequest > 0.0) return new SKSize((float)widthRequest, (float)widthRequest); - if (heightRequest > 0.0) return new SKSize((float)heightRequest, (float)heightRequest); - return new SKSize(100f, 100f); + if (widthRequest > 0.0) return new Size(widthRequest, widthRequest); + if (heightRequest > 0.0) return new Size(heightRequest, heightRequest); + return new Size(100.0, 100.0); } float imageWidth = _image.Width; @@ -1098,35 +1098,35 @@ public class SkiaImage : SkiaView if (widthRequest > 0.0) { - float scale = (float)widthRequest / imageWidth; - return new SKSize((float)widthRequest, imageHeight * scale); + double scale = widthRequest / imageWidth; + return new Size(widthRequest, imageHeight * scale); } if (heightRequest > 0.0) { - float scale = (float)heightRequest / imageHeight; - return new SKSize(imageWidth * scale, (float)heightRequest); + double scale = heightRequest / imageHeight; + return new Size(imageWidth * scale, heightRequest); } - if (availableSize.Width < float.MaxValue && availableSize.Height < float.MaxValue) + if (availableSize.Width < double.MaxValue && availableSize.Height < double.MaxValue) { - float scale = Math.Min(availableSize.Width / imageWidth, availableSize.Height / imageHeight); - return new SKSize(imageWidth * scale, imageHeight * scale); + double scale = Math.Min(availableSize.Width / imageWidth, availableSize.Height / imageHeight); + return new Size(imageWidth * scale, imageHeight * scale); } - if (availableSize.Width < float.MaxValue) + if (availableSize.Width < double.MaxValue) { - float scale = availableSize.Width / imageWidth; - return new SKSize(availableSize.Width, imageHeight * scale); + double scale = availableSize.Width / imageWidth; + return new Size(availableSize.Width, imageHeight * scale); } - if (availableSize.Height < float.MaxValue) + if (availableSize.Height < double.MaxValue) { - float scale = availableSize.Height / imageHeight; - return new SKSize(imageWidth * scale, availableSize.Height); + double scale = availableSize.Height / imageHeight; + return new Size(imageWidth * scale, availableSize.Height); } - return new SKSize(imageWidth, imageHeight); + return new Size(imageWidth, imageHeight); } protected override void Dispose(bool disposing) diff --git a/Views/SkiaImageButton.cs b/Views/SkiaImageButton.cs index 5040bfb..22bea11 100644 --- a/Views/SkiaImageButton.cs +++ b/Views/SkiaImageButton.cs @@ -641,7 +641,7 @@ public class SkiaImageButton : SkiaView Released?.Invoke(this, EventArgs.Empty); - if (wasPressed && Bounds.Contains(new SKPoint(e.X, e.Y))) + if (wasPressed && Bounds.Contains(e.X, e.Y)) { Clicked?.Invoke(this, EventArgs.Empty); ExecuteCommand(); @@ -687,66 +687,65 @@ public class SkiaImageButton : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { var padding = Padding; - var paddingWidth = (float)(padding.Left + padding.Right); - var paddingHeight = (float)(padding.Top + padding.Bottom); + var paddingWidth = padding.Left + padding.Right; + var paddingHeight = padding.Top + padding.Bottom; // Respect explicit WidthRequest/HeightRequest first (MAUI standard behavior) if (WidthRequest > 0 && HeightRequest > 0) { - return new SKSize((float)WidthRequest, (float)HeightRequest); + return new Size(WidthRequest, HeightRequest); } if (WidthRequest > 0) { // Fixed width, calculate height from aspect ratio or use width - float height = HeightRequest > 0 ? (float)HeightRequest - : _image != null ? (float)WidthRequest * _image.Height / _image.Width - : (float)WidthRequest; - return new SKSize((float)WidthRequest, height); + double height = HeightRequest > 0 ? HeightRequest + : _image != null ? WidthRequest * _image.Height / _image.Width + : WidthRequest; + return new Size(WidthRequest, height); } if (HeightRequest > 0) { // Fixed height, calculate width from aspect ratio or use height - float width = WidthRequest > 0 ? (float)WidthRequest - : _image != null ? (float)HeightRequest * _image.Width / _image.Height - : (float)HeightRequest; - return new SKSize(width, (float)HeightRequest); + double width = WidthRequest > 0 ? WidthRequest + : _image != null ? HeightRequest * _image.Width / _image.Height + : HeightRequest; + return new Size(width, HeightRequest); } // No explicit size - calculate from content if (_image == null) - return new SKSize(44 + paddingWidth, 44 + paddingHeight); // Default touch target size + return new Size(44 + paddingWidth, 44 + paddingHeight); // Default touch target size var imageWidth = _image.Width; var imageHeight = _image.Height; - if (availableSize.Width < float.MaxValue && availableSize.Height < float.MaxValue) + if (availableSize.Width < double.MaxValue && availableSize.Height < double.MaxValue) { - var availableContent = new SKSize( - availableSize.Width - paddingWidth, - availableSize.Height - paddingHeight); - var scale = Math.Min(availableContent.Width / imageWidth, availableContent.Height / imageHeight); - return new SKSize(imageWidth * scale + paddingWidth, imageHeight * scale + paddingHeight); + var availableContentW = availableSize.Width - paddingWidth; + var availableContentH = availableSize.Height - paddingHeight; + var scale = Math.Min(availableContentW / imageWidth, availableContentH / imageHeight); + return new Size(imageWidth * scale + paddingWidth, imageHeight * scale + paddingHeight); } - else if (availableSize.Width < float.MaxValue) + else if (availableSize.Width < double.MaxValue) { var availableWidth = availableSize.Width - paddingWidth; var scale = availableWidth / imageWidth; - return new SKSize(availableSize.Width, imageHeight * scale + paddingHeight); + return new Size(availableSize.Width, imageHeight * scale + paddingHeight); } - else if (availableSize.Height < float.MaxValue) + else if (availableSize.Height < double.MaxValue) { var availableHeight = availableSize.Height - paddingHeight; var scale = availableHeight / imageHeight; - return new SKSize(imageWidth * scale + paddingWidth, availableSize.Height); + return new Size(imageWidth * scale + paddingWidth, availableSize.Height); } - return new SKSize(imageWidth + paddingWidth, imageHeight + paddingHeight); + return new Size(imageWidth + paddingWidth, imageHeight + paddingHeight); } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { // If we have explicit size requests, constrain to desired size // This follows MAUI standard behavior - controls respect WidthRequest/HeightRequest @@ -757,12 +756,12 @@ public class SkiaImageButton : SkiaView if (desiredWidth > 0 && desiredHeight > 0 && (desiredWidth < bounds.Width || desiredHeight < bounds.Height)) { - float finalWidth = Math.Min(desiredWidth, bounds.Width); - float finalHeight = Math.Min(desiredHeight, bounds.Height); + double finalWidth = Math.Min(desiredWidth, bounds.Width); + double finalHeight = Math.Min(desiredHeight, bounds.Height); // Calculate position based on HorizontalOptions // LayoutAlignment: Start=0, Center=1, End=2, Fill=3 - float x = bounds.Left; + double x = bounds.Left; var hAlignValue = (int)HorizontalOptions.Alignment; if (hAlignValue == 1) // Center { @@ -775,7 +774,7 @@ public class SkiaImageButton : SkiaView // Fill (3) and Start (0) both use x = bounds.Left // Calculate position based on VerticalOptions - float y = bounds.Top; + double y = bounds.Top; var vAlignValue = (int)VerticalOptions.Alignment; if (vAlignValue == 1) // Center { @@ -787,7 +786,7 @@ public class SkiaImageButton : SkiaView } // Fill (3) and Start (0) both use y = bounds.Top - return new SKRect(x, y, x + finalWidth, y + finalHeight); + return new Rect(x, y, finalWidth, finalHeight); } return bounds; diff --git a/Views/SkiaIndicatorView.cs b/Views/SkiaIndicatorView.cs index e0617ec..62057e8 100644 --- a/Views/SkiaIndicatorView.cs +++ b/Views/SkiaIndicatorView.cs @@ -145,18 +145,18 @@ public class SkiaIndicatorView : SkiaView /// public bool HideSingle { get; set; } = true; - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { if (_count <= 0 || (HideSingle && _count <= 1)) { - return SKSize.Empty; + return Size.Zero; } int visibleCount = Math.Min(_count, MaximumVisible); - float totalWidth = visibleCount * (float)IndicatorSize + (visibleCount - 1) * (float)IndicatorSpacing; - float height = Math.Max((float)IndicatorSize, (float)SelectedIndicatorSize); + double totalWidth = visibleCount * IndicatorSize + (visibleCount - 1) * IndicatorSpacing; + double height = Math.Max(IndicatorSize, SelectedIndicatorSize); - return new SKSize(totalWidth, height); + return new Size(totalWidth, height); } protected override void OnDraw(SKCanvas canvas, SKRect bounds) @@ -164,12 +164,13 @@ public class SkiaIndicatorView : SkiaView if (_count <= 0 || (HideSingle && _count <= 1)) return; canvas.Save(); - canvas.ClipRect(Bounds); + var skBounds = new SKRect((float)Bounds.Left, (float)Bounds.Top, (float)(Bounds.Left + Bounds.Width), (float)(Bounds.Top + Bounds.Height)); + canvas.ClipRect(skBounds); int visibleCount = Math.Min(_count, MaximumVisible); float totalWidth = visibleCount * (float)IndicatorSize + (visibleCount - 1) * (float)IndicatorSpacing; - float startX = Bounds.MidX - totalWidth / 2 + (float)IndicatorSize / 2; - float centerY = Bounds.MidY; + float startX = (float)(Bounds.Left + Bounds.Width / 2) - totalWidth / 2 + (float)IndicatorSize / 2; + float centerY = (float)(Bounds.Top + Bounds.Height / 2); // Determine visible range if count > MaximumVisible int startIndex = 0; @@ -283,7 +284,7 @@ public class SkiaIndicatorView : SkiaView { int visibleCount = Math.Min(_count, MaximumVisible); float totalWidth = visibleCount * (float)IndicatorSize + (visibleCount - 1) * (float)IndicatorSpacing; - float startX = Bounds.MidX - totalWidth / 2; + float startX = (float)(Bounds.Left + Bounds.Width / 2) - totalWidth / 2; int startIndex = 0; if (_count > MaximumVisible) @@ -316,7 +317,7 @@ public class SkiaIndicatorView : SkiaView // Calculate which indicator was clicked int visibleCount = Math.Min(_count, MaximumVisible); float totalWidth = visibleCount * (float)IndicatorSize + (visibleCount - 1) * (float)IndicatorSpacing; - float startX = Bounds.MidX - totalWidth / 2; + float startX = (float)(Bounds.Left + Bounds.Width / 2) - totalWidth / 2; int startIndex = 0; if (_count > MaximumVisible) diff --git a/Views/SkiaItemsView.cs b/Views/SkiaItemsView.cs index 372b227..85cc64c 100644 --- a/Views/SkiaItemsView.cs +++ b/Views/SkiaItemsView.cs @@ -176,7 +176,7 @@ public class SkiaItemsView : SkiaView } // Use ScreenBounds.Height for visible viewport - protected float MaxScrollOffset => Math.Max(0, TotalContentHeight - ScreenBounds.Height); + protected float MaxScrollOffset => Math.Max(0, TotalContentHeight - (float)ScreenBounds.Height); protected override void OnDraw(SKCanvas canvas, SKRect bounds) { @@ -284,11 +284,11 @@ public class SkiaItemsView : SkiaView if (itemView != null) { // Measure with large height to get natural size - var availableSize = new SKSize(bounds.Width, float.MaxValue); + var availableSize = new Size(bounds.Width, float.MaxValue); var measuredSize = itemView.Measure(availableSize); // Store individual item height (with minimum of default height) - var measuredHeight = Math.Max(measuredSize.Height, _itemHeight); + var measuredHeight = Math.Max((float)measuredSize.Height, _itemHeight); if (!_itemHeights.TryGetValue(index, out var cachedHeight) || Math.Abs(cachedHeight - measuredHeight) > 1) { _itemHeights[index] = measuredHeight; @@ -300,7 +300,7 @@ public class SkiaItemsView : SkiaView } // Arrange with the actual measured height - var actualBounds = new SKRect(bounds.Left, bounds.Top, bounds.Right, bounds.Top + measuredHeight); + var actualBounds = new Rect(bounds.Left, bounds.Top, bounds.Width, measuredHeight); itemView.Arrange(actualBounds); itemView.Draw(canvas); return; @@ -423,8 +423,8 @@ public class SkiaItemsView : SkiaView _scrollbarDragStartY = e.Y; _scrollbarDragStartScrollOffset = _scrollOffset; // Cache values to prevent stutter - var thumbHeight = Math.Max(20, Bounds.Height * (Bounds.Height / TotalContentHeight)); - _scrollbarDragAvailableTrack = Bounds.Height - thumbHeight; + var thumbHeight = Math.Max(20f, (float)Bounds.Height * ((float)Bounds.Height / TotalContentHeight)); + _scrollbarDragAvailableTrack = (float)Bounds.Height - thumbHeight; _scrollbarDragMaxScroll = MaxScrollOffset; return; } @@ -445,15 +445,15 @@ public class SkiaItemsView : SkiaView { // Use ScreenBounds for hit testing (input events use screen coordinates) var screenBounds = ScreenBounds; - var viewportRatio = screenBounds.Height / TotalContentHeight; - var thumbHeight = Math.Max(20, screenBounds.Height * viewportRatio); - var scrollRatio = MaxScrollOffset > 0 ? _scrollOffset / MaxScrollOffset : 0; - var thumbY = screenBounds.Top + (screenBounds.Height - thumbHeight) * scrollRatio; + var viewportRatio = (float)screenBounds.Height / TotalContentHeight; + var thumbHeight = Math.Max(20f, (float)screenBounds.Height * viewportRatio); + var scrollRatio = MaxScrollOffset > 0 ? _scrollOffset / MaxScrollOffset : 0f; + var thumbY = (float)screenBounds.Top + ((float)screenBounds.Height - thumbHeight) * scrollRatio; return new SKRect( - screenBounds.Right - _scrollBarWidth, + (float)(screenBounds.Left + screenBounds.Width) - _scrollBarWidth, thumbY, - screenBounds.Right, + (float)(screenBounds.Left + screenBounds.Width), thumbY + thumbHeight); } @@ -621,12 +621,12 @@ public class SkiaItemsView : SkiaView break; case Key.PageUp: - SetScrollOffset(_scrollOffset - Bounds.Height); + SetScrollOffset(_scrollOffset - (float)Bounds.Height); e.Handled = true; break; case Key.PageDown: - SetScrollOffset(_scrollOffset + Bounds.Height); + SetScrollOffset(_scrollOffset + (float)Bounds.Height); e.Handled = true; break; @@ -663,9 +663,9 @@ public class SkiaItemsView : SkiaView { SetScrollOffset(itemTop); } - else if (itemBottom > _scrollOffset + Bounds.Height) + else if (itemBottom > _scrollOffset + (float)Bounds.Height) { - SetScrollOffset(itemBottom - Bounds.Height); + SetScrollOffset(itemBottom - (float)Bounds.Height); } } @@ -679,14 +679,14 @@ public class SkiaItemsView : SkiaView public override SkiaView? HitTest(float x, float y) { // HitTest uses Bounds (content space) - coordinates are transformed by parent - if (!IsVisible || !Bounds.Contains(new SKPoint(x, y))) + if (!IsVisible || !Bounds.Contains(x, y)) return null; // Check scrollbar area FIRST before content // This ensures scrollbar clicks are handled by this view - if (_showVerticalScrollBar && TotalContentHeight > Bounds.Height) + if (_showVerticalScrollBar && TotalContentHeight > (float)Bounds.Height) { - var trackArea = new SKRect(Bounds.Right - _scrollBarWidth, Bounds.Top, Bounds.Right, Bounds.Bottom); + var trackArea = new SKRect((float)(Bounds.Left + Bounds.Width) - _scrollBarWidth, (float)Bounds.Top, (float)(Bounds.Left + Bounds.Width), (float)(Bounds.Top + Bounds.Height)); if (trackArea.Contains(x, y)) return this; } @@ -694,21 +694,21 @@ public class SkiaItemsView : SkiaView return this; } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - var width = availableSize.Width < float.MaxValue ? availableSize.Width : 200; - var height = availableSize.Height < float.MaxValue ? availableSize.Height : 300; + var width = availableSize.Width < double.MaxValue ? availableSize.Width : 200; + var height = availableSize.Height < double.MaxValue ? availableSize.Height : 300; // Clear item caches when width changes significantly (items need re-measurement for text wrapping) if (Math.Abs(width - _lastMeasuredWidth) > 5) { _itemHeights.Clear(); _itemViewCache.Clear(); - _lastMeasuredWidth = width; + _lastMeasuredWidth = (float)width; } // Items view takes all available space - return new SKSize(width, height); + return new Size(width, height); } protected override void Dispose(bool disposing) diff --git a/Views/SkiaLabel.cs b/Views/SkiaLabel.cs index 3641274..a1cea89 100644 --- a/Views/SkiaLabel.cs +++ b/Views/SkiaLabel.cs @@ -410,7 +410,7 @@ public class SkiaLabel : SkiaView // Calculate character position from click var screenBounds = ScreenBounds; - var clickX = e.X - screenBounds.Left - (float)Padding.Left; + var clickX = e.X - (float)screenBounds.Left - (float)Padding.Left; var charIndex = GetCharacterIndexAtX(clickX); // Check for double-click (select word) @@ -448,7 +448,7 @@ public class SkiaLabel : SkiaView if (string.IsNullOrEmpty(text)) return; var screenBounds = ScreenBounds; - var clickX = e.X - screenBounds.Left - (float)Padding.Left; + var clickX = e.X - (float)screenBounds.Left - (float)Padding.Left; var charIndex = GetCharacterIndexAtX(clickX); _selectionLength = charIndex - _selectionStart; @@ -1192,16 +1192,16 @@ public class SkiaLabel : SkiaView #region Measurement - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { var padding = Padding; - float paddingH = (float)(padding.Left + padding.Right); - float paddingV = (float)(padding.Top + padding.Bottom); + double paddingH = padding.Left + padding.Right; + double paddingV = padding.Top + padding.Bottom; string displayText = GetDisplayText(); if (string.IsNullOrEmpty(displayText) && (FormattedText == null || FormattedText.Spans.Count == 0)) { - return new SKSize(paddingH, paddingV + (float)FontSize); + return new Size(paddingH, paddingV + FontSize); } float fontSize = FontSize > 0 ? (float)FontSize : 14f; @@ -1213,7 +1213,7 @@ public class SkiaLabel : SkiaView using var paint = new SKPaint(font); - float width, height; + double width, height; // LineHeight -1 means platform default (use 1.0 multiplier) double effectiveLineHeight = LineHeight < 0 ? 1.0 : LineHeight; @@ -1221,7 +1221,7 @@ public class SkiaLabel : SkiaView { // Measure formatted text width = 0; - height = (float)(fontSize * effectiveLineHeight); + height = fontSize * effectiveLineHeight; foreach (var span in FormattedText.Spans) { if (!string.IsNullOrEmpty(span.Text)) @@ -1240,7 +1240,7 @@ public class SkiaLabel : SkiaView // Account for character spacing if (CharacterSpacing != 0 && displayText.Length > 1) { - width += (float)(CharacterSpacing * (displayText.Length - 1)); + width += CharacterSpacing * (displayText.Length - 1); } // Account for multi-line @@ -1248,7 +1248,7 @@ public class SkiaLabel : SkiaView { var lines = displayText.Split('\n'); int lineCount = MaxLines > 0 ? Math.Min(lines.Length, MaxLines) : lines.Length; - height = (float)(lineCount * fontSize * effectiveLineHeight); + height = lineCount * fontSize * effectiveLineHeight; } } @@ -1258,14 +1258,14 @@ public class SkiaLabel : SkiaView // Respect explicit size requests if (WidthRequest >= 0) { - width = (float)WidthRequest; + width = WidthRequest; } if (HeightRequest >= 0) { - height = (float)HeightRequest; + height = HeightRequest; } - return new SKSize(Math.Max(width, 1f), Math.Max(height, 1f)); + return new Size(Math.Max(width, 1.0), Math.Max(height, 1.0)); } #endregion diff --git a/Views/SkiaLayoutView.cs b/Views/SkiaLayoutView.cs index f669eec..2d48ed3 100644 --- a/Views/SkiaLayoutView.cs +++ b/Views/SkiaLayoutView.cs @@ -193,7 +193,7 @@ public abstract class SkiaLayoutView : SkiaView /// protected virtual SKRect GetContentBounds() { - return GetContentBounds(Bounds); + return GetContentBounds(new SKRect((float)Bounds.Left, (float)Bounds.Top, (float)(Bounds.Left + Bounds.Width), (float)(Bounds.Top + Bounds.Height))); } /// @@ -247,7 +247,7 @@ public abstract class SkiaLayoutView : SkiaView public override SkiaView? HitTest(float x, float y) { - if (!IsVisible || !IsEnabled || !Bounds.Contains(new SKPoint(x, y))) + if (!IsVisible || !IsEnabled || !Bounds.Contains(x, y)) { if (this is SkiaBorder) { @@ -357,7 +357,7 @@ public class SkiaStackLayout : SkiaLayoutView set => SetValue(OrientationProperty, value); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { // Handle NaN/Infinity in padding var paddingLeft = (float)(double.IsNaN(Padding.Left) ? 0 : Padding.Left); @@ -365,8 +365,8 @@ public class SkiaStackLayout : SkiaLayoutView var paddingTop = (float)(double.IsNaN(Padding.Top) ? 0 : Padding.Top); var paddingBottom = (float)(double.IsNaN(Padding.Bottom) ? 0 : Padding.Bottom); - var contentWidth = availableSize.Width - paddingLeft - paddingRight; - var contentHeight = availableSize.Height - paddingTop - paddingBottom; + var contentWidth = (float)availableSize.Width - paddingLeft - paddingRight; + var contentHeight = (float)availableSize.Height - paddingTop - paddingBottom; // Clamp negative sizes to 0 if (contentWidth < 0 || float.IsNaN(contentWidth)) contentWidth = 0; @@ -377,7 +377,7 @@ public class SkiaStackLayout : SkiaLayoutView float maxWidth = 0; float maxHeight = 0; - var childAvailable = new SKSize(contentWidth, contentHeight); + var childAvailable = new Size(contentWidth, contentHeight); foreach (var child in Children) { @@ -386,8 +386,8 @@ public class SkiaStackLayout : SkiaLayoutView var childSize = child.Measure(childAvailable); // Skip NaN sizes from child measurements - var childWidth = float.IsNaN(childSize.Width) ? 0 : childSize.Width; - var childHeight = float.IsNaN(childSize.Height) ? 0 : childSize.Height; + var childWidth = double.IsNaN(childSize.Width) ? 0f : (float)childSize.Width; + var childHeight = double.IsNaN(childSize.Height) ? 0f : (float)childSize.Height; if (Orientation == StackOrientation.Vertical) { @@ -408,22 +408,22 @@ public class SkiaStackLayout : SkiaLayoutView if (Orientation == StackOrientation.Vertical) { totalHeight += totalSpacing; - return new SKSize( + return new Size( maxWidth + paddingLeft + paddingRight, totalHeight + paddingTop + paddingBottom); } else { totalWidth += totalSpacing; - return new SKSize( + return new Size( totalWidth + paddingLeft + paddingRight, maxHeight + paddingTop + paddingBottom); } } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { - var content = GetContentBounds(bounds); + var content = GetContentBounds(new SKRect((float)bounds.Left, (float)bounds.Top, (float)bounds.Right, (float)bounds.Bottom)); // Clamp content dimensions if infinite - use reasonable defaults var contentWidth = float.IsInfinity(content.Width) || float.IsNaN(content.Width) ? 800f : content.Width; @@ -438,14 +438,14 @@ public class SkiaStackLayout : SkiaLayoutView var childDesired = child.DesiredSize; // Handle NaN and Infinity in desired size - var childWidth = float.IsNaN(childDesired.Width) || float.IsInfinity(childDesired.Width) + var childWidth = double.IsNaN(childDesired.Width) || double.IsInfinity(childDesired.Width) ? contentWidth - : childDesired.Width; - var childHeight = float.IsNaN(childDesired.Height) || float.IsInfinity(childDesired.Height) + : (float)childDesired.Width; + var childHeight = double.IsNaN(childDesired.Height) || double.IsInfinity(childDesired.Height) ? contentHeight - : childDesired.Height; + : (float)childDesired.Height; - SKRect childBounds; + float childBoundsLeft, childBoundsTop, childBoundsWidth, childBoundsHeight; if (Orientation == StackOrientation.Vertical) { // For ScrollView children, give them the remaining viewport height @@ -455,11 +455,10 @@ public class SkiaStackLayout : SkiaLayoutView ? remainingHeight : Math.Min(childHeight, remainingHeight > 0 ? remainingHeight : childHeight); - childBounds = new SKRect( - content.Left, - content.Top + offset, - content.Left + contentWidth, - content.Top + offset + useHeight); + childBoundsLeft = content.Left; + childBoundsTop = content.Top + offset; + childBoundsWidth = contentWidth; + childBoundsHeight = useHeight; offset += useHeight + (float)Spacing; } else @@ -473,7 +472,7 @@ public class SkiaStackLayout : SkiaLayoutView // Respect child's VerticalOptions for horizontal layouts var useHeight = Math.Min(childHeight, contentHeight); float childTop = content.Top; - float childBottom = content.Top + useHeight; + float childBottomCalc = content.Top + useHeight; var verticalOptions = child.VerticalOptions; var alignmentValue = (int)verticalOptions.Alignment; @@ -482,34 +481,33 @@ public class SkiaStackLayout : SkiaLayoutView if (alignmentValue == 1) // Center { childTop = content.Top + (contentHeight - useHeight) / 2; - childBottom = childTop + useHeight; + childBottomCalc = childTop + useHeight; } else if (alignmentValue == 2) // End { childTop = content.Top + contentHeight - useHeight; - childBottom = content.Top + contentHeight; + childBottomCalc = content.Top + contentHeight; } else if (alignmentValue == 3) // Fill { childTop = content.Top; - childBottom = content.Top + contentHeight; + childBottomCalc = content.Top + contentHeight; } - childBounds = new SKRect( - content.Left + offset, - childTop, - content.Left + offset + useWidth, - childBottom); + childBoundsLeft = content.Left + offset; + childBoundsTop = childTop; + childBoundsWidth = useWidth; + childBoundsHeight = childBottomCalc - childTop; offset += useWidth + (float)Spacing; } // Apply child's margin var margin = child.Margin; - var marginedBounds = new SKRect( - childBounds.Left + (float)margin.Left, - childBounds.Top + (float)margin.Top, - childBounds.Right - (float)margin.Right, - childBounds.Bottom - (float)margin.Bottom); + var marginedBounds = new Rect( + childBoundsLeft + (float)margin.Left, + childBoundsTop + (float)margin.Top, + childBoundsWidth - (float)margin.Left - (float)margin.Right, + childBoundsHeight - (float)margin.Top - (float)margin.Bottom); child.Arrange(marginedBounds); } return bounds; @@ -626,10 +624,10 @@ public class SkiaGrid : SkiaLayoutView Invalidate(); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - var contentWidth = availableSize.Width - (float)Padding.Left - (float)Padding.Right; - var contentHeight = availableSize.Height - (float)Padding.Top - (float)Padding.Bottom; + var contentWidth = (float)(availableSize.Width - Padding.Left - Padding.Right); + var contentHeight = (float)(availableSize.Height - Padding.Top - Padding.Bottom); // Handle NaN/Infinity if (float.IsNaN(contentWidth) || float.IsInfinity(contentWidth)) contentWidth = 800; @@ -652,8 +650,8 @@ public class SkiaGrid : SkiaLayoutView var def = pos.Column < _columnDefinitions.Count ? _columnDefinitions[pos.Column] : GridLength.Star; if (def.IsAuto && pos.ColumnSpan == 1) { - var childSize = child.Measure(new SKSize(float.PositiveInfinity, float.PositiveInfinity)); - var childWidth = float.IsNaN(childSize.Width) ? 0 : childSize.Width; + var childSize = child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); + var childWidth = double.IsNaN(childSize.Width) ? 0f : (float)childSize.Width; columnNaturalWidths[pos.Column] = Math.Max(columnNaturalWidths[pos.Column], childWidth); } } @@ -670,11 +668,11 @@ public class SkiaGrid : SkiaLayoutView var cellWidth = GetCellWidth(pos.Column, pos.ColumnSpan); // Give infinite height for initial measure - var childSize = child.Measure(new SKSize(cellWidth, float.PositiveInfinity)); + var childSize = child.Measure(new Size(cellWidth, double.PositiveInfinity)); // Track max height for each row // Cap infinite/very large heights - child returning infinity means it doesn't have a natural height - var childHeight = childSize.Height; + var childHeight = (float)childSize.Height; if (float.IsNaN(childHeight) || float.IsInfinity(childHeight) || childHeight > 100000) { // Use a default minimum - will be expanded by Star sizing if finite height is available @@ -706,16 +704,16 @@ public class SkiaGrid : SkiaLayoutView var cellWidth = GetCellWidth(pos.Column, pos.ColumnSpan); var cellHeight = GetCellHeight(pos.Row, pos.RowSpan); - child.Measure(new SKSize(cellWidth, cellHeight)); + child.Measure(new Size(cellWidth, cellHeight)); } // Calculate total size var totalWidth = _columnWidths.Sum() + Math.Max(0, columnCount - 1) * ColumnSpacing; var totalHeight = _rowHeights.Sum() + Math.Max(0, rowCount - 1) * RowSpacing; - return new SKSize( - totalWidth + (float)Padding.Left + (float)Padding.Right, - totalHeight + (float)Padding.Top + (float)Padding.Bottom); + return new Size( + totalWidth + Padding.Left + Padding.Right, + totalHeight + Padding.Top + Padding.Bottom); } private int GetMaxRow() @@ -827,11 +825,11 @@ public class SkiaGrid : SkiaLayoutView return offset; } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { try { - var content = GetContentBounds(bounds); + var content = GetContentBounds(new SKRect((float)bounds.Left, (float)bounds.Top, (float)bounds.Right, (float)bounds.Bottom)); // Recalculate row heights for arrange bounds if they differ from measurement // This ensures Star rows expand to fill available space @@ -909,11 +907,11 @@ public class SkiaGrid : SkiaLayoutView // Apply child's margin var margin = child.Margin; - var marginedBounds = new SKRect( + var marginedBounds = new Rect( x + (float)margin.Left, y + (float)margin.Top, - x + width - (float)margin.Right, - y + height - (float)margin.Bottom); + width - (float)margin.Left - (float)margin.Right, + height - (float)margin.Top - (float)margin.Bottom); child.Arrange(marginedBounds); } return bounds; @@ -1024,7 +1022,7 @@ public class SkiaAbsoluteLayout : SkiaLayoutView Invalidate(); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { float maxRight = 0; float maxBottom = 0; @@ -1036,20 +1034,20 @@ public class SkiaAbsoluteLayout : SkiaLayoutView var layout = GetLayoutBounds(child); var bounds = layout.Bounds; - child.Measure(new SKSize(bounds.Width, bounds.Height)); + child.Measure(new Size(bounds.Width, bounds.Height)); maxRight = Math.Max(maxRight, bounds.Right); maxBottom = Math.Max(maxBottom, bounds.Bottom); } - return new SKSize( - maxRight + (float)Padding.Left + (float)Padding.Right, - maxBottom + (float)Padding.Top + (float)Padding.Bottom); + return new Size( + maxRight + Padding.Left + Padding.Right, + maxBottom + Padding.Top + Padding.Bottom); } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { - var content = GetContentBounds(bounds); + var content = GetContentBounds(new SKRect((float)bounds.Left, (float)bounds.Top, (float)bounds.Right, (float)bounds.Bottom)); foreach (var child in Children) { @@ -1077,7 +1075,7 @@ public class SkiaAbsoluteLayout : SkiaLayoutView if (flags.HasFlag(AbsoluteLayoutFlags.WidthProportional)) width = childBounds.Width * content.Width; else if (childBounds.Width < 0) - width = child.DesiredSize.Width; + width = (float)child.DesiredSize.Width; else width = childBounds.Width; @@ -1085,17 +1083,17 @@ public class SkiaAbsoluteLayout : SkiaLayoutView if (flags.HasFlag(AbsoluteLayoutFlags.HeightProportional)) height = childBounds.Height * content.Height; else if (childBounds.Height < 0) - height = child.DesiredSize.Height; + height = (float)child.DesiredSize.Height; else height = childBounds.Height; // Apply child's margin var margin = child.Margin; - var marginedBounds = new SKRect( + var marginedBounds = new Rect( x + (float)margin.Left, y + (float)margin.Top, - x + width - (float)margin.Right, - y + height - (float)margin.Bottom); + width - (float)margin.Left - (float)margin.Right, + height - (float)margin.Top - (float)margin.Bottom); child.Arrange(marginedBounds); } return bounds; diff --git a/Views/SkiaMenuBar.cs b/Views/SkiaMenuBar.cs index 72cb6da..e180cfe 100644 --- a/Views/SkiaMenuBar.cs +++ b/Views/SkiaMenuBar.cs @@ -104,9 +104,9 @@ public class SkiaMenuBar : SkiaView /// public float ItemPadding { get; set; } = 12f; - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - return new SKSize(availableSize.Width, BarHeight); + return new Size(availableSize.Width, BarHeight); } protected override void OnDraw(SKCanvas canvas, SKRect bounds) @@ -119,7 +119,8 @@ public class SkiaMenuBar : SkiaView Color = _menuBackgroundColorSK, Style = SKPaintStyle.Fill }; - canvas.DrawRect(Bounds, bgPaint); + var skBounds = new SKRect((float)Bounds.Left, (float)Bounds.Top, (float)(Bounds.Left + Bounds.Width), (float)(Bounds.Top + Bounds.Height)); + canvas.DrawRect(skBounds, bgPaint); // Draw bottom border using var borderPaint = new SKPaint @@ -128,7 +129,7 @@ public class SkiaMenuBar : SkiaView Style = SKPaintStyle.Stroke, StrokeWidth = 1 }; - canvas.DrawLine(Bounds.Left, Bounds.Bottom, Bounds.Right, Bounds.Bottom, borderPaint); + canvas.DrawLine((float)Bounds.Left, (float)(Bounds.Top + Bounds.Height), (float)(Bounds.Left + Bounds.Width), (float)(Bounds.Top + Bounds.Height), borderPaint); // Draw menu items using var textPaint = new SKPaint @@ -138,7 +139,7 @@ public class SkiaMenuBar : SkiaView IsAntialias = true }; - float x = Bounds.Left; + float x = (float)Bounds.Left; for (int i = 0; i < _items.Count; i++) { @@ -147,7 +148,7 @@ public class SkiaMenuBar : SkiaView textPaint.MeasureText(item.Text, ref textBounds); float itemWidth = textBounds.Width + ItemPadding * 2; - var itemBounds = new SKRect(x, Bounds.Top, x + itemWidth, Bounds.Bottom); + var itemBounds = new SKRect(x, (float)Bounds.Top, x + itemWidth, (float)(Bounds.Top + Bounds.Height)); // Draw item background if (i == _openIndex) @@ -161,9 +162,9 @@ public class SkiaMenuBar : SkiaView canvas.DrawRect(itemBounds, hoverPaint); } - // Draw text + // Draw text (MidY = Top + Height/2) float textX = x + ItemPadding; - float textY = Bounds.MidY - textBounds.MidY; + float textY = (float)(Bounds.Top + Bounds.Height / 2) - textBounds.MidY; canvas.DrawText(item.Text, textX, textY, textPaint); item.Bounds = itemBounds; diff --git a/Views/SkiaNavigationPage.cs b/Views/SkiaNavigationPage.cs index 0cd1f69..739a339 100644 --- a/Views/SkiaNavigationPage.cs +++ b/Views/SkiaNavigationPage.cs @@ -287,7 +287,7 @@ public class SkiaNavigationPage : SkiaView { canvas.Save(); canvas.Translate(currentOffset, 0); - _currentPage.Bounds = bounds; + _currentPage.Bounds = new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height); _currentPage.Draw(canvas); canvas.Restore(); } @@ -295,7 +295,7 @@ public class SkiaNavigationPage : SkiaView // Draw incoming page canvas.Save(); canvas.Translate(incomingOffset, 0); - _incomingPage.Bounds = bounds; + _incomingPage.Bounds = new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height); _incomingPage.Draw(canvas); canvas.Restore(); } @@ -308,7 +308,7 @@ public class SkiaNavigationPage : SkiaView // Draw incoming page (sliding in) canvas.Save(); canvas.Translate(incomingOffset, 0); - _incomingPage.Bounds = bounds; + _incomingPage.Bounds = new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height); _incomingPage.Draw(canvas); canvas.Restore(); @@ -317,7 +317,7 @@ public class SkiaNavigationPage : SkiaView { canvas.Save(); canvas.Translate(currentOffset, 0); - _currentPage.Bounds = bounds; + _currentPage.Bounds = new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height); _currentPage.Draw(canvas); canvas.Restore(); } @@ -327,7 +327,7 @@ public class SkiaNavigationPage : SkiaView { // Draw current page normally Console.WriteLine("[SkiaNavigationPage] OnDraw: drawing _currentPage=" + _currentPage.Title); - _currentPage.Bounds = bounds; + _currentPage.Bounds = new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height); _currentPage.Draw(canvas); // Draw back button if applicable @@ -368,7 +368,7 @@ public class SkiaNavigationPage : SkiaView return 1 - (float)Math.Pow(1 - t, 3); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { return availableSize; } diff --git a/Views/SkiaPage.cs b/Views/SkiaPage.cs index 7a26541..d712e24 100644 --- a/Views/SkiaPage.cs +++ b/Views/SkiaPage.cs @@ -187,9 +187,9 @@ public class SkiaPage : SkiaView contentBounds.Bottom - (float)margin.Bottom); // Measure and arrange the content before drawing - var availableSize = new SKSize(adjustedBounds.Width, adjustedBounds.Height); + var availableSize = new Size(adjustedBounds.Width, adjustedBounds.Height); _content.Measure(availableSize); - _content.Arrange(adjustedBounds); + _content.Arrange(new Rect(adjustedBounds.Left, adjustedBounds.Top, adjustedBounds.Width, adjustedBounds.Height)); Console.WriteLine($"[SkiaPage] Drawing content: {_content.GetType().Name}, Bounds={_content.Bounds}, IsVisible={_content.IsVisible}"); _content.Draw(canvas); } @@ -294,7 +294,7 @@ public class SkiaPage : SkiaView NavigatingFrom?.Invoke(this, EventArgs.Empty); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { // Page takes all available space return availableSize; diff --git a/Views/SkiaPicker.cs b/Views/SkiaPicker.cs index df72398..5f73e4c 100644 --- a/Views/SkiaPicker.cs +++ b/Views/SkiaPicker.cs @@ -419,7 +419,8 @@ public class SkiaPicker : SkiaView private void DrawDropdownOverlay(SKCanvas canvas) { if (_items.Count == 0 || !_isOpen) return; - DrawDropdown(canvas, ScreenBounds); + var skScreenBounds = new SKRect((float)ScreenBounds.Left, (float)ScreenBounds.Top, (float)(ScreenBounds.Left + ScreenBounds.Width), (float)(ScreenBounds.Top + ScreenBounds.Height)); + DrawDropdown(canvas, skScreenBounds); } protected override void OnDraw(SKCanvas canvas, SKRect bounds) @@ -808,10 +809,10 @@ public class SkiaPicker : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - return new SKSize( - availableSize.Width < float.MaxValue ? Math.Min(availableSize.Width, 200) : 200, + return new Size( + availableSize.Width < double.MaxValue ? Math.Min(availableSize.Width, 200) : 200, 40); } @@ -837,10 +838,10 @@ public class SkiaPicker : SkiaView var dropdownMaxHeight = (float)_dropdownMaxHeight; var dropdownHeight = Math.Min(_items.Count * itemHeight, dropdownMaxHeight); var dropdownRect = new SKRect( - screenBounds.Left, - screenBounds.Bottom + 4, - screenBounds.Right, - screenBounds.Bottom + 4 + dropdownHeight); + (float)screenBounds.Left, + (float)(screenBounds.Top + screenBounds.Height) + 4, + (float)(screenBounds.Left + screenBounds.Width), + (float)(screenBounds.Top + screenBounds.Height) + 4 + dropdownHeight); return dropdownRect.Contains(x, y); } diff --git a/Views/SkiaProgressBar.cs b/Views/SkiaProgressBar.cs index bffa185..850cd07 100644 --- a/Views/SkiaProgressBar.cs +++ b/Views/SkiaProgressBar.cs @@ -244,10 +244,10 @@ public class SkiaProgressBar : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - var barHeight = (float)BarHeight; - return new SKSize(200f, barHeight + 8f); + var barHeight = BarHeight; + return new Size(200, barHeight + 8); } #endregion diff --git a/Views/SkiaRadioButton.cs b/Views/SkiaRadioButton.cs index e179058..300c8a1 100644 --- a/Views/SkiaRadioButton.cs +++ b/Views/SkiaRadioButton.cs @@ -507,7 +507,7 @@ public class SkiaRadioButton : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { var radioSize = (float)RadioSize; var fontSize = (float)FontSize; @@ -520,7 +520,7 @@ public class SkiaRadioButton : SkiaView using var paint = new SKPaint(font); textWidth = paint.MeasureText(Content) + spacing; } - return new SKSize(radioSize + textWidth, Math.Max(radioSize, fontSize * 1.5f)); + return new Size(radioSize + textWidth, Math.Max(radioSize, fontSize * 1.5f)); } #endregion diff --git a/Views/SkiaRefreshView.cs b/Views/SkiaRefreshView.cs index 3e2b57d..d72d418 100644 --- a/Views/SkiaRefreshView.cs +++ b/Views/SkiaRefreshView.cs @@ -130,25 +130,21 @@ public class SkiaRefreshView : SkiaLayoutView /// public event EventHandler? Refreshing; - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { if (_content != null) { - _content.Measure(availableSize); + _content.Measure(new Size(availableSize.Width, availableSize.Height)); } return availableSize; } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { if (_content != null) { float offset = _isRefreshing ? _refreshThreshold : _pullDistance; - var contentBounds = new SKRect( - bounds.Left, - bounds.Top + offset, - bounds.Right, - bounds.Bottom + offset); + var contentBounds = new Rect(bounds.Left, bounds.Top + offset, bounds.Width, bounds.Height); _content.Arrange(contentBounds); } return bounds; diff --git a/Views/SkiaScrollView.cs b/Views/SkiaScrollView.cs index 84d178f..7ee8944 100644 --- a/Views/SkiaScrollView.cs +++ b/Views/SkiaScrollView.cs @@ -240,9 +240,9 @@ public class SkiaScrollView : SkiaView get { // Handle infinite or NaN bounds - use a reasonable default viewport - var viewportWidth = float.IsInfinity(Bounds.Width) || float.IsNaN(Bounds.Width) || Bounds.Width <= 0 + var viewportWidth = double.IsInfinity(Bounds.Width) || double.IsNaN(Bounds.Width) || Bounds.Width <= 0 ? 800f - : Bounds.Width; + : (float)Bounds.Width; return Math.Max(0, ContentSize.Width - viewportWidth); } } @@ -256,9 +256,9 @@ public class SkiaScrollView : SkiaView { // Handle infinite, NaN, or unreasonably large bounds - use a reasonable default viewport var boundsHeight = Bounds.Height; - var viewportHeight = (float.IsInfinity(boundsHeight) || float.IsNaN(boundsHeight) || boundsHeight <= 0 || boundsHeight > 10000) + var viewportHeight = (double.IsInfinity(boundsHeight) || double.IsNaN(boundsHeight) || boundsHeight <= 0 || boundsHeight > 10000) ? 544f // Default viewport height (600 - 56 for shell header) - : boundsHeight; + : (float)boundsHeight; return Math.Max(0, ContentSize.Height - viewportHeight); } } @@ -290,17 +290,18 @@ public class SkiaScrollView : SkiaView // Reserve space for vertical scrollbar if content might be taller than viewport effectiveWidth -= ScrollBarWidth; } - var availableSize = new SKSize(effectiveWidth, float.PositiveInfinity); + var availableSize = new Size(effectiveWidth, double.PositiveInfinity); // Update ContentSize with the properly constrained measurement - ContentSize = _content.Measure(availableSize); + var contentDesired = _content.Measure(availableSize); + ContentSize = new SKSize((float)contentDesired.Width, (float)contentDesired.Height); // Apply content's margin var margin = _content.Margin; - var contentBounds = new SKRect( - bounds.Left + (float)margin.Left, - bounds.Top + (float)margin.Top, - bounds.Left + Math.Max(bounds.Width, _content.DesiredSize.Width) - (float)margin.Right, - bounds.Top + Math.Max(bounds.Height, _content.DesiredSize.Height) - (float)margin.Bottom); + var contentLeft = bounds.Left + (float)margin.Left; + var contentTop = bounds.Top + (float)margin.Top; + var contentWidth = Math.Max(bounds.Width, (float)_content.DesiredSize.Width) - (float)margin.Left - (float)margin.Right; + var contentHeight = Math.Max(bounds.Height, (float)_content.DesiredSize.Height) - (float)margin.Top - (float)margin.Bottom; + var contentBounds = new Rect(contentLeft, contentTop, contentWidth, contentHeight); _content.Arrange(contentBounds); canvas.Save(); @@ -358,8 +359,8 @@ public class SkiaScrollView : SkiaView private void DrawVerticalScrollbar(SKCanvas canvas, SKRect bounds, bool hasHorizontal) { var trackHeight = bounds.Height - (hasHorizontal ? ScrollBarWidth : 0); - var thumbHeight = Math.Max(20, (bounds.Height / ContentSize.Height) * trackHeight); - var thumbY = (ScrollY / ScrollableHeight) * (trackHeight - thumbHeight); + var thumbHeight = Math.Max(20f, (bounds.Height / ContentSize.Height) * trackHeight); + var thumbY = ScrollableHeight > 0 ? (ScrollY / ScrollableHeight) * (trackHeight - thumbHeight) : 0f; using var paint = new SKPaint { @@ -381,8 +382,8 @@ public class SkiaScrollView : SkiaView private void DrawHorizontalScrollbar(SKCanvas canvas, SKRect bounds, bool hasVertical) { var trackWidth = bounds.Width - (hasVertical ? ScrollBarWidth : 0); - var thumbWidth = Math.Max(20, (bounds.Width / ContentSize.Width) * trackWidth); - var thumbX = (ScrollX / ScrollableWidth) * (trackWidth - thumbWidth); + var thumbWidth = Math.Max(20f, (bounds.Width / ContentSize.Width) * trackWidth); + var thumbX = ScrollableWidth > 0 ? (ScrollX / ScrollableWidth) * (trackWidth - thumbWidth) : 0f; using var paint = new SKPaint { @@ -444,8 +445,8 @@ public class SkiaScrollView : SkiaView _scrollbarDragStartScrollY = _scrollY; // Cache values to prevent stutter from floating-point recalculations var hasHorizontal = ShouldShowHorizontalScrollbar(); - var trackHeight = Bounds.Height - (hasHorizontal ? ScrollBarWidth : 0); - var thumbHeight = Math.Max(20, (Bounds.Height / ContentSize.Height) * trackHeight); + var trackHeight = (float)Bounds.Height - (hasHorizontal ? ScrollBarWidth : 0); + var thumbHeight = Math.Max(20f, ((float)Bounds.Height / ContentSize.Height) * trackHeight); _scrollbarDragAvailableTrack = trackHeight - thumbHeight; _scrollbarDragScrollableExtent = ScrollableHeight; return; @@ -463,8 +464,8 @@ public class SkiaScrollView : SkiaView _scrollbarDragStartScrollX = _scrollX; // Cache values to prevent stutter from floating-point recalculations var hasVertical = ShouldShowVerticalScrollbar(); - var trackWidth = Bounds.Width - (hasVertical ? ScrollBarWidth : 0); - var thumbWidth = Math.Max(20, (Bounds.Width / ContentSize.Width) * trackWidth); + var trackWidth = (float)Bounds.Width - (hasVertical ? ScrollBarWidth : 0); + var thumbWidth = Math.Max(20f, ((float)Bounds.Width / ContentSize.Width) * trackWidth); _scrollbarDragAvailableTrack = trackWidth - thumbWidth; _scrollbarDragScrollableExtent = ScrollableWidth; return; @@ -549,34 +550,34 @@ public class SkiaScrollView : SkiaView private SKRect GetVerticalScrollbarThumbBounds() { var hasHorizontal = ShouldShowHorizontalScrollbar(); - var trackHeight = Bounds.Height - (hasHorizontal ? ScrollBarWidth : 0); - var thumbHeight = Math.Max(20, (Bounds.Height / ContentSize.Height) * trackHeight); - var thumbY = ScrollableHeight > 0 ? (ScrollY / ScrollableHeight) * (trackHeight - thumbHeight) : 0; + var trackHeight = (float)Bounds.Height - (hasHorizontal ? ScrollBarWidth : 0); + var thumbHeight = Math.Max(20f, ((float)Bounds.Height / ContentSize.Height) * trackHeight); + var thumbY = ScrollableHeight > 0 ? (ScrollY / ScrollableHeight) * (trackHeight - thumbHeight) : 0f; return new SKRect( - Bounds.Right - ScrollBarWidth, - Bounds.Top + thumbY, - Bounds.Right, - Bounds.Top + thumbY + thumbHeight); + (float)(Bounds.Left + Bounds.Width) - ScrollBarWidth, + (float)Bounds.Top + thumbY, + (float)(Bounds.Left + Bounds.Width), + (float)Bounds.Top + thumbY + thumbHeight); } private SKRect GetHorizontalScrollbarThumbBounds() { var hasVertical = ShouldShowVerticalScrollbar(); - var trackWidth = Bounds.Width - (hasVertical ? ScrollBarWidth : 0); - var thumbWidth = Math.Max(20, (Bounds.Width / ContentSize.Width) * trackWidth); - var thumbX = ScrollableWidth > 0 ? (ScrollX / ScrollableWidth) * (trackWidth - thumbWidth) : 0; + var trackWidth = (float)Bounds.Width - (hasVertical ? ScrollBarWidth : 0); + var thumbWidth = Math.Max(20f, ((float)Bounds.Width / ContentSize.Width) * trackWidth); + var thumbX = ScrollableWidth > 0 ? (ScrollX / ScrollableWidth) * (trackWidth - thumbWidth) : 0f; return new SKRect( - Bounds.Left + thumbX, - Bounds.Bottom - ScrollBarWidth, - Bounds.Left + thumbX + thumbWidth, - Bounds.Bottom); + (float)Bounds.Left + thumbX, + (float)(Bounds.Top + Bounds.Height) - ScrollBarWidth, + (float)Bounds.Left + thumbX + thumbWidth, + (float)(Bounds.Top + Bounds.Height)); } public override SkiaView? HitTest(float x, float y) { - if (!IsVisible || !IsEnabled || !Bounds.Contains(new SKPoint(x, y))) + if (!IsVisible || !IsEnabled || !Bounds.Contains(x, y)) return null; // Check scrollbar areas FIRST before content @@ -585,14 +586,14 @@ public class SkiaScrollView : SkiaView { var thumbBounds = GetVerticalScrollbarThumbBounds(); // Check if click is in the scrollbar track area (not just thumb) - var trackArea = new SKRect(Bounds.Right - ScrollBarWidth, Bounds.Top, Bounds.Right, Bounds.Bottom); + var trackArea = new SKRect((float)(Bounds.Left + Bounds.Width) - ScrollBarWidth, (float)Bounds.Top, (float)(Bounds.Left + Bounds.Width), (float)(Bounds.Top + Bounds.Height)); if (trackArea.Contains(x, y)) return this; } if (ShouldShowHorizontalScrollbar() && ScrollableWidth > 0) { - var trackArea = new SKRect(Bounds.Left, Bounds.Bottom - ScrollBarWidth, Bounds.Right, Bounds.Bottom); + var trackArea = new SKRect((float)Bounds.Left, (float)(Bounds.Top + Bounds.Height) - ScrollBarWidth, (float)(Bounds.Left + Bounds.Width), (float)(Bounds.Top + Bounds.Height)); if (trackArea.Contains(x, y)) return this; } @@ -680,38 +681,40 @@ public class SkiaScrollView : SkiaView float targetY = _scrollY; // Calculate viewport dimensions - float viewportWidth = Bounds.Width; - float viewportHeight = Bounds.Height; + float viewportWidth = (float)Bounds.Width; + float viewportHeight = (float)Bounds.Height; + float elementRight = (float)(elementBounds.Left + elementBounds.Width); + float elementBottom = (float)(elementBounds.Top + elementBounds.Height); switch (position) { case ScrollToPosition.Start: - targetX = elementBounds.Left; - targetY = elementBounds.Top; + targetX = (float)elementBounds.Left; + targetY = (float)elementBounds.Top; break; case ScrollToPosition.Center: - targetX = elementBounds.Left - (viewportWidth - elementBounds.Width) / 2; - targetY = elementBounds.Top - (viewportHeight - elementBounds.Height) / 2; + targetX = (float)elementBounds.Left - (viewportWidth - (float)elementBounds.Width) / 2; + targetY = (float)elementBounds.Top - (viewportHeight - (float)elementBounds.Height) / 2; break; case ScrollToPosition.End: - targetX = elementBounds.Right - viewportWidth; - targetY = elementBounds.Bottom - viewportHeight; + targetX = elementRight - viewportWidth; + targetY = elementBottom - viewportHeight; break; case ScrollToPosition.MakeVisible: default: // Only scroll if element is not fully visible if (elementBounds.Left < _scrollX) - targetX = elementBounds.Left; - else if (elementBounds.Right > _scrollX + viewportWidth) - targetX = elementBounds.Right - viewportWidth; + targetX = (float)elementBounds.Left; + else if (elementRight > _scrollX + viewportWidth) + targetX = elementRight - viewportWidth; if (elementBounds.Top < _scrollY) - targetY = elementBounds.Top; - else if (elementBounds.Bottom > _scrollY + viewportHeight) - targetY = elementBounds.Bottom - viewportHeight; + targetY = (float)elementBounds.Top; + else if (elementBottom > _scrollY + viewportHeight) + targetY = elementBottom - viewportHeight; break; } @@ -730,15 +733,18 @@ public class SkiaScrollView : SkiaView if (_content == null) return; var viewBounds = view.Bounds; + float viewRight = (float)(viewBounds.Left + viewBounds.Width); + float viewBottom = (float)(viewBounds.Top + viewBounds.Height); // Check if view is fully visible var visibleRect = new SKRect( ScrollX, ScrollY, - ScrollX + Bounds.Width, - ScrollY + Bounds.Height); + ScrollX + (float)Bounds.Width, + ScrollY + (float)Bounds.Height); - if (visibleRect.Contains(viewBounds)) + var viewSKRect = new SKRect((float)viewBounds.Left, (float)viewBounds.Top, viewRight, viewBottom); + if (visibleRect.Contains(viewSKRect)) return; // Calculate scroll position to bring view into view @@ -746,14 +752,14 @@ public class SkiaScrollView : SkiaView float targetY = ScrollY; if (viewBounds.Left < visibleRect.Left) - targetX = viewBounds.Left; - else if (viewBounds.Right > visibleRect.Right) - targetX = viewBounds.Right - Bounds.Width; + targetX = (float)viewBounds.Left; + else if (viewRight > visibleRect.Right) + targetX = viewRight - (float)Bounds.Width; if (viewBounds.Top < visibleRect.Top) - targetY = viewBounds.Top; - else if (viewBounds.Bottom > visibleRect.Bottom) - targetY = viewBounds.Bottom - Bounds.Height; + targetY = (float)viewBounds.Top; + else if (viewBottom > visibleRect.Bottom) + targetY = viewBottom - (float)Bounds.Height; ScrollTo(targetX, targetY, animated); } @@ -770,7 +776,7 @@ public class SkiaScrollView : SkiaView return Math.Clamp(value, 0, ScrollableHeight); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { if (_content != null) { @@ -787,17 +793,17 @@ public class SkiaScrollView : SkiaView { case ScrollOrientation.Horizontal: contentWidth = float.PositiveInfinity; - contentHeight = float.IsInfinity(availableSize.Height) ? 400f : availableSize.Height; + contentHeight = double.IsInfinity(availableSize.Height) ? 400f : (float)availableSize.Height; break; case ScrollOrientation.Neither: - contentWidth = float.IsInfinity(availableSize.Width) ? 400f : availableSize.Width; - contentHeight = float.IsInfinity(availableSize.Height) ? 400f : availableSize.Height; + contentWidth = double.IsInfinity(availableSize.Width) ? 400f : (float)availableSize.Width; + contentHeight = double.IsInfinity(availableSize.Height) ? 400f : (float)availableSize.Height; break; case ScrollOrientation.Both: // For Both: first measure with viewport width to get responsive layout // Content can still exceed viewport if it has minimum width constraints // Reserve space for vertical scrollbar to prevent horizontal scrollbar - contentWidth = float.IsInfinity(availableSize.Width) ? 800f : availableSize.Width; + contentWidth = double.IsInfinity(availableSize.Width) ? 800f : (float)availableSize.Width; if (VerticalScrollBarVisibility != ScrollBarVisibility.Never) contentWidth -= ScrollBarWidth; contentHeight = float.PositiveInfinity; @@ -805,14 +811,15 @@ public class SkiaScrollView : SkiaView case ScrollOrientation.Vertical: default: // Reserve space for vertical scrollbar to prevent horizontal scrollbar - contentWidth = float.IsInfinity(availableSize.Width) ? 800f : availableSize.Width; + contentWidth = double.IsInfinity(availableSize.Width) ? 800f : (float)availableSize.Width; if (VerticalScrollBarVisibility != ScrollBarVisibility.Never) contentWidth -= ScrollBarWidth; contentHeight = float.PositiveInfinity; break; } - ContentSize = _content.Measure(new SKSize(contentWidth, contentHeight)); + var contentDesiredMeasure = _content.Measure(new Size(contentWidth, contentHeight)); + ContentSize = new SKSize((float)contentDesiredMeasure.Width, (float)contentDesiredMeasure.Height); } else { @@ -823,41 +830,41 @@ public class SkiaScrollView : SkiaView // IMPORTANT: When available is infinite, return a reasonable viewport size, NOT content size // A ScrollView should NOT expand to fit its content - it should stay at a fixed viewport // and scroll the content. Use a default viewport size when parent gives infinity. - const float DefaultViewportWidth = 400f; - const float DefaultViewportHeight = 400f; + const double DefaultViewportWidth = 400.0; + const double DefaultViewportHeight = 400.0; - var width = float.IsInfinity(availableSize.Width) || float.IsNaN(availableSize.Width) + var width = double.IsInfinity(availableSize.Width) || double.IsNaN(availableSize.Width) ? Math.Min(ContentSize.Width, DefaultViewportWidth) : availableSize.Width; - var height = float.IsInfinity(availableSize.Height) || float.IsNaN(availableSize.Height) + var height = double.IsInfinity(availableSize.Height) || double.IsNaN(availableSize.Height) ? Math.Min(ContentSize.Height, DefaultViewportHeight) : availableSize.Height; - return new SKSize(width, height); + return new Size(width, height); } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { // CRITICAL: If bounds has infinite height, use a fixed viewport size // NOT ContentSize.Height - that would make ScrollableHeight = 0 const float DefaultViewportHeight = 544f; // 600 - 56 for shell header var actualBounds = bounds; - if (float.IsInfinity(bounds.Height) || float.IsNaN(bounds.Height)) + if (double.IsInfinity(bounds.Height) || double.IsNaN(bounds.Height)) { Console.WriteLine($"[SkiaScrollView] WARNING: Infinite/NaN height, using default viewport={DefaultViewportHeight}"); - actualBounds = new SKRect(bounds.Left, bounds.Top, bounds.Right, bounds.Top + DefaultViewportHeight); + actualBounds = new Rect(bounds.Left, bounds.Top, bounds.Width, DefaultViewportHeight); } if (_content != null) { // Apply content's margin and arrange content at its full size var margin = _content.Margin; - var contentBounds = new SKRect( - actualBounds.Left + (float)margin.Left, - actualBounds.Top + (float)margin.Top, - actualBounds.Left + Math.Max(actualBounds.Width, ContentSize.Width) - (float)margin.Right, - actualBounds.Top + Math.Max(actualBounds.Height, ContentSize.Height) - (float)margin.Bottom); + var contentLeft = (float)actualBounds.Left + (float)margin.Left; + var contentTop = (float)actualBounds.Top + (float)margin.Top; + var contentWidth = Math.Max((float)actualBounds.Width, ContentSize.Width) - (float)margin.Left - (float)margin.Right; + var contentHeight = Math.Max((float)actualBounds.Height, ContentSize.Height) - (float)margin.Top - (float)margin.Bottom; + var contentBounds = new Rect(contentLeft, contentTop, contentWidth, contentHeight); _content.Arrange(contentBounds); } diff --git a/Views/SkiaSearchBar.cs b/Views/SkiaSearchBar.cs index 24319f4..4c018b5 100644 --- a/Views/SkiaSearchBar.cs +++ b/Views/SkiaSearchBar.cs @@ -177,7 +177,7 @@ public class SkiaSearchBar : SkiaView ? bounds.Right - clearButtonSize - iconPadding * 2 : bounds.Right - iconPadding; - var entryBounds = new SKRect(entryLeft, bounds.Top, entryRight, bounds.Bottom); + var entryBounds = new Rect(entryLeft, bounds.Top, entryRight - entryLeft, bounds.Height); _entry.Arrange(entryBounds); _entry.Draw(canvas); @@ -306,9 +306,9 @@ public class SkiaSearchBar : SkiaView #region Measurement - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - return new SKSize(250, 40); + return new Size(250, 40); } #endregion diff --git a/Views/SkiaShell.cs b/Views/SkiaShell.cs index 40c5f13..2d46371 100644 --- a/Views/SkiaShell.cs +++ b/Views/SkiaShell.cs @@ -750,36 +750,36 @@ public class SkiaShell : SkiaLayoutView } } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { // Measure current content with padding accounted for (consistent with ArrangeOverride) if (_currentContent != null) { float contentTop = NavBarIsVisible ? NavBarHeight : 0; float contentBottom = TabBarIsVisible ? TabBarHeight : 0; - var contentSize = new SKSize( - availableSize.Width - (float)Padding.Left - (float)Padding.Right, - availableSize.Height - contentTop - contentBottom - (float)Padding.Top - (float)Padding.Bottom); + var contentSize = new Size( + availableSize.Width - Padding.Left - Padding.Right, + availableSize.Height - contentTop - contentBottom - Padding.Top - Padding.Bottom); _currentContent.Measure(contentSize); } return availableSize; } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { Console.WriteLine($"[SkiaShell] ArrangeOverride - bounds={bounds}"); // Arrange current content with padding if (_currentContent != null) { - float contentTop = bounds.Top + (NavBarIsVisible ? NavBarHeight : 0) + ContentPadding; - float contentBottom = bounds.Bottom - (TabBarIsVisible ? TabBarHeight : 0) - ContentPadding; - var contentBounds = new SKRect( + float contentTop = (float)bounds.Top + (NavBarIsVisible ? NavBarHeight : 0) + ContentPadding; + float contentBottom = (float)bounds.Bottom - (TabBarIsVisible ? TabBarHeight : 0) - ContentPadding; + var contentBounds = new Rect( bounds.Left + ContentPadding, contentTop, - bounds.Right - ContentPadding, - contentBottom); + bounds.Width - ContentPadding * 2, + contentBottom - contentTop); Console.WriteLine($"[SkiaShell] Arranging content with bounds={contentBounds}, padding={ContentPadding}"); _currentContent.Arrange(contentBounds); } @@ -1011,8 +1011,8 @@ public class SkiaShell : SkiaLayoutView // Check flyout area if (_flyoutAnimationProgress > 0) { - float flyoutX = Bounds.Left - FlyoutWidth + (FlyoutWidth * _flyoutAnimationProgress); - var flyoutBounds = new SKRect(flyoutX, Bounds.Top, flyoutX + FlyoutWidth, Bounds.Bottom); + float flyoutX = (float)Bounds.Left - FlyoutWidth + (FlyoutWidth * _flyoutAnimationProgress); + var flyoutBounds = new SKRect(flyoutX, (float)Bounds.Top, flyoutX + FlyoutWidth, (float)Bounds.Bottom); if (flyoutBounds.Contains(x, y)) { @@ -1027,13 +1027,13 @@ public class SkiaShell : SkiaLayoutView } // Check nav bar - if (NavBarIsVisible && y < Bounds.Top + NavBarHeight) + if (NavBarIsVisible && y < (float)Bounds.Top + NavBarHeight) { return this; } // Check tab bar - if (TabBarIsVisible && y > Bounds.Bottom - TabBarHeight) + if (TabBarIsVisible && y > (float)Bounds.Bottom - TabBarHeight) { return this; } @@ -1055,8 +1055,8 @@ public class SkiaShell : SkiaLayoutView // Check flyout tap if (_flyoutAnimationProgress > 0) { - float flyoutX = Bounds.Left - FlyoutWidth + (FlyoutWidth * _flyoutAnimationProgress); - var flyoutBounds = new SKRect(flyoutX, Bounds.Top, flyoutX + FlyoutWidth, Bounds.Bottom); + float flyoutX = (float)Bounds.Left - FlyoutWidth + (FlyoutWidth * _flyoutAnimationProgress); + var flyoutBounds = new SKRect(flyoutX, (float)Bounds.Top, flyoutX + FlyoutWidth, (float)Bounds.Bottom); if (flyoutBounds.Contains(e.X, e.Y)) { @@ -1105,13 +1105,13 @@ public class SkiaShell : SkiaLayoutView } // Check tab bar tap - if (TabBarIsVisible && e.Y > Bounds.Bottom - TabBarHeight) + if (TabBarIsVisible && e.Y > (float)Bounds.Bottom - TabBarHeight) { if (_selectedSectionIndex >= 0 && _selectedSectionIndex < _sections.Count) { var section = _sections[_selectedSectionIndex]; - float tabWidth = Bounds.Width / section.Items.Count; - int tappedIndex = (int)((e.X - Bounds.Left) / tabWidth); + float tabWidth = (float)Bounds.Width / section.Items.Count; + int tappedIndex = (int)((e.X - (float)Bounds.Left) / tabWidth); tappedIndex = Math.Clamp(tappedIndex, 0, section.Items.Count - 1); if (tappedIndex != _selectedItemIndex) @@ -1130,8 +1130,8 @@ public class SkiaShell : SkiaLayoutView { if (FlyoutIsPresented && _flyoutAnimationProgress > 0) { - float flyoutX = Bounds.Left - FlyoutWidth + (FlyoutWidth * _flyoutAnimationProgress); - var flyoutBounds = new SKRect(flyoutX, Bounds.Top, flyoutX + FlyoutWidth, Bounds.Bottom); + float flyoutX = (float)Bounds.Left - FlyoutWidth + (FlyoutWidth * _flyoutAnimationProgress); + var flyoutBounds = new SKRect(flyoutX, (float)Bounds.Top, flyoutX + FlyoutWidth, (float)Bounds.Bottom); if (flyoutBounds.Contains(e.X, e.Y)) { diff --git a/Views/SkiaSlider.cs b/Views/SkiaSlider.cs index 987b7db..b62b4c4 100644 --- a/Views/SkiaSlider.cs +++ b/Views/SkiaSlider.cs @@ -476,10 +476,10 @@ public class SkiaSlider : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - var thumbRadius = (float)ThumbRadius; - return new SKSize(200, thumbRadius * 2 + 16); + var thumbRadius = ThumbRadius; + return new Size(200, thumbRadius * 2 + 16); } #endregion diff --git a/Views/SkiaStepper.cs b/Views/SkiaStepper.cs index 703a072..1d5fc3c 100644 --- a/Views/SkiaStepper.cs +++ b/Views/SkiaStepper.cs @@ -520,10 +520,10 @@ public class SkiaStepper : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - var buttonWidth = (float)ButtonWidth; - return new SKSize(buttonWidth * 2 + 1, 32); + var buttonWidth = ButtonWidth; + return new Size(buttonWidth * 2 + 1, 32); } #endregion diff --git a/Views/SkiaSwipeView.cs b/Views/SkiaSwipeView.cs index 7146dfa..ac8acdd 100644 --- a/Views/SkiaSwipeView.cs +++ b/Views/SkiaSwipeView.cs @@ -137,24 +137,24 @@ public class SkiaSwipeView : SkiaLayoutView Invalidate(); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { if (_content != null) { - _content.Measure(availableSize); + _content.Measure(new Size(availableSize.Width, availableSize.Height)); } return availableSize; } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { if (_content != null) { - var contentBounds = new SKRect( + var contentBounds = new Rect( bounds.Left + _swipeOffset, bounds.Top, - bounds.Right + _swipeOffset, - bounds.Bottom); + bounds.Width, + bounds.Height); _content.Arrange(contentBounds); } return bounds; diff --git a/Views/SkiaSwitch.cs b/Views/SkiaSwitch.cs index 8ce05eb..5620f5c 100644 --- a/Views/SkiaSwitch.cs +++ b/Views/SkiaSwitch.cs @@ -439,11 +439,11 @@ public class SkiaSwitch : SkiaView #region Layout - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - var trackWidth = (float)TrackWidth; - var trackHeight = (float)TrackHeight; - return new SKSize(trackWidth + 8f, trackHeight + 8f); + var trackWidth = TrackWidth; + var trackHeight = TrackHeight; + return new Size(trackWidth + 8, trackHeight + 8); } #endregion diff --git a/Views/SkiaTabbedPage.cs b/Views/SkiaTabbedPage.cs index 26f723a..dd45c0a 100644 --- a/Views/SkiaTabbedPage.cs +++ b/Views/SkiaTabbedPage.cs @@ -216,11 +216,11 @@ public class SkiaTabbedPage : SkiaLayoutView Invalidate(); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { // Measure the content area (excluding tab bar) var contentHeight = availableSize.Height - TabBarHeight; - var contentSize = new SKSize(availableSize.Width, contentHeight); + var contentSize = new Size(availableSize.Width, contentHeight); foreach (var tab in _tabs) { @@ -230,25 +230,25 @@ public class SkiaTabbedPage : SkiaLayoutView return availableSize; } - protected override SKRect ArrangeOverride(SKRect bounds) + protected override Rect ArrangeOverride(Rect bounds) { // Calculate content bounds based on tab bar position - SKRect contentBounds; + Rect contentBounds; if (TabBarOnBottom) { - contentBounds = new SKRect( + contentBounds = new Rect( bounds.Left, bounds.Top, - bounds.Right, - bounds.Bottom - TabBarHeight); + bounds.Width, + bounds.Height - TabBarHeight); } else { - contentBounds = new SKRect( + contentBounds = new Rect( bounds.Left, bounds.Top + TabBarHeight, - bounds.Right, - bounds.Bottom); + bounds.Width, + bounds.Height - TabBarHeight); } // Arrange each tab's content to fill the content area @@ -284,18 +284,18 @@ public class SkiaTabbedPage : SkiaLayoutView if (TabBarOnBottom) { tabBarBounds = new SKRect( - Bounds.Left, - Bounds.Bottom - TabBarHeight, - Bounds.Right, - Bounds.Bottom); + (float)Bounds.Left, + (float)Bounds.Bottom - TabBarHeight, + (float)Bounds.Right, + (float)Bounds.Bottom); } else { tabBarBounds = new SKRect( - Bounds.Left, - Bounds.Top, - Bounds.Right, - Bounds.Top + TabBarHeight); + (float)Bounds.Left, + (float)Bounds.Top, + (float)Bounds.Right, + (float)Bounds.Top + TabBarHeight); } // Draw background @@ -377,18 +377,18 @@ public class SkiaTabbedPage : SkiaLayoutView if (TabBarOnBottom) { tabBarBounds = new SKRect( - Bounds.Left, - Bounds.Bottom - TabBarHeight, - Bounds.Right, - Bounds.Bottom); + (float)Bounds.Left, + (float)(Bounds.Top + Bounds.Height) - TabBarHeight, + (float)(Bounds.Left + Bounds.Width), + (float)(Bounds.Top + Bounds.Height)); } else { tabBarBounds = new SKRect( - Bounds.Left, - Bounds.Top, - Bounds.Right, - Bounds.Top + TabBarHeight); + (float)Bounds.Left, + (float)Bounds.Top, + (float)(Bounds.Left + Bounds.Width), + (float)Bounds.Top + TabBarHeight); } if (tabBarBounds.Contains(x, y)) @@ -415,18 +415,18 @@ public class SkiaTabbedPage : SkiaLayoutView if (TabBarOnBottom) { tabBarBounds = new SKRect( - Bounds.Left, - Bounds.Bottom - TabBarHeight, - Bounds.Right, - Bounds.Bottom); + (float)Bounds.Left, + (float)(Bounds.Top + Bounds.Height) - TabBarHeight, + (float)(Bounds.Left + Bounds.Width), + (float)(Bounds.Top + Bounds.Height)); } else { tabBarBounds = new SKRect( - Bounds.Left, - Bounds.Top, - Bounds.Right, - Bounds.Top + TabBarHeight); + (float)Bounds.Left, + (float)Bounds.Top, + (float)(Bounds.Left + Bounds.Width), + (float)Bounds.Top + TabBarHeight); } if (tabBarBounds.Contains(e.X, e.Y) && _tabs.Count > 0) diff --git a/Views/SkiaTemplatedView.cs b/Views/SkiaTemplatedView.cs index f4e25de..955f121 100644 --- a/Views/SkiaTemplatedView.cs +++ b/Views/SkiaTemplatedView.cs @@ -323,11 +323,12 @@ public abstract class SkiaTemplatedView : SkiaView /// protected abstract void DrawDefaultAppearance(SKCanvas canvas, SKRect bounds); - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { if (_templateRoot != null && _templateApplied) { - return _templateRoot.Measure(availableSize); + var measured = _templateRoot.Measure(new Size(availableSize.Width, availableSize.Height)); + return new Size(measured.Width, measured.Height); } return MeasureDefaultAppearance(availableSize); @@ -337,12 +338,12 @@ public abstract class SkiaTemplatedView : SkiaView /// Measures the default appearance when no template is applied. /// Override in derived classes. /// - protected virtual SKSize MeasureDefaultAppearance(SKSize availableSize) + protected virtual Size MeasureDefaultAppearance(Size availableSize) { - return new SKSize(100, 40); + return new Size(100, 40); } - public new void Arrange(SKRect bounds) + public new void Arrange(Rect bounds) { base.Arrange(bounds); diff --git a/Views/SkiaTimePicker.cs b/Views/SkiaTimePicker.cs index e37b247..b3560c1 100644 --- a/Views/SkiaTimePicker.cs +++ b/Views/SkiaTimePicker.cs @@ -278,7 +278,8 @@ public class SkiaTimePicker : SkiaView private void DrawClockOverlay(SKCanvas canvas) { if (!_isOpen) return; - DrawClockPopup(canvas, ScreenBounds); + var sb = ScreenBounds; + DrawClockPopup(canvas, new SKRect((float)sb.Left, (float)sb.Top, (float)sb.Right, (float)sb.Bottom)); } private void DrawPickerButton(SKCanvas canvas, SKRect bounds) @@ -499,7 +500,7 @@ public class SkiaTimePicker : SkiaView if (IsOpen) { var screenBounds = ScreenBounds; - var popupRect = GetPopupRect(screenBounds); + var popupRect = GetPopupRect(new SKRect((float)screenBounds.Left, (float)screenBounds.Top, (float)screenBounds.Right, (float)screenBounds.Bottom)); var headerRect = new SKRect(popupRect.Left, popupRect.Top, popupRect.Right, popupRect.Top + HeaderHeight); if (headerRect.Contains(e.X, e.Y)) @@ -598,9 +599,9 @@ public class SkiaTimePicker : SkiaView Invalidate(); } - protected override SKSize MeasureOverride(SKSize availableSize) + protected override Size MeasureOverride(Size availableSize) { - return new SKSize(availableSize.Width < float.MaxValue ? Math.Min(availableSize.Width, 200) : 200, 40); + return new Size(availableSize.Width < double.MaxValue ? Math.Min(availableSize.Width, 200) : 200, 40); } protected override bool HitTestPopupArea(float x, float y) @@ -611,7 +612,7 @@ public class SkiaTimePicker : SkiaView if (_isOpen) { - var popupRect = GetPopupRect(screenBounds); + var popupRect = GetPopupRect(new SKRect((float)screenBounds.Left, (float)screenBounds.Top, (float)screenBounds.Right, (float)screenBounds.Bottom)); return popupRect.Contains(x, y); } diff --git a/Views/SkiaView.cs b/Views/SkiaView.cs index 1e34edf..faa36c6 100644 --- a/Views/SkiaView.cs +++ b/Views/SkiaView.cs @@ -3,6 +3,7 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Shapes; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform.Linux; using Microsoft.Maui.Platform.Linux.Handlers; using Microsoft.Maui.Platform.Linux.Rendering; @@ -701,14 +702,14 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible #endregion private bool _disposed; - private SKRect _bounds; + private Rect _bounds; private SkiaView? _parent; private readonly List _children = new(); /// /// Gets the absolute bounds of this view in screen coordinates. /// - public SKRect GetAbsoluteBounds() + public Rect GetAbsoluteBounds() { var bounds = Bounds; var current = Parent; @@ -717,11 +718,11 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible // Adjust for scroll offset if parent is a ScrollView if (current is SkiaScrollView scrollView) { - bounds = new SKRect( + bounds = new Rect( bounds.Left - scrollView.ScrollX, bounds.Top - scrollView.ScrollY, - bounds.Right - scrollView.ScrollX, - bounds.Bottom - scrollView.ScrollY); + bounds.Width, + bounds.Height); } current = current.Parent; } @@ -730,8 +731,9 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible /// /// Gets or sets the bounds of this view in parent coordinates. + /// Uses MAUI Rect for public API compliance. /// - public SKRect Bounds + public Rect Bounds { get => _bounds; set @@ -744,6 +746,15 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible } } + /// + /// Gets the bounds as SKRect for internal SkiaSharp rendering. + /// + internal SKRect BoundsSK => new SKRect( + (float)_bounds.Left, + (float)_bounds.Top, + (float)_bounds.Right, + (float)_bounds.Bottom); + /// /// Gets or sets whether this view is visible. /// @@ -1115,7 +1126,7 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible /// /// Gets the bounds of this view in screen coordinates (accounting for scroll offsets). /// - public SKRect ScreenBounds + public Rect ScreenBounds { get { @@ -1127,11 +1138,11 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible { if (parent is SkiaScrollView scrollView) { - bounds = new SKRect( + bounds = new Rect( bounds.Left - scrollView.ScrollX, bounds.Top - scrollView.ScrollY, - bounds.Right - scrollView.ScrollX, - bounds.Bottom - scrollView.ScrollY); + bounds.Width, + bounds.Height); } parent = parent.Parent; } @@ -1142,8 +1153,14 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible /// /// Gets the desired size calculated during measure. + /// Uses MAUI Size for public API compliance. /// - public SKSize DesiredSize { get; protected set; } + public Size DesiredSize { get; protected set; } + + /// + /// Gets the desired size as SKSize for internal SkiaSharp rendering. + /// + internal SKSize DesiredSizeSK => new SKSize((float)DesiredSize.Width, (float)DesiredSize.Height); /// /// Gets the child views. @@ -1262,7 +1279,9 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible // Notify rendering engine of dirty region if (Bounds.Width > 0 && Bounds.Height > 0) { - SkiaRenderingEngine.Current?.InvalidateRegion(Bounds); + SkiaRenderingEngine.Current?.InvalidateRegion(new SKRect( + (float)Bounds.Left, (float)Bounds.Top, + (float)Bounds.Right, (float)Bounds.Bottom)); } if (_parent != null) @@ -1280,7 +1299,7 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible /// public void InvalidateMeasure() { - DesiredSize = SKSize.Empty; + DesiredSize = Size.Zero; _parent?.InvalidateMeasure(); Invalidate(); } @@ -1297,14 +1316,17 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible canvas.Save(); + // Get SKRect for internal rendering + var skBounds = BoundsSK; + // Apply transforms if any are set if (Scale != 1.0 || ScaleX != 1.0 || ScaleY != 1.0 || Rotation != 0.0 || RotationX != 0.0 || RotationY != 0.0 || TranslationX != 0.0 || TranslationY != 0.0) { // Calculate anchor point in absolute coordinates - float anchorAbsX = Bounds.Left + (float)(Bounds.Width * AnchorX); - float anchorAbsY = Bounds.Top + (float)(Bounds.Height * AnchorY); + float anchorAbsX = skBounds.Left + (float)(Bounds.Width * AnchorX); + float anchorAbsY = skBounds.Top + (float)(Bounds.Height * AnchorY); // Move origin to anchor point canvas.Translate(anchorAbsX, anchorAbsY); @@ -1342,20 +1364,20 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible // Draw shadow if set if (Shadow != null) { - DrawShadow(canvas, Bounds); + DrawShadow(canvas, skBounds); } // Apply clip geometry if set if (Clip != null) { - ApplyClip(canvas, Bounds); + ApplyClip(canvas, skBounds); } // Draw background at absolute bounds - DrawBackground(canvas, Bounds); + DrawBackground(canvas, skBounds); // Draw content at absolute bounds - OnDraw(canvas, Bounds); + OnDraw(canvas, skBounds); // Draw children - they draw at their own absolute bounds foreach (var child in _children) @@ -1530,8 +1552,9 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible /// /// Measures the desired size of this view. + /// Uses MAUI Size for public API compliance. /// - public SKSize Measure(SKSize availableSize) + public Size Measure(Size availableSize) { DesiredSize = MeasureOverride(availableSize); return DesiredSize; @@ -1539,36 +1562,40 @@ public abstract class SkiaView : BindableObject, IDisposable, IAccessible /// /// Override to provide custom measurement. + /// Uses MAUI Size for public API compliance. /// - protected virtual SKSize MeasureOverride(SKSize availableSize) + protected virtual Size MeasureOverride(Size availableSize) { - var width = WidthRequest >= 0 ? (float)WidthRequest : 0; - var height = HeightRequest >= 0 ? (float)HeightRequest : 0; - return new SKSize(width, height); + var width = WidthRequest >= 0 ? WidthRequest : 0; + var height = HeightRequest >= 0 ? HeightRequest : 0; + return new Size(width, height); } /// /// Arranges this view within the given bounds. + /// Uses MAUI Rect for public API compliance. /// - public virtual void Arrange(SKRect bounds) + public virtual void Arrange(Rect bounds) { Bounds = ArrangeOverride(bounds); } /// /// Override to customize arrangement within the given bounds. + /// Uses MAUI Rect for public API compliance. /// - protected virtual SKRect ArrangeOverride(SKRect bounds) + protected virtual Rect ArrangeOverride(Rect bounds) { return bounds; } /// /// Performs hit testing to find the view at the given point. + /// Uses MAUI Point for public API compliance. /// - public virtual SkiaView? HitTest(SKPoint point) + public virtual SkiaView? HitTest(Point point) { - return HitTest(point.X, point.Y); + return HitTest((float)point.X, (float)point.Y); } /// diff --git a/Views/SkiaWebView.cs b/Views/SkiaWebView.cs index 63faad3..457e58c 100644 --- a/Views/SkiaWebView.cs +++ b/Views/SkiaWebView.cs @@ -137,7 +137,7 @@ public class SkiaWebView : SkiaView private string? _userAgent; private CookieContainer _cookies = new(); private double _loadProgress; - private SKRect _lastBounds; + private Rect _lastBounds; private int _lastMainX; private int _lastMainY; private int _lastPosX; @@ -1340,7 +1340,7 @@ public class SkiaWebView : SkiaView protected override void OnDraw(SKCanvas canvas, SKRect bounds) { base.OnDraw(canvas, bounds); - Bounds = bounds; + Bounds = new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height); if (_isInitialized) { @@ -1364,7 +1364,7 @@ public class SkiaWebView : SkiaView if (needsUpdate && bounds.Width > 50f && bounds.Height > 50f) { PositionUsingGtk(); - _lastBounds = bounds; + _lastBounds = new Rect(bounds.Left, bounds.Top, bounds.Width, bounds.Height); } } } diff --git a/tests/OpenMaui.Controls.Linux.Tests.csproj b/tests/OpenMaui.Controls.Linux.Tests.csproj index 1010a5b..61c9c55 100644 --- a/tests/OpenMaui.Controls.Linux.Tests.csproj +++ b/tests/OpenMaui.Controls.Linux.Tests.csproj @@ -21,7 +21,9 @@ - + + + diff --git a/tests/Views/SkiaButtonTests.cs b/tests/Views/SkiaButtonTests.cs index 0f961d0..5784893 100644 --- a/tests/Views/SkiaButtonTests.cs +++ b/tests/Views/SkiaButtonTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform; using SkiaSharp; using Xunit; @@ -42,7 +43,7 @@ public class SkiaButtonTests var button = new SkiaButton { Text = "Test" }; // Act - var size = button.Measure(new SKSize(1000, 1000)); + var size = button.Measure(new Size(1000, 1000)); // Assert size.Width.Should().BeGreaterThan(0); @@ -61,7 +62,7 @@ public class SkiaButtonTests }; // Act - var size = button.Measure(new SKSize(1000, 1000)); + var size = button.Measure(new Size(1000, 1000)); // Assert - Measure returns content-based size size.Width.Should().BeGreaterThan(0); @@ -100,7 +101,7 @@ public class SkiaButtonTests { // Arrange var button = new SkiaButton { Text = "Test" }; - button.Bounds = new SKRect(0, 0, 100, 40); + button.Bounds = new Rect(0, 0, 100, 40); using var surface = SKSurface.Create(new SKImageInfo(200, 100)); var canvas = surface.Canvas; @@ -129,7 +130,7 @@ public class SkiaButtonTests { // Arrange var button = new SkiaButton(); - var color = new SKColor(0, 255, 0); + var color = Microsoft.Maui.Graphics.Color.FromRgb(0, 255, 0); // Act button.BackgroundColor = color; diff --git a/tests/Views/SkiaCarouselViewTests.cs b/tests/Views/SkiaCarouselViewTests.cs index 148bba9..96caa64 100644 --- a/tests/Views/SkiaCarouselViewTests.cs +++ b/tests/Views/SkiaCarouselViewTests.cs @@ -1,6 +1,7 @@ // 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.Graphics; using SkiaSharp; using Xunit; @@ -15,7 +16,7 @@ public class SkiaCarouselViewTests Assert.Equal(0, carousel.Position); Assert.False(carousel.Loop); - Assert.Equal(0f, carousel.PeekAreaInsets); + Assert.Equal(0.0, carousel.PeekAreaInsets); Assert.Equal(0, carousel.ItemCount); } @@ -71,9 +72,9 @@ public class SkiaCarouselViewTests { var carousel = new SkiaCarouselView(); - carousel.PeekAreaInsets = 20f; + carousel.PeekAreaInsets = 20.0; - Assert.Equal(20f, carousel.PeekAreaInsets); + Assert.Equal(20.0, carousel.PeekAreaInsets); } [Fact] @@ -180,9 +181,9 @@ public class SkiaCarouselViewTests { var carousel = new SkiaCarouselView(); - carousel.IndicatorColor = SKColors.Gray; + carousel.IndicatorColor = Colors.Grey; - Assert.Equal(SKColors.Gray, carousel.IndicatorColor); + Assert.Equal(Colors.Grey, carousel.IndicatorColor); } [Fact] @@ -190,9 +191,9 @@ public class SkiaCarouselViewTests { var carousel = new SkiaCarouselView(); - carousel.SelectedIndicatorColor = SKColors.Blue; + carousel.SelectedIndicatorColor = Colors.Blue; - Assert.Equal(SKColors.Blue, carousel.SelectedIndicatorColor); + Assert.Equal(Colors.Blue, carousel.SelectedIndicatorColor); } [Fact] @@ -213,7 +214,7 @@ public class SkiaCarouselViewTests { var carousel = new SkiaCarouselView(); - Assert.Equal(0f, carousel.ItemSpacing); + Assert.Equal(0.0, carousel.ItemSpacing); } [Fact] @@ -221,9 +222,9 @@ public class SkiaCarouselViewTests { var carousel = new SkiaCarouselView(); - carousel.ItemSpacing = 16f; + carousel.ItemSpacing = 16.0; - Assert.Equal(16f, carousel.ItemSpacing); + Assert.Equal(16.0, carousel.ItemSpacing); } [Fact] @@ -245,7 +246,7 @@ public class SkiaCarouselViewTests { var carousel = new SkiaCarouselView(); carousel.AddItem(new SkiaLabel { Text = "Item" }); - carousel.Arrange(new SKRect(0, 0, 300, 200)); + carousel.Arrange(new Rect(0, 0, 300, 200)); var hit = carousel.HitTest(150, 100); diff --git a/tests/Views/SkiaEntryTests.cs b/tests/Views/SkiaEntryTests.cs index 39f605e..f337548 100644 --- a/tests/Views/SkiaEntryTests.cs +++ b/tests/Views/SkiaEntryTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform; using SkiaSharp; using Xunit; @@ -104,7 +105,7 @@ public class SkiaEntryTests { // Arrange var entry = new SkiaEntry { Text = "Hello" }; - entry.Bounds = new SKRect(0, 0, 200, 40); + entry.Bounds = new Rect(0, 0, 200, 40); entry.OnFocusGained(); var originalLength = entry.Text.Length; @@ -120,7 +121,7 @@ public class SkiaEntryTests { // Arrange var entry = new SkiaEntry { Text = "Hello" }; - entry.Bounds = new SKRect(0, 0, 200, 40); + entry.Bounds = new Rect(0, 0, 200, 40); entry.OnFocusGained(); // Act - Verify OnKeyDown doesn't throw @@ -136,7 +137,7 @@ public class SkiaEntryTests // Arrange var entry = new SkiaEntry { Text = "Hello", IsReadOnly = true }; var originalText = entry.Text; - entry.Bounds = new SKRect(0, 0, 200, 40); + entry.Bounds = new Rect(0, 0, 200, 40); entry.OnFocusGained(); // Act @@ -164,7 +165,7 @@ public class SkiaEntryTests { // Arrange var entry = new SkiaEntry { Text = "Test", Placeholder = "Enter..." }; - entry.Bounds = new SKRect(0, 0, 200, 40); + entry.Bounds = new Rect(0, 0, 200, 40); using var surface = SKSurface.Create(new SKImageInfo(300, 100)); var canvas = surface.Canvas; diff --git a/tests/Views/SkiaIndicatorViewTests.cs b/tests/Views/SkiaIndicatorViewTests.cs index 24200ad..808c7af 100644 --- a/tests/Views/SkiaIndicatorViewTests.cs +++ b/tests/Views/SkiaIndicatorViewTests.cs @@ -1,6 +1,7 @@ // 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.Graphics; using SkiaSharp; using Xunit; @@ -66,9 +67,9 @@ public class SkiaIndicatorViewTests { var indicator = new SkiaIndicatorView(); - indicator.IndicatorColor = SKColors.Gray; + indicator.IndicatorColor = Colors.Grey; - Assert.Equal(SKColors.Gray, indicator.IndicatorColor); + Assert.Equal(Colors.Grey, indicator.IndicatorColor); } [Fact] @@ -76,9 +77,9 @@ public class SkiaIndicatorViewTests { var indicator = new SkiaIndicatorView(); - indicator.SelectedIndicatorColor = SKColors.Blue; + indicator.SelectedIndicatorColor = Colors.Blue; - Assert.Equal(SKColors.Blue, indicator.SelectedIndicatorColor); + Assert.Equal(Colors.Blue, indicator.SelectedIndicatorColor); } [Fact] @@ -86,9 +87,9 @@ public class SkiaIndicatorViewTests { var indicator = new SkiaIndicatorView(); - indicator.IndicatorSize = 12f; + indicator.IndicatorSize = 12.0; - Assert.Equal(12f, indicator.IndicatorSize); + Assert.Equal(12.0, indicator.IndicatorSize); } [Fact] @@ -96,9 +97,9 @@ public class SkiaIndicatorViewTests { var indicator = new SkiaIndicatorView(); - indicator.SelectedIndicatorSize = 16f; + indicator.SelectedIndicatorSize = 16.0; - Assert.Equal(16f, indicator.SelectedIndicatorSize); + Assert.Equal(16.0, indicator.SelectedIndicatorSize); } [Fact] @@ -106,9 +107,9 @@ public class SkiaIndicatorViewTests { var indicator = new SkiaIndicatorView(); - indicator.IndicatorSpacing = 10f; + indicator.IndicatorSpacing = 10.0; - Assert.Equal(10f, indicator.IndicatorSpacing); + Assert.Equal(10.0, indicator.IndicatorSpacing); } [Fact] @@ -164,9 +165,9 @@ public class SkiaIndicatorViewTests { var indicator = new SkiaIndicatorView(); - indicator.BorderColor = SKColors.Black; + indicator.BorderColor = Colors.Black; - Assert.Equal(SKColors.Black, indicator.BorderColor); + Assert.Equal(Colors.Black, indicator.BorderColor); } [Fact] @@ -174,9 +175,9 @@ public class SkiaIndicatorViewTests { var indicator = new SkiaIndicatorView(); - indicator.BorderWidth = 2f; + indicator.BorderWidth = 2.0; - Assert.Equal(2f, indicator.BorderWidth); + Assert.Equal(2.0, indicator.BorderWidth); } [Fact] @@ -232,9 +233,9 @@ public class SkiaIndicatorViewTests { var indicator = new SkiaIndicatorView(); indicator.Count = 5; - indicator.IndicatorSize = 10f; - indicator.IndicatorSpacing = 8f; - indicator.Arrange(new SKRect(0, 0, 200, 20)); + indicator.IndicatorSize = 10.0; + indicator.IndicatorSpacing = 8.0; + indicator.Arrange(new Rect(0, 0, 200, 20)); var hit = indicator.HitTest(100, 10); diff --git a/tests/Views/SkiaMenuBarTests.cs b/tests/Views/SkiaMenuBarTests.cs index 3f61f3e..547e95f 100644 --- a/tests/Views/SkiaMenuBarTests.cs +++ b/tests/Views/SkiaMenuBarTests.cs @@ -1,6 +1,7 @@ // 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.Graphics; using SkiaSharp; using Xunit; @@ -145,9 +146,9 @@ public class SkiaMenuBarTests { var menuBar = new SkiaMenuBar(); - menuBar.BackgroundColor = SKColors.White; + menuBar.BackgroundColor = Colors.White; - Assert.Equal(SKColors.White, menuBar.BackgroundColor); + Assert.Equal(Colors.White, menuBar.BackgroundColor); } [Fact] @@ -155,9 +156,9 @@ public class SkiaMenuBarTests { var menuBar = new SkiaMenuBar(); - menuBar.TextColor = SKColors.Black; + menuBar.TextColor = Colors.Black; - Assert.Equal(SKColors.Black, menuBar.TextColor); + Assert.Equal(Colors.Black, menuBar.TextColor); } [Fact] @@ -165,9 +166,9 @@ public class SkiaMenuBarTests { var menuBar = new SkiaMenuBar(); - menuBar.HoverBackgroundColor = SKColors.LightGray; + menuBar.HoverBackgroundColor = Colors.LightGrey; - Assert.Equal(SKColors.LightGray, menuBar.HoverBackgroundColor); + Assert.Equal(Colors.LightGrey, menuBar.HoverBackgroundColor); } [Fact] @@ -175,9 +176,9 @@ public class SkiaMenuBarTests { var menuBar = new SkiaMenuBar(); - menuBar.ActiveBackgroundColor = SKColors.DarkGray; + menuBar.ActiveBackgroundColor = Colors.DarkGrey; - Assert.Equal(SKColors.DarkGray, menuBar.ActiveBackgroundColor); + Assert.Equal(Colors.DarkGrey, menuBar.ActiveBackgroundColor); } [Fact] @@ -186,7 +187,7 @@ public class SkiaMenuBarTests var menuBar = new SkiaMenuBar(); menuBar.BarHeight = 30f; - var size = menuBar.Measure(new SKSize(800, 600)); + var size = menuBar.Measure(new Size(800, 600)); Assert.Equal(30f, size.Height); } @@ -196,7 +197,7 @@ public class SkiaMenuBarTests { var menuBar = new SkiaMenuBar(); - var size = menuBar.Measure(new SKSize(800, 600)); + var size = menuBar.Measure(new Size(800, 600)); Assert.Equal(800f, size.Width); } @@ -205,7 +206,7 @@ public class SkiaMenuBarTests public void HitTest_WithinBounds_ReturnsMenuBar() { var menuBar = new SkiaMenuBar(); - menuBar.Arrange(new SKRect(0, 0, 800, 28)); + menuBar.Arrange(new Rect(0, 0, 800, 28)); var hit = menuBar.HitTest(400, 14); @@ -216,7 +217,7 @@ public class SkiaMenuBarTests public void HitTest_OutsideBounds_ReturnsNull() { var menuBar = new SkiaMenuBar(); - menuBar.Arrange(new SKRect(0, 0, 800, 28)); + menuBar.Arrange(new Rect(0, 0, 800, 28)); var hit = menuBar.HitTest(400, 50); @@ -266,9 +267,9 @@ public class SkiaMenuFlyoutTests { var flyout = new SkiaMenuFlyout(); - flyout.BackgroundColor = SKColors.White; + flyout.BackgroundColor = Colors.White; - Assert.Equal(SKColors.White, flyout.BackgroundColor); + Assert.Equal(Colors.White, flyout.BackgroundColor); } [Fact] @@ -276,9 +277,9 @@ public class SkiaMenuFlyoutTests { var flyout = new SkiaMenuFlyout(); - flyout.TextColor = SKColors.Black; + flyout.TextColor = Colors.Black; - Assert.Equal(SKColors.Black, flyout.TextColor); + Assert.Equal(Colors.Black, flyout.TextColor); } [Fact] @@ -286,9 +287,9 @@ public class SkiaMenuFlyoutTests { var flyout = new SkiaMenuFlyout(); - flyout.DisabledTextColor = new SKColor(160, 160, 160); + flyout.DisabledTextColor = Color.FromRgb(160, 160, 160); - Assert.Equal(new SKColor(160, 160, 160), flyout.DisabledTextColor); + Assert.Equal(Color.FromRgb(160, 160, 160), flyout.DisabledTextColor); } [Fact] @@ -296,9 +297,9 @@ public class SkiaMenuFlyoutTests { var flyout = new SkiaMenuFlyout(); - flyout.HoverBackgroundColor = SKColors.LightBlue; + flyout.HoverBackgroundColor = Colors.LightBlue; - Assert.Equal(SKColors.LightBlue, flyout.HoverBackgroundColor); + Assert.Equal(Colors.LightBlue, flyout.HoverBackgroundColor); } [Fact] @@ -306,9 +307,9 @@ public class SkiaMenuFlyoutTests { var flyout = new SkiaMenuFlyout(); - flyout.SeparatorColor = SKColors.Gray; + flyout.SeparatorColor = Colors.Grey; - Assert.Equal(SKColors.Gray, flyout.SeparatorColor); + Assert.Equal(Colors.Grey, flyout.SeparatorColor); } [Fact] diff --git a/tests/Views/SkiaRefreshViewTests.cs b/tests/Views/SkiaRefreshViewTests.cs index d1ae4a6..623c31b 100644 --- a/tests/Views/SkiaRefreshViewTests.cs +++ b/tests/Views/SkiaRefreshViewTests.cs @@ -1,6 +1,7 @@ // 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.Graphics; using SkiaSharp; using Xunit; @@ -87,7 +88,7 @@ public class SkiaRefreshViewTests { var refreshView = new SkiaRefreshView(); - Assert.Equal(new SKColor(33, 150, 243), refreshView.RefreshColor); + Assert.Equal(Color.FromRgb(33, 150, 243), refreshView.RefreshColor); } [Fact] @@ -95,9 +96,9 @@ public class SkiaRefreshViewTests { var refreshView = new SkiaRefreshView(); - refreshView.RefreshColor = SKColors.Red; + refreshView.RefreshColor = Colors.Red; - Assert.Equal(SKColors.Red, refreshView.RefreshColor); + Assert.Equal(Colors.Red, refreshView.RefreshColor); } [Fact] @@ -105,7 +106,7 @@ public class SkiaRefreshViewTests { var refreshView = new SkiaRefreshView(); - Assert.Equal(SKColors.White, refreshView.RefreshBackgroundColor); + Assert.Equal(Colors.White, refreshView.RefreshBackgroundColor); } [Fact] @@ -113,9 +114,9 @@ public class SkiaRefreshViewTests { var refreshView = new SkiaRefreshView(); - refreshView.RefreshBackgroundColor = SKColors.LightGray; + refreshView.RefreshBackgroundColor = Colors.LightGrey; - Assert.Equal(SKColors.LightGray, refreshView.RefreshBackgroundColor); + Assert.Equal(Colors.LightGrey, refreshView.RefreshBackgroundColor); } [Fact] @@ -135,7 +136,7 @@ public class SkiaRefreshViewTests var refreshView = new SkiaRefreshView(); var content = new SkiaLabel { Text = "Test" }; refreshView.Content = content; - refreshView.Arrange(new SKRect(0, 0, 200, 400)); + refreshView.Arrange(new Rect(0, 0, 200, 400)); var hit = refreshView.HitTest(100, 200); diff --git a/tests/Views/SkiaScrollViewTests.cs b/tests/Views/SkiaScrollViewTests.cs index 54d9967..234eee7 100644 --- a/tests/Views/SkiaScrollViewTests.cs +++ b/tests/Views/SkiaScrollViewTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform; using SkiaSharp; using Xunit; @@ -46,8 +47,8 @@ public class SkiaScrollViewTests content.AddChild(new SkiaButton { Text = "1", RequestedHeight = 100 }); content.AddChild(new SkiaButton { Text = "2", RequestedHeight = 100 }); scrollView.Content = content; - scrollView.Measure(new SKSize(200, 100)); // Viewport smaller than content - scrollView.Arrange(new SKRect(0, 0, 200, 100)); + scrollView.Measure(new Size(200, 100)); // Viewport smaller than content + scrollView.Arrange(new Rect(0, 0, 200, 100)); // Act - Try to scroll below 0 scrollView.ScrollY = -50; @@ -67,8 +68,8 @@ public class SkiaScrollViewTests content.AddChild(new SkiaButton { Text = $"Button {i}", RequestedHeight = 50 }); } scrollView.Content = content; - scrollView.Measure(new SKSize(200, 300)); - scrollView.Arrange(new SKRect(0, 0, 200, 300)); + scrollView.Measure(new Size(200, 300)); + scrollView.Arrange(new Rect(0, 0, 200, 300)); var initialScrollY = scrollView.ScrollY; @@ -89,8 +90,8 @@ public class SkiaScrollViewTests content.AddChild(button); scrollView.Content = content; - scrollView.Measure(new SKSize(200, 200)); - scrollView.Arrange(new SKRect(0, 0, 200, 200)); + scrollView.Measure(new Size(200, 200)); + scrollView.Arrange(new Rect(0, 0, 200, 200)); // Act var hit = scrollView.HitTest(100, 25); @@ -111,8 +112,8 @@ public class SkiaScrollViewTests } scrollView.Content = content; - scrollView.Measure(new SKSize(200, 100)); - scrollView.Arrange(new SKRect(0, 0, 200, 100)); + scrollView.Measure(new Size(200, 100)); + scrollView.Arrange(new Rect(0, 0, 200, 100)); // Act scrollView.ScrollY = 50; @@ -129,7 +130,7 @@ public class SkiaScrollViewTests var content = new SkiaStackLayout(); content.AddChild(new SkiaButton { Text = "Test" }); scrollView.Content = content; - scrollView.Bounds = new SKRect(0, 0, 200, 200); + scrollView.Bounds = new Rect(0, 0, 200, 200); using var surface = SKSurface.Create(new SKImageInfo(300, 300)); var canvas = surface.Canvas; @@ -150,8 +151,8 @@ public class SkiaScrollViewTests content.AddChild(new SkiaButton { Text = $"Button {i}", RequestedHeight = 50 }); } scrollView.Content = content; - scrollView.Measure(new SKSize(200, 200)); - scrollView.Arrange(new SKRect(0, 0, 200, 200)); + scrollView.Measure(new Size(200, 200)); + scrollView.Arrange(new Rect(0, 0, 200, 200)); // Act - Scroll to maximum scrollView.ScrollY = 10000; // Very large value diff --git a/tests/Views/SkiaSliderTests.cs b/tests/Views/SkiaSliderTests.cs index 50645e5..9e464c9 100644 --- a/tests/Views/SkiaSliderTests.cs +++ b/tests/Views/SkiaSliderTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform; using SkiaSharp; using Xunit; @@ -19,7 +20,7 @@ public class SkiaSliderTests // Assert slider.Value.Should().Be(0); slider.Minimum.Should().Be(0); - slider.Maximum.Should().Be(100); // Default maximum is 100 + slider.Maximum.Should().Be(1.0); // MAUI Slider.Maximum default is 1.0 slider.IsEnabled.Should().BeTrue(); } @@ -120,7 +121,7 @@ public class SkiaSliderTests { // Arrange var slider = new SkiaSlider { Value = 50, Minimum = 0, Maximum = 100 }; - slider.Bounds = new SKRect(0, 0, 200, 40); + slider.Bounds = new Rect(0, 0, 200, 40); using var surface = SKSurface.Create(new SKImageInfo(300, 100)); var canvas = surface.Canvas; diff --git a/tests/Views/SkiaStackLayoutTests.cs b/tests/Views/SkiaStackLayoutTests.cs index 272c057..b3d6565 100644 --- a/tests/Views/SkiaStackLayoutTests.cs +++ b/tests/Views/SkiaStackLayoutTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using FluentAssertions; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform; using SkiaSharp; using Xunit; @@ -68,7 +69,7 @@ public class SkiaStackLayoutTests layout.AddChild(new SkiaButton { Text = "3" }); // Act - var size = layout.Measure(new SKSize(200, 1000)); + var size = layout.Measure(new Size(200, 1000)); // Assert - Size should account for 3 children with spacing size.Height.Should().BeGreaterThan(0); @@ -89,7 +90,7 @@ public class SkiaStackLayoutTests layout.AddChild(new SkiaButton { Text = "3" }); // Act - var size = layout.Measure(new SKSize(1000, 200)); + var size = layout.Measure(new Size(1000, 200)); // Assert - Size should account for 3 children with spacing size.Width.Should().BeGreaterThan(0); @@ -111,8 +112,8 @@ public class SkiaStackLayoutTests layout.AddChild(button2); // Act - layout.Measure(new SKSize(200, 500)); - layout.Arrange(new SKRect(0, 0, 200, 500)); + layout.Measure(new Size(200, 500)); + layout.Arrange(new Rect(0, 0, 200, 500)); // Assert - Button2 should be below Button1 button2.Bounds.Top.Should().BeGreaterThan(button1.Bounds.Top); @@ -133,8 +134,8 @@ public class SkiaStackLayoutTests layout.AddChild(button2); // Act - layout.Measure(new SKSize(500, 200)); - layout.Arrange(new SKRect(0, 0, 500, 200)); + layout.Measure(new Size(500, 200)); + layout.Arrange(new Rect(0, 0, 500, 200)); // Assert - Button2 should be to the right of Button1 button2.Bounds.Left.Should().BeGreaterThan(button1.Bounds.Left); @@ -147,14 +148,14 @@ public class SkiaStackLayoutTests var layout = new SkiaStackLayout { Orientation = PlatformStackOrientation.Vertical, - Padding = new SKRect(20, 20, 20, 20) + Padding = new Microsoft.Maui.Thickness(20, 20, 20, 20) }; var button = new SkiaButton { Text = "Test" }; layout.AddChild(button); // Act - layout.Measure(new SKSize(300, 300)); - layout.Arrange(new SKRect(0, 0, 300, 300)); + layout.Measure(new Size(300, 300)); + layout.Arrange(new Rect(0, 0, 300, 300)); // Assert - Padding property is set layout.Padding.Left.Should().Be(20); @@ -168,7 +169,7 @@ public class SkiaStackLayoutTests var layout = new SkiaStackLayout(); layout.AddChild(new SkiaButton { Text = "1" }); layout.AddChild(new SkiaButton { Text = "2" }); - layout.Bounds = new SKRect(0, 0, 200, 200); + layout.Bounds = new Rect(0, 0, 200, 200); using var surface = SKSurface.Create(new SKImageInfo(300, 300)); var canvas = surface.Canvas; @@ -188,8 +189,8 @@ public class SkiaStackLayoutTests layout.AddChild(button1); layout.AddChild(button2); - layout.Measure(new SKSize(200, 200)); - layout.Arrange(new SKRect(0, 0, 200, 200)); + layout.Measure(new Size(200, 200)); + layout.Arrange(new Rect(0, 0, 200, 200)); // Act - Hit test within layout bounds var hit = layout.HitTest(100, 10); diff --git a/tests/Views/SkiaSwipeViewTests.cs b/tests/Views/SkiaSwipeViewTests.cs index dffe000..d460c86 100644 --- a/tests/Views/SkiaSwipeViewTests.cs +++ b/tests/Views/SkiaSwipeViewTests.cs @@ -1,6 +1,7 @@ // 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.Graphics; using SkiaSharp; using Xunit; @@ -36,7 +37,7 @@ public class SkiaSwipeViewTests public void LeftItems_CanAddItems() { var swipeView = new SkiaSwipeView(); - var item = new SwipeItem { Text = "Delete", BackgroundColor = SKColors.Red }; + var item = new SwipeItem { Text = "Delete", BackgroundColor = Colors.Red }; swipeView.LeftItems.Add(item); @@ -48,7 +49,7 @@ public class SkiaSwipeViewTests public void RightItems_CanAddItems() { var swipeView = new SkiaSwipeView(); - var item = new SwipeItem { Text = "Archive", BackgroundColor = SKColors.Blue }; + var item = new SwipeItem { Text = "Archive", BackgroundColor = Colors.Blue }; swipeView.RightItems.Add(item); @@ -146,17 +147,17 @@ public class SkiaSwipeViewTests [Fact] public void SwipeItem_TextColor_CanBeSet() { - var item = new SwipeItem { TextColor = SKColors.Yellow }; + var item = new SwipeItem { TextColor = Colors.Yellow }; - Assert.Equal(SKColors.Yellow, item.TextColor); + Assert.Equal(Colors.Yellow, item.TextColor); } [Fact] public void SwipeItem_BackgroundColor_CanBeSet() { - var item = new SwipeItem { BackgroundColor = SKColors.Green }; + var item = new SwipeItem { BackgroundColor = Colors.Green }; - Assert.Equal(SKColors.Green, item.BackgroundColor); + Assert.Equal(Colors.Green, item.BackgroundColor); } [Fact] @@ -190,7 +191,7 @@ public class SkiaSwipeViewTests { var swipeView = new SkiaSwipeView(); swipeView.Content = new SkiaLabel { Text = "Content" }; - swipeView.Arrange(new SKRect(0, 0, 300, 50)); + swipeView.Arrange(new Rect(0, 0, 300, 50)); var hit = swipeView.HitTest(150, 25); @@ -203,7 +204,7 @@ public class SkiaSwipeViewTests var swipeView = new SkiaSwipeView(); swipeView.Content = new SkiaLabel { Text = "Test" }; - var size = swipeView.Measure(new SKSize(300, 100)); + var size = swipeView.Measure(new Size(300, 100)); Assert.True(size.Width <= 300); Assert.True(size.Height <= 100);