Verify Views files against decompiled, extract embedded types
Fixed files: - SkiaImageButton.cs: Added SVG support with multi-path search - SkiaNavigationPage.cs: Added LinuxApplication.IsGtkMode check - SkiaRefreshView.cs: Added ICommand support (Command, CommandParameter) - SkiaTemplatedView.cs: Added missing using statements Extracted embedded types to separate files (matching decompiled pattern): - From SkiaMenuBar.cs: MenuBarItem, MenuItem, SkiaMenuFlyout, MenuItemClickedEventArgs - From SkiaNavigationPage.cs: NavigationEventArgs - From SkiaTabbedPage.cs: TabItem - From SkiaVisualStateManager.cs: SkiaVisualStateGroupList, SkiaVisualStateGroup, SkiaVisualState, SkiaVisualStateSetter - From SkiaSwipeView.cs: SwipeItem, SwipeStartedEventArgs, SwipeEndedEventArgs - From SkiaFlyoutPage.cs: FlyoutLayoutBehavior (already separate) - From SkiaIndicatorView.cs: IndicatorShape (already separate) - From SkiaBorder.cs: SkiaFrame - From SkiaCarouselView.cs: PositionChangedEventArgs - From SkiaCollectionView.cs: SkiaSelectionMode, ItemsLayoutOrientation - From SkiaContentPresenter.cs: LayoutAlignment Verified matching decompiled: - SkiaContextMenu.cs, SkiaFlexLayout.cs, SkiaGraphicsView.cs Build: 0 errors 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
13
Views/FlyoutLayoutBehavior.cs
Normal file
13
Views/FlyoutLayoutBehavior.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public enum FlyoutLayoutBehavior
|
||||
{
|
||||
Default,
|
||||
Popover,
|
||||
Split,
|
||||
SplitOnLandscape,
|
||||
SplitOnPortrait
|
||||
}
|
||||
12
Views/IndicatorShape.cs
Normal file
12
Views/IndicatorShape.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public enum IndicatorShape
|
||||
{
|
||||
Circle,
|
||||
Square,
|
||||
RoundedSquare,
|
||||
Diamond
|
||||
}
|
||||
13
Views/ItemsLayoutOrientation.cs
Normal file
13
Views/ItemsLayoutOrientation.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Layout orientation for items.
|
||||
/// </summary>
|
||||
public enum ItemsLayoutOrientation
|
||||
{
|
||||
Vertical,
|
||||
Horizontal
|
||||
}
|
||||
12
Views/LayoutAlignment.cs
Normal file
12
Views/LayoutAlignment.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public enum LayoutAlignment
|
||||
{
|
||||
Fill,
|
||||
Start,
|
||||
Center,
|
||||
End
|
||||
}
|
||||
16
Views/MenuBarItem.cs
Normal file
16
Views/MenuBarItem.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class MenuBarItem
|
||||
{
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
public List<MenuItem> Items { get; } = new List<MenuItem>();
|
||||
|
||||
internal SKRect Bounds { get; set; }
|
||||
}
|
||||
31
Views/MenuItem.cs
Normal file
31
Views/MenuItem.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class MenuItem
|
||||
{
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
public string? Shortcut { get; set; }
|
||||
|
||||
public bool IsSeparator { get; set; }
|
||||
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
public bool IsChecked { get; set; }
|
||||
|
||||
public string? IconSource { get; set; }
|
||||
|
||||
public List<MenuItem> SubItems { get; } = new List<MenuItem>();
|
||||
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
internal void OnClicked()
|
||||
{
|
||||
Clicked?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
16
Views/MenuItemClickedEventArgs.cs
Normal file
16
Views/MenuItemClickedEventArgs.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class MenuItemClickedEventArgs : EventArgs
|
||||
{
|
||||
public MenuItem Item { get; }
|
||||
|
||||
public MenuItemClickedEventArgs(MenuItem item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
}
|
||||
16
Views/NavigationEventArgs.cs
Normal file
16
Views/NavigationEventArgs.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class NavigationEventArgs : EventArgs
|
||||
{
|
||||
public SkiaPage Page { get; }
|
||||
|
||||
public NavigationEventArgs(SkiaPage page)
|
||||
{
|
||||
Page = page;
|
||||
}
|
||||
}
|
||||
21
Views/PositionChangedEventArgs.cs
Normal file
21
Views/PositionChangedEventArgs.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Event args for position changed events in carousel views.
|
||||
/// </summary>
|
||||
public class PositionChangedEventArgs : EventArgs
|
||||
{
|
||||
public int PreviousPosition { get; }
|
||||
public int CurrentPosition { get; }
|
||||
|
||||
public PositionChangedEventArgs(int previousPosition, int currentPosition)
|
||||
{
|
||||
PreviousPosition = previousPosition;
|
||||
CurrentPosition = currentPosition;
|
||||
}
|
||||
}
|
||||
@@ -385,20 +385,3 @@ public class SkiaBorder : SkiaLayoutView
|
||||
_isPressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frame control - a Border with shadow enabled by default.
|
||||
/// Mimics the MAUI Frame control appearance.
|
||||
/// </summary>
|
||||
public class SkiaFrame : SkiaBorder
|
||||
{
|
||||
public SkiaFrame()
|
||||
{
|
||||
HasShadow = true;
|
||||
CornerRadius = 4;
|
||||
SetPadding(10);
|
||||
BackgroundColor = SKColors.White;
|
||||
Stroke = SKColors.Transparent;
|
||||
StrokeThickness = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,18 +386,3 @@ public class SkiaCarouselView : SkiaLayoutView
|
||||
base.OnPointerReleased(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for position changed events.
|
||||
/// </summary>
|
||||
public class PositionChangedEventArgs : EventArgs
|
||||
{
|
||||
public int PreviousPosition { get; }
|
||||
public int CurrentPosition { get; }
|
||||
|
||||
public PositionChangedEventArgs(int previousPosition, int currentPosition)
|
||||
{
|
||||
PreviousPosition = previousPosition;
|
||||
CurrentPosition = currentPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,25 +9,6 @@ using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Selection mode for collection views.
|
||||
/// </summary>
|
||||
public enum SkiaSelectionMode
|
||||
{
|
||||
None,
|
||||
Single,
|
||||
Multiple
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Layout orientation for items.
|
||||
/// </summary>
|
||||
public enum ItemsLayoutOrientation
|
||||
{
|
||||
Vertical,
|
||||
Horizontal
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skia-rendered CollectionView with selection, headers, and flexible layouts.
|
||||
/// </summary>
|
||||
|
||||
@@ -229,29 +229,3 @@ public class SkiaContentPresenter : SkiaView
|
||||
Content?.OnPointerReleased(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Layout alignment options.
|
||||
/// </summary>
|
||||
public enum LayoutAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// Fill the available space.
|
||||
/// </summary>
|
||||
Fill,
|
||||
|
||||
/// <summary>
|
||||
/// Align to the start (left or top).
|
||||
/// </summary>
|
||||
Start,
|
||||
|
||||
/// <summary>
|
||||
/// Align to the center.
|
||||
/// </summary>
|
||||
Center,
|
||||
|
||||
/// <summary>
|
||||
/// Align to the end (right or bottom).
|
||||
/// </summary>
|
||||
End
|
||||
}
|
||||
|
||||
@@ -348,34 +348,3 @@ public class SkiaFlyoutPage : SkiaLayoutView
|
||||
IsPresented = !IsPresented;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines how the flyout behaves.
|
||||
/// </summary>
|
||||
public enum FlyoutLayoutBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Default behavior based on device/window size.
|
||||
/// </summary>
|
||||
Default,
|
||||
|
||||
/// <summary>
|
||||
/// Flyout slides over the detail content.
|
||||
/// </summary>
|
||||
Popover,
|
||||
|
||||
/// <summary>
|
||||
/// Flyout and detail are shown side by side.
|
||||
/// </summary>
|
||||
Split,
|
||||
|
||||
/// <summary>
|
||||
/// Flyout pushes the detail content.
|
||||
/// </summary>
|
||||
SplitOnLandscape,
|
||||
|
||||
/// <summary>
|
||||
/// Flyout is always shown in portrait, side by side in landscape.
|
||||
/// </summary>
|
||||
SplitOnPortrait
|
||||
}
|
||||
|
||||
23
Views/SkiaFrame.cs
Normal file
23
Views/SkiaFrame.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Frame control - a Border with shadow enabled by default.
|
||||
/// Mimics the MAUI Frame control appearance.
|
||||
/// </summary>
|
||||
public class SkiaFrame : SkiaBorder
|
||||
{
|
||||
public SkiaFrame()
|
||||
{
|
||||
HasShadow = true;
|
||||
CornerRadius = 4f;
|
||||
SetPadding(10f);
|
||||
BackgroundColor = SKColors.White;
|
||||
Stroke = SKColors.Transparent;
|
||||
StrokeThickness = 0f;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using SkiaSharp;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Svg.Skia;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
@@ -210,16 +215,89 @@ public class SkiaImageButton : SkiaView
|
||||
{
|
||||
_isLoading = true;
|
||||
Invalidate();
|
||||
Console.WriteLine("[SkiaImageButton] LoadFromFileAsync: " + filePath);
|
||||
|
||||
try
|
||||
{
|
||||
var searchPaths = new List<string>
|
||||
{
|
||||
filePath,
|
||||
Path.Combine(AppContext.BaseDirectory, filePath),
|
||||
Path.Combine(AppContext.BaseDirectory, "Resources", "Images", filePath),
|
||||
Path.Combine(AppContext.BaseDirectory, "Resources", filePath)
|
||||
};
|
||||
|
||||
// Also check for SVG version if PNG was requested
|
||||
if (filePath.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var svgPath = Path.ChangeExtension(filePath, ".svg");
|
||||
searchPaths.Add(svgPath);
|
||||
searchPaths.Add(Path.Combine(AppContext.BaseDirectory, svgPath));
|
||||
searchPaths.Add(Path.Combine(AppContext.BaseDirectory, "Resources", "Images", svgPath));
|
||||
searchPaths.Add(Path.Combine(AppContext.BaseDirectory, "Resources", svgPath));
|
||||
}
|
||||
|
||||
string? foundPath = null;
|
||||
foreach (var path in searchPaths)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
foundPath = path;
|
||||
Console.WriteLine("[SkiaImageButton] Found file at: " + path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundPath == null)
|
||||
{
|
||||
Console.WriteLine("[SkiaImageButton] File not found: " + filePath);
|
||||
Console.WriteLine("[SkiaImageButton] Searched paths: " + string.Join(", ", searchPaths));
|
||||
_isLoading = false;
|
||||
ImageLoadingError?.Invoke(this, new ImageLoadingErrorEventArgs(new FileNotFoundException(filePath)));
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
using var stream = File.OpenRead(filePath);
|
||||
var bitmap = SKBitmap.Decode(stream);
|
||||
if (bitmap != null)
|
||||
if (foundPath.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Bitmap = bitmap;
|
||||
using var svg = new SKSvg();
|
||||
svg.Load(foundPath);
|
||||
if (svg.Picture != null)
|
||||
{
|
||||
var cullRect = svg.Picture.CullRect;
|
||||
bool hasWidth = WidthRequest > 0;
|
||||
bool hasHeight = HeightRequest > 0;
|
||||
|
||||
float targetWidth = hasWidth
|
||||
? (float)(WidthRequest - PaddingLeft - PaddingRight)
|
||||
: cullRect.Width;
|
||||
float targetHeight = hasHeight
|
||||
? (float)(HeightRequest - PaddingTop - PaddingBottom)
|
||||
: cullRect.Height;
|
||||
|
||||
float scale = Math.Min(targetWidth / cullRect.Width, targetHeight / cullRect.Height);
|
||||
int width = Math.Max(1, (int)(cullRect.Width * scale));
|
||||
int height = Math.Max(1, (int)(cullRect.Height * scale));
|
||||
|
||||
var bitmap = new SKBitmap(width, height, false);
|
||||
using var canvas = new SKCanvas(bitmap);
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
canvas.Scale(scale);
|
||||
canvas.DrawPicture(svg.Picture);
|
||||
Bitmap = bitmap;
|
||||
Console.WriteLine($"[SkiaImageButton] Loaded SVG: {foundPath} ({width}x{height})");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using var stream = File.OpenRead(foundPath);
|
||||
var bitmap = SKBitmap.Decode(stream);
|
||||
if (bitmap != null)
|
||||
{
|
||||
Bitmap = bitmap;
|
||||
Console.WriteLine("[SkiaImageButton] Loaded image: " + foundPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -303,14 +303,3 @@ public class SkiaIndicatorView : SkiaView
|
||||
base.OnPointerPressed(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shape of indicator dots.
|
||||
/// </summary>
|
||||
public enum IndicatorShape
|
||||
{
|
||||
Circle,
|
||||
Square,
|
||||
RoundedSquare,
|
||||
Diamond
|
||||
}
|
||||
|
||||
@@ -262,337 +262,3 @@ public class SkiaMenuBar : SkiaView
|
||||
CloseFlyout();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a top-level menu bar item.
|
||||
/// </summary>
|
||||
public class MenuBarItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the display text.
|
||||
/// </summary>
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the menu items.
|
||||
/// </summary>
|
||||
public List<MenuItem> Items { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bounds (set during rendering).
|
||||
/// </summary>
|
||||
internal SKRect Bounds { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a menu item.
|
||||
/// </summary>
|
||||
public class MenuItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the display text.
|
||||
/// </summary>
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the keyboard shortcut text.
|
||||
/// </summary>
|
||||
public string? Shortcut { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this is a separator.
|
||||
/// </summary>
|
||||
public bool IsSeparator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this item is enabled.
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this item is checked.
|
||||
/// </summary>
|
||||
public bool IsChecked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon source.
|
||||
/// </summary>
|
||||
public string? IconSource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sub-menu items.
|
||||
/// </summary>
|
||||
public List<MenuItem> SubItems { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the item is clicked.
|
||||
/// </summary>
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
internal void OnClicked()
|
||||
{
|
||||
Clicked?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A dropdown menu flyout.
|
||||
/// </summary>
|
||||
public class SkiaMenuFlyout : SkiaView
|
||||
{
|
||||
private int _hoveredIndex = -1;
|
||||
private SKRect _bounds;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the menu items.
|
||||
/// </summary>
|
||||
public List<MenuItem> Items { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position.
|
||||
/// </summary>
|
||||
public SKPoint Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the background color.
|
||||
/// </summary>
|
||||
public SKColor BackgroundColor { get; set; } = SKColors.White;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text color.
|
||||
/// </summary>
|
||||
public SKColor TextColor { get; set; } = new SKColor(33, 33, 33);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the disabled text color.
|
||||
/// </summary>
|
||||
public SKColor DisabledTextColor { get; set; } = new SKColor(160, 160, 160);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the hover background color.
|
||||
/// </summary>
|
||||
public SKColor HoverBackgroundColor { get; set; } = new SKColor(230, 230, 230);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the separator color.
|
||||
/// </summary>
|
||||
public SKColor SeparatorColor { get; set; } = new SKColor(220, 220, 220);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the font size.
|
||||
/// </summary>
|
||||
public float FontSize { get; set; } = 13f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item height.
|
||||
/// </summary>
|
||||
public float ItemHeight { get; set; } = 28f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the separator height.
|
||||
/// </summary>
|
||||
public float SeparatorHeight { get; set; } = 9f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum width.
|
||||
/// </summary>
|
||||
public float MinWidth { get; set; } = 180f;
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when an item is clicked.
|
||||
/// </summary>
|
||||
public event EventHandler<MenuItemClickedEventArgs>? ItemClicked;
|
||||
|
||||
protected override void OnDraw(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
if (Items.Count == 0) return;
|
||||
|
||||
// Calculate bounds
|
||||
float width = MinWidth;
|
||||
float height = 0;
|
||||
|
||||
using var textPaint = new SKPaint
|
||||
{
|
||||
TextSize = FontSize,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
foreach (var item in Items)
|
||||
{
|
||||
if (item.IsSeparator)
|
||||
{
|
||||
height += SeparatorHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
height += ItemHeight;
|
||||
|
||||
var textBounds = new SKRect();
|
||||
textPaint.MeasureText(item.Text, ref textBounds);
|
||||
float itemWidth = textBounds.Width + 50; // Padding + icon space
|
||||
if (!string.IsNullOrEmpty(item.Shortcut))
|
||||
{
|
||||
textPaint.MeasureText(item.Shortcut, ref textBounds);
|
||||
itemWidth += textBounds.Width + 20;
|
||||
}
|
||||
width = Math.Max(width, itemWidth);
|
||||
}
|
||||
}
|
||||
|
||||
_bounds = new SKRect(Position.X, Position.Y, Position.X + width, Position.Y + height);
|
||||
|
||||
// Draw shadow
|
||||
using var shadowPaint = new SKPaint
|
||||
{
|
||||
ImageFilter = SKImageFilter.CreateDropShadow(0, 2, 8, 8, new SKColor(0, 0, 0, 40))
|
||||
};
|
||||
canvas.DrawRect(_bounds, shadowPaint);
|
||||
|
||||
// Draw background
|
||||
using var bgPaint = new SKPaint
|
||||
{
|
||||
Color = BackgroundColor,
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(_bounds, bgPaint);
|
||||
|
||||
// Draw border
|
||||
using var borderPaint = new SKPaint
|
||||
{
|
||||
Color = new SKColor(200, 200, 200),
|
||||
Style = SKPaintStyle.Stroke,
|
||||
StrokeWidth = 1
|
||||
};
|
||||
canvas.DrawRect(_bounds, borderPaint);
|
||||
|
||||
// Draw items
|
||||
float y = _bounds.Top;
|
||||
textPaint.Color = TextColor;
|
||||
|
||||
for (int i = 0; i < Items.Count; i++)
|
||||
{
|
||||
var item = Items[i];
|
||||
|
||||
if (item.IsSeparator)
|
||||
{
|
||||
float separatorY = y + SeparatorHeight / 2;
|
||||
using var sepPaint = new SKPaint { Color = SeparatorColor, StrokeWidth = 1 };
|
||||
canvas.DrawLine(_bounds.Left + 8, separatorY, _bounds.Right - 8, separatorY, sepPaint);
|
||||
y += SeparatorHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
var itemBounds = new SKRect(_bounds.Left, y, _bounds.Right, y + ItemHeight);
|
||||
|
||||
// Draw hover background
|
||||
if (i == _hoveredIndex && item.IsEnabled)
|
||||
{
|
||||
using var hoverPaint = new SKPaint { Color = HoverBackgroundColor, Style = SKPaintStyle.Fill };
|
||||
canvas.DrawRect(itemBounds, hoverPaint);
|
||||
}
|
||||
|
||||
// Draw check mark
|
||||
if (item.IsChecked)
|
||||
{
|
||||
using var checkPaint = new SKPaint
|
||||
{
|
||||
Color = item.IsEnabled ? TextColor : DisabledTextColor,
|
||||
TextSize = FontSize,
|
||||
IsAntialias = true
|
||||
};
|
||||
canvas.DrawText("✓", _bounds.Left + 8, y + ItemHeight / 2 + 5, checkPaint);
|
||||
}
|
||||
|
||||
// Draw text
|
||||
textPaint.Color = item.IsEnabled ? TextColor : DisabledTextColor;
|
||||
canvas.DrawText(item.Text, _bounds.Left + 28, y + ItemHeight / 2 + 5, textPaint);
|
||||
|
||||
// Draw shortcut
|
||||
if (!string.IsNullOrEmpty(item.Shortcut))
|
||||
{
|
||||
textPaint.Color = DisabledTextColor;
|
||||
var shortcutBounds = new SKRect();
|
||||
textPaint.MeasureText(item.Shortcut, ref shortcutBounds);
|
||||
canvas.DrawText(item.Shortcut, _bounds.Right - shortcutBounds.Width - 12, y + ItemHeight / 2 + 5, textPaint);
|
||||
}
|
||||
|
||||
// Draw submenu arrow
|
||||
if (item.SubItems.Count > 0)
|
||||
{
|
||||
canvas.DrawText("▸", _bounds.Right - 16, y + ItemHeight / 2 + 5, textPaint);
|
||||
}
|
||||
|
||||
y += ItemHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override SkiaView? HitTest(float x, float y)
|
||||
{
|
||||
if (_bounds.Contains(x, y))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
if (!_bounds.Contains(e.X, e.Y))
|
||||
{
|
||||
_hoveredIndex = -1;
|
||||
Invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
float y = _bounds.Top;
|
||||
int newHovered = -1;
|
||||
|
||||
for (int i = 0; i < Items.Count; i++)
|
||||
{
|
||||
var item = Items[i];
|
||||
float itemHeight = item.IsSeparator ? SeparatorHeight : ItemHeight;
|
||||
|
||||
if (e.Y >= y && e.Y < y + itemHeight && !item.IsSeparator)
|
||||
{
|
||||
newHovered = i;
|
||||
break;
|
||||
}
|
||||
|
||||
y += itemHeight;
|
||||
}
|
||||
|
||||
if (newHovered != _hoveredIndex)
|
||||
{
|
||||
_hoveredIndex = newHovered;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPointerPressed(PointerEventArgs e)
|
||||
{
|
||||
if (_hoveredIndex >= 0 && _hoveredIndex < Items.Count)
|
||||
{
|
||||
var item = Items[_hoveredIndex];
|
||||
if (item.IsEnabled && !item.IsSeparator)
|
||||
{
|
||||
item.OnClicked();
|
||||
ItemClicked?.Invoke(this, new MenuItemClickedEventArgs(item));
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for menu item clicked.
|
||||
/// </summary>
|
||||
public class MenuItemClickedEventArgs : EventArgs
|
||||
{
|
||||
public MenuItem Item { get; }
|
||||
|
||||
public MenuItemClickedEventArgs(MenuItem item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
}
|
||||
|
||||
225
Views/SkiaMenuFlyout.cs
Normal file
225
Views/SkiaMenuFlyout.cs
Normal file
@@ -0,0 +1,225 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class SkiaMenuFlyout : SkiaView
|
||||
{
|
||||
private int _hoveredIndex = -1;
|
||||
private SKRect _bounds;
|
||||
|
||||
public List<MenuItem> Items { get; set; } = new List<MenuItem>();
|
||||
|
||||
public SKPoint Position { get; set; }
|
||||
|
||||
public new SKColor BackgroundColor { get; set; } = SKColors.White;
|
||||
|
||||
public SKColor TextColor { get; set; } = new SKColor(33, 33, 33);
|
||||
|
||||
public SKColor DisabledTextColor { get; set; } = new SKColor(160, 160, 160);
|
||||
|
||||
public SKColor HoverBackgroundColor { get; set; } = new SKColor(230, 230, 230);
|
||||
|
||||
public SKColor SeparatorColor { get; set; } = new SKColor(220, 220, 220);
|
||||
|
||||
public float FontSize { get; set; } = 13f;
|
||||
|
||||
public float ItemHeight { get; set; } = 28f;
|
||||
|
||||
public float SeparatorHeight { get; set; } = 9f;
|
||||
|
||||
public float MinWidth { get; set; } = 180f;
|
||||
|
||||
public event EventHandler<MenuItemClickedEventArgs>? ItemClicked;
|
||||
|
||||
protected override void OnDraw(SKCanvas canvas, SKRect bounds)
|
||||
{
|
||||
if (Items.Count == 0)
|
||||
return;
|
||||
|
||||
float width = MinWidth;
|
||||
float height = 0f;
|
||||
|
||||
using var textPaint = new SKPaint
|
||||
{
|
||||
TextSize = FontSize,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
foreach (var item in Items)
|
||||
{
|
||||
if (item.IsSeparator)
|
||||
{
|
||||
height += SeparatorHeight;
|
||||
continue;
|
||||
}
|
||||
|
||||
height += ItemHeight;
|
||||
var textBounds = new SKRect();
|
||||
textPaint.MeasureText(item.Text, ref textBounds);
|
||||
float itemWidth = textBounds.Width + 50f;
|
||||
|
||||
if (!string.IsNullOrEmpty(item.Shortcut))
|
||||
{
|
||||
textPaint.MeasureText(item.Shortcut, ref textBounds);
|
||||
itemWidth += textBounds.Width + 20f;
|
||||
}
|
||||
|
||||
width = Math.Max(width, itemWidth);
|
||||
}
|
||||
|
||||
_bounds = new SKRect(Position.X, Position.Y, Position.X + width, Position.Y + height);
|
||||
|
||||
// Draw shadow
|
||||
using var shadowPaint = new SKPaint
|
||||
{
|
||||
ImageFilter = SKImageFilter.CreateDropShadow(0f, 2f, 8f, 8f, new SKColor(0, 0, 0, 40))
|
||||
};
|
||||
canvas.DrawRect(_bounds, shadowPaint);
|
||||
|
||||
// Draw background
|
||||
using var bgPaint = new SKPaint
|
||||
{
|
||||
Color = BackgroundColor,
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(_bounds, bgPaint);
|
||||
|
||||
// Draw border
|
||||
using var borderPaint = new SKPaint
|
||||
{
|
||||
Color = new SKColor(200, 200, 200),
|
||||
Style = SKPaintStyle.Stroke,
|
||||
StrokeWidth = 1f
|
||||
};
|
||||
canvas.DrawRect(_bounds, borderPaint);
|
||||
|
||||
// Draw items
|
||||
float y = _bounds.Top;
|
||||
textPaint.Color = TextColor;
|
||||
|
||||
for (int i = 0; i < Items.Count; i++)
|
||||
{
|
||||
var menuItem = Items[i];
|
||||
|
||||
if (menuItem.IsSeparator)
|
||||
{
|
||||
float separatorY = y + SeparatorHeight / 2f;
|
||||
using var sepPaint = new SKPaint
|
||||
{
|
||||
Color = SeparatorColor,
|
||||
StrokeWidth = 1f
|
||||
};
|
||||
canvas.DrawLine(_bounds.Left + 8f, separatorY, _bounds.Right - 8f, separatorY, sepPaint);
|
||||
y += SeparatorHeight;
|
||||
continue;
|
||||
}
|
||||
|
||||
var itemBounds = new SKRect(_bounds.Left, y, _bounds.Right, y + ItemHeight);
|
||||
|
||||
// Draw hover background
|
||||
if (i == _hoveredIndex && menuItem.IsEnabled)
|
||||
{
|
||||
using var hoverPaint = new SKPaint
|
||||
{
|
||||
Color = HoverBackgroundColor,
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
canvas.DrawRect(itemBounds, hoverPaint);
|
||||
}
|
||||
|
||||
// Draw check mark
|
||||
if (menuItem.IsChecked)
|
||||
{
|
||||
using var checkPaint = new SKPaint
|
||||
{
|
||||
Color = menuItem.IsEnabled ? TextColor : DisabledTextColor,
|
||||
TextSize = FontSize,
|
||||
IsAntialias = true
|
||||
};
|
||||
canvas.DrawText("\u2713", _bounds.Left + 8f, y + ItemHeight / 2f + 5f, checkPaint);
|
||||
}
|
||||
|
||||
// Draw text
|
||||
textPaint.Color = menuItem.IsEnabled ? TextColor : DisabledTextColor;
|
||||
canvas.DrawText(menuItem.Text, _bounds.Left + 28f, y + ItemHeight / 2f + 5f, textPaint);
|
||||
|
||||
// Draw shortcut
|
||||
if (!string.IsNullOrEmpty(menuItem.Shortcut))
|
||||
{
|
||||
textPaint.Color = DisabledTextColor;
|
||||
var shortcutBounds = new SKRect();
|
||||
textPaint.MeasureText(menuItem.Shortcut, ref shortcutBounds);
|
||||
canvas.DrawText(menuItem.Shortcut, _bounds.Right - shortcutBounds.Width - 12f, y + ItemHeight / 2f + 5f, textPaint);
|
||||
}
|
||||
|
||||
// Draw submenu arrow
|
||||
if (menuItem.SubItems.Count > 0)
|
||||
{
|
||||
canvas.DrawText("\u25B8", _bounds.Right - 16f, y + ItemHeight / 2f + 5f, textPaint);
|
||||
}
|
||||
|
||||
y += ItemHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public override SkiaView? HitTest(float x, float y)
|
||||
{
|
||||
if (_bounds.Contains(x, y))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
if (!_bounds.Contains(e.X, e.Y))
|
||||
{
|
||||
_hoveredIndex = -1;
|
||||
Invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
float y = _bounds.Top;
|
||||
int newHovered = -1;
|
||||
|
||||
for (int i = 0; i < Items.Count; i++)
|
||||
{
|
||||
var menuItem = Items[i];
|
||||
float itemHeight = menuItem.IsSeparator ? SeparatorHeight : ItemHeight;
|
||||
|
||||
if (e.Y >= y && e.Y < y + itemHeight && !menuItem.IsSeparator)
|
||||
{
|
||||
newHovered = i;
|
||||
break;
|
||||
}
|
||||
|
||||
y += itemHeight;
|
||||
}
|
||||
|
||||
if (newHovered != _hoveredIndex)
|
||||
{
|
||||
_hoveredIndex = newHovered;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPointerPressed(PointerEventArgs e)
|
||||
{
|
||||
if (_hoveredIndex >= 0 && _hoveredIndex < Items.Count)
|
||||
{
|
||||
var menuItem = Items[_hoveredIndex];
|
||||
if (menuItem.IsEnabled && !menuItem.IsSeparator)
|
||||
{
|
||||
menuItem.OnClicked();
|
||||
ItemClicked?.Invoke(this, new MenuItemClickedEventArgs(menuItem));
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Maui.Platform.Linux;
|
||||
using SkiaSharp;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
@@ -89,6 +93,12 @@ public class SkiaNavigationPage : SkiaView
|
||||
{
|
||||
if (_isAnimating) return;
|
||||
|
||||
// Disable animation in GTK mode
|
||||
if (LinuxApplication.IsGtkMode)
|
||||
{
|
||||
animated = false;
|
||||
}
|
||||
|
||||
if (_currentPage != null)
|
||||
{
|
||||
_currentPage.OnDisappearing();
|
||||
@@ -108,9 +118,12 @@ public class SkiaNavigationPage : SkiaView
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("[SkiaNavigationPage] Push (no animation): setting _currentPage to " + page.Title);
|
||||
_currentPage = page;
|
||||
_currentPage.OnAppearing();
|
||||
Console.WriteLine("[SkiaNavigationPage] Push: calling Invalidate");
|
||||
Invalidate();
|
||||
Console.WriteLine("[SkiaNavigationPage] Push: Invalidate called, _currentPage is now " + _currentPage?.Title);
|
||||
}
|
||||
|
||||
Pushed?.Invoke(this, new NavigationEventArgs(page));
|
||||
@@ -120,6 +133,12 @@ public class SkiaNavigationPage : SkiaView
|
||||
{
|
||||
if (_isAnimating || _navigationStack.Count == 0) return null;
|
||||
|
||||
// Disable animation in GTK mode
|
||||
if (LinuxApplication.IsGtkMode)
|
||||
{
|
||||
animated = false;
|
||||
}
|
||||
|
||||
var poppedPage = _currentPage;
|
||||
poppedPage?.OnDisappearing();
|
||||
|
||||
@@ -302,6 +321,7 @@ public class SkiaNavigationPage : SkiaView
|
||||
else if (_currentPage != null)
|
||||
{
|
||||
// Draw current page normally
|
||||
Console.WriteLine("[SkiaNavigationPage] OnDraw: drawing _currentPage=" + _currentPage.Title);
|
||||
_currentPage.Bounds = bounds;
|
||||
_currentPage.Draw(canvas);
|
||||
|
||||
@@ -436,16 +456,3 @@ public class SkiaNavigationPage : SkiaView
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for navigation events.
|
||||
/// </summary>
|
||||
public class NavigationEventArgs : EventArgs
|
||||
{
|
||||
public SkiaPage Page { get; }
|
||||
|
||||
public NavigationEventArgs(SkiaPage page)
|
||||
{
|
||||
Page = page;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,46 +13,46 @@ public class SkiaRadioButton : SkiaView
|
||||
#region BindableProperties
|
||||
|
||||
public static readonly BindableProperty IsCheckedProperty =
|
||||
BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(SkiaRadioButton), false, BindingMode.TwoWay,
|
||||
BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(SkiaRadioButton), false, BindingMode.OneWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).OnIsCheckedChanged());
|
||||
|
||||
public static readonly BindableProperty ContentProperty =
|
||||
BindableProperty.Create(nameof(Content), typeof(string), typeof(SkiaRadioButton), "",
|
||||
BindableProperty.Create(nameof(Content), typeof(string), typeof(SkiaRadioButton), "", BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).InvalidateMeasure());
|
||||
|
||||
public static readonly BindableProperty ValueProperty =
|
||||
BindableProperty.Create(nameof(Value), typeof(object), typeof(SkiaRadioButton), null);
|
||||
BindableProperty.Create(nameof(Value), typeof(object), typeof(SkiaRadioButton), null, BindingMode.TwoWay);
|
||||
|
||||
public static readonly BindableProperty GroupNameProperty =
|
||||
BindableProperty.Create(nameof(GroupName), typeof(string), typeof(SkiaRadioButton), null,
|
||||
BindableProperty.Create(nameof(GroupName), typeof(string), typeof(SkiaRadioButton), null, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).OnGroupNameChanged((string?)o, (string?)n));
|
||||
|
||||
public static readonly BindableProperty RadioColorProperty =
|
||||
BindableProperty.Create(nameof(RadioColor), typeof(SKColor), typeof(SkiaRadioButton), new SKColor(0x21, 0x96, 0xF3),
|
||||
BindableProperty.Create(nameof(RadioColor), typeof(SKColor), typeof(SkiaRadioButton), new SKColor(0x21, 0x96, 0xF3), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty UncheckedColorProperty =
|
||||
BindableProperty.Create(nameof(UncheckedColor), typeof(SKColor), typeof(SkiaRadioButton), new SKColor(0x75, 0x75, 0x75),
|
||||
BindableProperty.Create(nameof(UncheckedColor), typeof(SKColor), typeof(SkiaRadioButton), new SKColor(0x75, 0x75, 0x75), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty TextColorProperty =
|
||||
BindableProperty.Create(nameof(TextColor), typeof(SKColor), typeof(SkiaRadioButton), SKColors.Black,
|
||||
BindableProperty.Create(nameof(TextColor), typeof(SKColor), typeof(SkiaRadioButton), SKColors.Black, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty DisabledColorProperty =
|
||||
BindableProperty.Create(nameof(DisabledColor), typeof(SKColor), typeof(SkiaRadioButton), new SKColor(0xBD, 0xBD, 0xBD),
|
||||
BindableProperty.Create(nameof(DisabledColor), typeof(SKColor), typeof(SkiaRadioButton), new SKColor(0xBD, 0xBD, 0xBD), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty FontSizeProperty =
|
||||
BindableProperty.Create(nameof(FontSize), typeof(float), typeof(SkiaRadioButton), 14f,
|
||||
BindableProperty.Create(nameof(FontSize), typeof(float), typeof(SkiaRadioButton), 14f, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).InvalidateMeasure());
|
||||
|
||||
public static readonly BindableProperty RadioSizeProperty =
|
||||
BindableProperty.Create(nameof(RadioSize), typeof(float), typeof(SkiaRadioButton), 20f,
|
||||
BindableProperty.Create(nameof(RadioSize), typeof(float), typeof(SkiaRadioButton), 20f, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).InvalidateMeasure());
|
||||
|
||||
public static readonly BindableProperty SpacingProperty =
|
||||
BindableProperty.Create(nameof(Spacing), typeof(float), typeof(SkiaRadioButton), 8f,
|
||||
BindableProperty.Create(nameof(Spacing), typeof(float), typeof(SkiaRadioButton), 8f, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaRadioButton)b).InvalidateMeasure());
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
@@ -86,6 +88,16 @@ public class SkiaRefreshView : SkiaLayoutView
|
||||
/// </summary>
|
||||
public SKColor RefreshBackgroundColor { get; set; } = SKColors.White;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the command to execute when refresh is triggered.
|
||||
/// </summary>
|
||||
public ICommand? Command { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the command parameter.
|
||||
/// </summary>
|
||||
public object? CommandParameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when refresh is triggered.
|
||||
/// </summary>
|
||||
@@ -266,6 +278,7 @@ public class SkiaRefreshView : SkiaLayoutView
|
||||
_pullDistance = _refreshThreshold;
|
||||
_lastSpinnerUpdate = DateTime.UtcNow;
|
||||
Refreshing?.Invoke(this, EventArgs.Empty);
|
||||
Command?.Execute(CommandParameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
14
Views/SkiaSelectionMode.cs
Normal file
14
Views/SkiaSelectionMode.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Selection mode for collection views.
|
||||
/// </summary>
|
||||
public enum SkiaSelectionMode
|
||||
{
|
||||
None,
|
||||
Single,
|
||||
Multiple
|
||||
}
|
||||
@@ -13,50 +13,50 @@ public class SkiaStepper : SkiaView
|
||||
#region BindableProperties
|
||||
|
||||
public static readonly BindableProperty ValueProperty =
|
||||
BindableProperty.Create(nameof(Value), typeof(double), typeof(SkiaStepper), 0.0, BindingMode.TwoWay,
|
||||
BindableProperty.Create(nameof(Value), typeof(double), typeof(SkiaStepper), 0.0, BindingMode.OneWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).OnValuePropertyChanged((double)o, (double)n));
|
||||
|
||||
public static readonly BindableProperty MinimumProperty =
|
||||
BindableProperty.Create(nameof(Minimum), typeof(double), typeof(SkiaStepper), 0.0,
|
||||
BindableProperty.Create(nameof(Minimum), typeof(double), typeof(SkiaStepper), 0.0, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).OnRangeChanged());
|
||||
|
||||
public static readonly BindableProperty MaximumProperty =
|
||||
BindableProperty.Create(nameof(Maximum), typeof(double), typeof(SkiaStepper), 100.0,
|
||||
BindableProperty.Create(nameof(Maximum), typeof(double), typeof(SkiaStepper), 100.0, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).OnRangeChanged());
|
||||
|
||||
public static readonly BindableProperty IncrementProperty =
|
||||
BindableProperty.Create(nameof(Increment), typeof(double), typeof(SkiaStepper), 1.0);
|
||||
BindableProperty.Create(nameof(Increment), typeof(double), typeof(SkiaStepper), 1.0, BindingMode.TwoWay);
|
||||
|
||||
public static readonly BindableProperty ButtonBackgroundColorProperty =
|
||||
BindableProperty.Create(nameof(ButtonBackgroundColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xE0, 0xE0, 0xE0),
|
||||
BindableProperty.Create(nameof(ButtonBackgroundColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xE0, 0xE0, 0xE0), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty ButtonPressedColorProperty =
|
||||
BindableProperty.Create(nameof(ButtonPressedColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xBD, 0xBD, 0xBD),
|
||||
BindableProperty.Create(nameof(ButtonPressedColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xBD, 0xBD, 0xBD), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty ButtonDisabledColorProperty =
|
||||
BindableProperty.Create(nameof(ButtonDisabledColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xF5, 0xF5, 0xF5),
|
||||
BindableProperty.Create(nameof(ButtonDisabledColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xF5, 0xF5, 0xF5), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty BorderColorProperty =
|
||||
BindableProperty.Create(nameof(BorderColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xBD, 0xBD, 0xBD),
|
||||
BindableProperty.Create(nameof(BorderColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xBD, 0xBD, 0xBD), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty SymbolColorProperty =
|
||||
BindableProperty.Create(nameof(SymbolColor), typeof(SKColor), typeof(SkiaStepper), SKColors.Black,
|
||||
BindableProperty.Create(nameof(SymbolColor), typeof(SKColor), typeof(SkiaStepper), SKColors.Black, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty SymbolDisabledColorProperty =
|
||||
BindableProperty.Create(nameof(SymbolDisabledColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xBD, 0xBD, 0xBD),
|
||||
BindableProperty.Create(nameof(SymbolDisabledColor), typeof(SKColor), typeof(SkiaStepper), new SKColor(0xBD, 0xBD, 0xBD), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty CornerRadiusProperty =
|
||||
BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(SkiaStepper), 4f,
|
||||
BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(SkiaStepper), 4f, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty ButtonWidthProperty =
|
||||
BindableProperty.Create(nameof(ButtonWidth), typeof(float), typeof(SkiaStepper), 40f,
|
||||
BindableProperty.Create(nameof(ButtonWidth), typeof(float), typeof(SkiaStepper), 40f, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaStepper)b).InvalidateMeasure());
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -382,88 +382,3 @@ public class SkiaSwipeView : SkiaLayoutView
|
||||
base.OnPointerReleased(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a swipe action item.
|
||||
/// </summary>
|
||||
public class SwipeItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the text.
|
||||
/// </summary>
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon source.
|
||||
/// </summary>
|
||||
public string? IconSource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the background color.
|
||||
/// </summary>
|
||||
public SKColor BackgroundColor { get; set; } = new SKColor(33, 150, 243);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text color.
|
||||
/// </summary>
|
||||
public SKColor TextColor { get; set; } = SKColors.White;
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the item is invoked.
|
||||
/// </summary>
|
||||
public event EventHandler? Invoked;
|
||||
|
||||
internal void OnInvoked()
|
||||
{
|
||||
Invoked?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swipe direction.
|
||||
/// </summary>
|
||||
public enum SwipeDirection
|
||||
{
|
||||
None,
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swipe mode.
|
||||
/// </summary>
|
||||
public enum SwipeMode
|
||||
{
|
||||
Reveal,
|
||||
Execute
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for swipe started.
|
||||
/// </summary>
|
||||
public class SwipeStartedEventArgs : EventArgs
|
||||
{
|
||||
public SwipeDirection Direction { get; }
|
||||
|
||||
public SwipeStartedEventArgs(SwipeDirection direction)
|
||||
{
|
||||
Direction = direction;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for swipe ended.
|
||||
/// </summary>
|
||||
public class SwipeEndedEventArgs : EventArgs
|
||||
{
|
||||
public SwipeDirection Direction { get; }
|
||||
public bool IsOpen { get; }
|
||||
|
||||
public SwipeEndedEventArgs(SwipeDirection direction, bool isOpen)
|
||||
{
|
||||
Direction = direction;
|
||||
IsOpen = isOpen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,29 +394,3 @@ public class SkiaTabbedPage : SkiaLayoutView
|
||||
base.OnPointerPressed(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a tab item with title, icon, and content.
|
||||
/// </summary>
|
||||
public class TabItem
|
||||
{
|
||||
/// <summary>
|
||||
/// The title displayed in the tab.
|
||||
/// </summary>
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Optional icon path for the tab.
|
||||
/// </summary>
|
||||
public string? IconPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The content view displayed when this tab is selected.
|
||||
/// </summary>
|
||||
public SkiaView Content { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Optional badge text to display on the tab.
|
||||
/// </summary>
|
||||
public string? Badge { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Controls.Shapes;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
@@ -14,43 +14,43 @@ public class SkiaTimePicker : SkiaView
|
||||
#region BindableProperties
|
||||
|
||||
public static readonly BindableProperty TimeProperty =
|
||||
BindableProperty.Create(nameof(Time), typeof(TimeSpan), typeof(SkiaTimePicker), DateTime.Now.TimeOfDay, BindingMode.TwoWay,
|
||||
BindableProperty.Create(nameof(Time), typeof(TimeSpan), typeof(SkiaTimePicker), DateTime.Now.TimeOfDay, BindingMode.OneWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).OnTimePropertyChanged());
|
||||
|
||||
public static readonly BindableProperty FormatProperty =
|
||||
BindableProperty.Create(nameof(Format), typeof(string), typeof(SkiaTimePicker), "t",
|
||||
BindableProperty.Create(nameof(Format), typeof(string), typeof(SkiaTimePicker), "t", BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty TextColorProperty =
|
||||
BindableProperty.Create(nameof(TextColor), typeof(SKColor), typeof(SkiaTimePicker), SKColors.Black,
|
||||
BindableProperty.Create(nameof(TextColor), typeof(SKColor), typeof(SkiaTimePicker), SKColors.Black, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty BorderColorProperty =
|
||||
BindableProperty.Create(nameof(BorderColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0xBD, 0xBD, 0xBD),
|
||||
BindableProperty.Create(nameof(BorderColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0xBD, 0xBD, 0xBD), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty ClockBackgroundColorProperty =
|
||||
BindableProperty.Create(nameof(ClockBackgroundColor), typeof(SKColor), typeof(SkiaTimePicker), SKColors.White,
|
||||
BindableProperty.Create(nameof(ClockBackgroundColor), typeof(SKColor), typeof(SkiaTimePicker), SKColors.White, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty ClockFaceColorProperty =
|
||||
BindableProperty.Create(nameof(ClockFaceColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0xF5, 0xF5, 0xF5),
|
||||
BindableProperty.Create(nameof(ClockFaceColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0xF5, 0xF5, 0xF5), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty SelectedColorProperty =
|
||||
BindableProperty.Create(nameof(SelectedColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0x21, 0x96, 0xF3),
|
||||
BindableProperty.Create(nameof(SelectedColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0x21, 0x96, 0xF3), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty HeaderColorProperty =
|
||||
BindableProperty.Create(nameof(HeaderColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0x21, 0x96, 0xF3),
|
||||
BindableProperty.Create(nameof(HeaderColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0x21, 0x96, 0xF3), BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
|
||||
|
||||
public static readonly BindableProperty FontSizeProperty =
|
||||
BindableProperty.Create(nameof(FontSize), typeof(float), typeof(SkiaTimePicker), 14f,
|
||||
BindableProperty.Create(nameof(FontSize), typeof(float), typeof(SkiaTimePicker), 14f, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).InvalidateMeasure());
|
||||
|
||||
public static readonly BindableProperty CornerRadiusProperty =
|
||||
BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(SkiaTimePicker), 4f,
|
||||
BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(SkiaTimePicker), 4f, BindingMode.TwoWay,
|
||||
propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
|
||||
|
||||
#endregion
|
||||
|
||||
13
Views/SkiaVisualState.cs
Normal file
13
Views/SkiaVisualState.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class SkiaVisualState
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
public List<SkiaVisualStateSetter> Setters { get; } = new List<SkiaVisualStateSetter>();
|
||||
}
|
||||
15
Views/SkiaVisualStateGroup.cs
Normal file
15
Views/SkiaVisualStateGroup.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class SkiaVisualStateGroup
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
public List<SkiaVisualState> States { get; } = new List<SkiaVisualState>();
|
||||
|
||||
public SkiaVisualState? CurrentState { get; set; }
|
||||
}
|
||||
10
Views/SkiaVisualStateGroupList.cs
Normal file
10
Views/SkiaVisualStateGroupList.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class SkiaVisualStateGroupList : List<SkiaVisualStateGroup>
|
||||
{
|
||||
}
|
||||
@@ -123,94 +123,3 @@ public static class SkiaVisualStateManager
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A list of visual state groups.
|
||||
/// </summary>
|
||||
public class SkiaVisualStateGroupList : List<SkiaVisualStateGroup>
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A group of mutually exclusive visual states.
|
||||
/// </summary>
|
||||
public class SkiaVisualStateGroup
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this group.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of states in this group.
|
||||
/// </summary>
|
||||
public List<SkiaVisualState> States { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the currently active state.
|
||||
/// </summary>
|
||||
public SkiaVisualState? CurrentState { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single visual state with its setters.
|
||||
/// </summary>
|
||||
public class SkiaVisualState
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this state.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of setters for this state.
|
||||
/// </summary>
|
||||
public List<SkiaVisualStateSetter> Setters { get; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a property value when a visual state is active.
|
||||
/// </summary>
|
||||
public class SkiaVisualStateSetter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the property to set.
|
||||
/// </summary>
|
||||
public BindableProperty? Property { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to set.
|
||||
/// </summary>
|
||||
public object? Value { get; set; }
|
||||
|
||||
// Store original value for unapply
|
||||
private object? _originalValue;
|
||||
private bool _hasOriginalValue;
|
||||
|
||||
/// <summary>
|
||||
/// Applies this setter to the target view.
|
||||
/// </summary>
|
||||
public void Apply(SkiaView view)
|
||||
{
|
||||
if (Property == null) return;
|
||||
|
||||
// Store original value if not already stored
|
||||
if (!_hasOriginalValue)
|
||||
{
|
||||
_originalValue = view.GetValue(Property);
|
||||
_hasOriginalValue = true;
|
||||
}
|
||||
|
||||
view.SetValue(Property, Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unapplies this setter, restoring the original value.
|
||||
/// </summary>
|
||||
public void Unapply(SkiaView view)
|
||||
{
|
||||
if (Property == null || !_hasOriginalValue) return;
|
||||
|
||||
view.SetValue(Property, _originalValue);
|
||||
}
|
||||
}
|
||||
|
||||
37
Views/SkiaVisualStateSetter.cs
Normal file
37
Views/SkiaVisualStateSetter.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class SkiaVisualStateSetter
|
||||
{
|
||||
private object? _originalValue;
|
||||
private bool _hasOriginalValue;
|
||||
|
||||
public BindableProperty? Property { get; set; }
|
||||
|
||||
public object? Value { get; set; }
|
||||
|
||||
public void Apply(SkiaView view)
|
||||
{
|
||||
if (Property != null)
|
||||
{
|
||||
if (!_hasOriginalValue)
|
||||
{
|
||||
_originalValue = view.GetValue(Property);
|
||||
_hasOriginalValue = true;
|
||||
}
|
||||
view.SetValue(Property, Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Unapply(SkiaView view)
|
||||
{
|
||||
if (Property != null && _hasOriginalValue)
|
||||
{
|
||||
view.SetValue(Property, _originalValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Views/SwipeDirection.cs
Normal file
13
Views/SwipeDirection.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public enum SwipeDirection
|
||||
{
|
||||
None,
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down
|
||||
}
|
||||
19
Views/SwipeEndedEventArgs.cs
Normal file
19
Views/SwipeEndedEventArgs.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class SwipeEndedEventArgs : EventArgs
|
||||
{
|
||||
public SwipeDirection Direction { get; }
|
||||
|
||||
public bool IsOpen { get; }
|
||||
|
||||
public SwipeEndedEventArgs(SwipeDirection direction, bool isOpen)
|
||||
{
|
||||
Direction = direction;
|
||||
IsOpen = isOpen;
|
||||
}
|
||||
}
|
||||
25
Views/SwipeItem.cs
Normal file
25
Views/SwipeItem.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class SwipeItem
|
||||
{
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
public string? IconSource { get; set; }
|
||||
|
||||
public SKColor BackgroundColor { get; set; } = new SKColor(33, 150, 243);
|
||||
|
||||
public SKColor TextColor { get; set; } = SKColors.White;
|
||||
|
||||
public event EventHandler? Invoked;
|
||||
|
||||
internal void OnInvoked()
|
||||
{
|
||||
Invoked?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
10
Views/SwipeMode.cs
Normal file
10
Views/SwipeMode.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public enum SwipeMode
|
||||
{
|
||||
Reveal,
|
||||
Execute
|
||||
}
|
||||
16
Views/SwipeStartedEventArgs.cs
Normal file
16
Views/SwipeStartedEventArgs.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class SwipeStartedEventArgs : EventArgs
|
||||
{
|
||||
public SwipeDirection Direction { get; }
|
||||
|
||||
public SwipeStartedEventArgs(SwipeDirection direction)
|
||||
{
|
||||
Direction = direction;
|
||||
}
|
||||
}
|
||||
15
Views/TabItem.cs
Normal file
15
Views/TabItem.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
public class TabItem
|
||||
{
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
public string? IconPath { get; set; }
|
||||
|
||||
public SkiaView Content { get; set; } = null!;
|
||||
|
||||
public string? Badge { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user