From 0c183e832c84d92baca08e3823c33e4d6fb2591b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Fri, 1 Sep 2023 23:17:09 -0600 Subject: [PATCH 01/78] add missing series --- docs/cartesianChart/overview.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/docs/cartesianChart/overview.md b/docs/cartesianChart/overview.md index 16dd28eb5..c064f93c0 100644 --- a/docs/cartesianChart/overview.md +++ b/docs/cartesianChart/overview.md @@ -119,7 +119,7 @@ any image bellow is a link to an article explaining more about them.
-series +series
Step line series
@@ -154,11 +154,32 @@ any image bellow is a link to an article explaining more about them.
-series +series
Stacked step line series
+ +
+series +
Box series
+
+
+ + +
+series +
Error series
+
+
+ + +
+series +
Bubble series
+
+
+ ## Axes A `CartesianChart` has 2 axes, the `YAxis` and the `XAxis` properties, an [IAxis]({{ website_url }}/api/{{ version}}/LiveChartsCore.Kernel.Sketches.ICartesianAxis) From f499b532406d5a6241b1dbd13b5387cce42454ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 2 Sep 2023 09:47:12 -0600 Subject: [PATCH 02/78] ffixes #1209 --- samples/WinFormsSample/General/Scrollable/View.cs | 12 +++++++----- .../LiveChartsCore.SkiaSharp.WinForms/Chart.cs | 11 ++++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/samples/WinFormsSample/General/Scrollable/View.cs b/samples/WinFormsSample/General/Scrollable/View.cs index 9464c9e41..4efab21ed 100644 --- a/samples/WinFormsSample/General/Scrollable/View.cs +++ b/samples/WinFormsSample/General/Scrollable/View.cs @@ -57,8 +57,10 @@ public View() Dock = DockStyle.Fill }; + _scrollBarChart = cartesianChart2; + cartesianChart2.MouseDown += CartesianChart2_MouseDown; - cartesianChart2.MouseMove += CartesianChart2_MouseMove; + cartesianChart2.GetDrawnControl().MouseMove += CartesianChart2_MouseMove; cartesianChart2.MouseUp += CartesianChart2_MouseUp; var splitContainer = new SplitContainer @@ -88,12 +90,12 @@ private void OnChart_Updated(IChartView chart) thumb.Xj = x.MaxLimit; } - private void CartesianChart2_MouseDown(object sender, MouseEventArgs e) + private void CartesianChart2_MouseDown(object? sender, MouseEventArgs e) { _isDown = true; } - private void CartesianChart2_MouseMove(object sender, MouseEventArgs e) + private void CartesianChart2_MouseMove(object? sender, MouseEventArgs e) { if (!_isDown) return; @@ -114,8 +116,8 @@ private void CartesianChart2_MouseMove(object sender, MouseEventArgs e) vm.ScrollableAxes[0].MaxLimit = thumb.Xj; } - private void CartesianChart2_MouseUp(object sender, MouseEventArgs e) + private void CartesianChart2_MouseUp(object? sender, MouseEventArgs e) { - _isDown = true; + _isDown = false; } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs index 13b011c20..68a4f19b9 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs @@ -118,7 +118,7 @@ protected Chart(IChartTooltip? tooltip, IChartLegend> VisualElements /// public abstract IEnumerable> GetVisualsAt(LvcPoint point); + /// + /// Gets the drawn control. + /// + /// + public Control GetDrawnControl() + { + return Controls[0].Controls[0]; + } + internal Point GetCanvasPosition() { return motionCanvas.Location; From 57fb431e143ad102fa73a362c5316ce2717209f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 2 Sep 2023 10:59:19 -0600 Subject: [PATCH 03/78] maui zoom by section on windows --- src/LiveChartsCore/CartesianChart.cs | 4 ++-- .../CartesianChart.xaml.cs | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/LiveChartsCore/CartesianChart.cs b/src/LiveChartsCore/CartesianChart.cs index 230349004..ffc8caebe 100644 --- a/src/LiveChartsCore/CartesianChart.cs +++ b/src/LiveChartsCore/CartesianChart.cs @@ -40,8 +40,8 @@ namespace LiveChartsCore; public class CartesianChart : Chart where TDrawingContext : DrawingContext { + internal readonly ISizedGeometry _zoomingSection; private readonly ICartesianChartView _chartView; - private readonly ISizedGeometry _zoomingSection; private int _nextSeries = 0; private double _zoomingSpeed = 0; private ZoomAndPanMode _zoomMode; @@ -62,7 +62,7 @@ public CartesianChart( Action defaultPlatformConfig, MotionCanvas canvas, ISizedGeometry? zoomingSection) - : base(canvas, defaultPlatformConfig, view) + : base(canvas, defaultPlatformConfig, view) { _chartView = view; _zoomingSection = zoomingSection ?? throw new Exception($"{nameof(zoomingSection)} is required."); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs index 495561a2c..bdceb8efd 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs @@ -753,15 +753,6 @@ void IChartView.InvokeOnUIThread(Action action) protected void InitializeCore() { var zoomingSection = new RectangleGeometry(); - var zoomingSectionPaint = new SolidColorPaint - { - IsFill = true, - Color = new SkiaSharp.SKColor(33, 150, 243, 50), - ZIndex = int.MaxValue - }; - zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); - canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); - _core = new CartesianChart( this, config => config.UseDefaults(), canvas.CanvasCore, zoomingSection); _core.Update(); @@ -899,6 +890,7 @@ private void OnTapped(object? sender, TappedEventArgs e) #endif #if WINDOWS + private bool _isZoomingSectionAttached = false; private void OnHandlerChanged(object? sender, EventArgs e) { @@ -932,6 +924,20 @@ private void OnPointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRout // https://github.com/dotnet/maui/issues/16202 //if (Keyboard.Modifiers > 0) return; + if (!_isZoomingSectionAttached) + { + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + var zoomingSection = ((CartesianChart)CoreChart)._zoomingSection; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + _isZoomingSectionAttached = true; + } + var p = e.GetCurrentPoint(sender as Microsoft.Maui.Platform.ContentPanel); _core?.InvokePointerDown( new LvcPoint((float)p.Position.X, (float)p.Position.Y), p.Properties.IsRightButtonPressed); From bae7e25535a2e54353548daaa94342ed3c39125f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 13:24:38 -0600 Subject: [PATCH 04/78] remove old uno sln --- LiveCharts.Uno.sln | 203 --------------------------------------------- 1 file changed, 203 deletions(-) delete mode 100644 LiveCharts.Uno.sln diff --git a/LiveCharts.Uno.sln b/LiveCharts.Uno.sln deleted file mode 100644 index 472aecb50..000000000 --- a/LiveCharts.Uno.sln +++ /dev/null @@ -1,203 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.6.33829.357 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore", "src\LiveChartsCore\LiveChartsCore.csproj", "{1D9A28EC-F444-4EA4-9EC9-E416897271AE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView", "src\skiasharp\LiveChartsCore.SkiaSharp\LiveChartsCore.SkiaSharpView.csproj", "{7B22725F-9F03-4D60-9B58-DCA36D2820AB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "src\skiasharp\LiveChartsCore.SkiaSharpView.Uno.WinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{6FAD289A-7297-4CBD-903C-E632AFC5900C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{30634DDE-9E2E-47F7-AFD3-F00F175CDF17}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Mobile", "samples\UnoPlatformSample\UnoPlatformSample.Mobile\UnoPlatformSample.Mobile.csproj", "{FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Skia.Gtk", "samples\UnoPlatformSample\UnoPlatformSample.Skia.Gtk\UnoPlatformSample.Skia.Gtk.csproj", "{739C38F2-4D2B-4ADF-8980-BC28F18876B3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Windows", "samples\UnoPlatformSample\UnoPlatformSample.Windows\UnoPlatformSample.Windows.csproj", "{66F715C7-7009-4957-B249-C4A3B03F02C2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample", "samples\UnoPlatformSample\UnoPlatformSample\UnoPlatformSample.csproj", "{1567153D-8F2C-4766-98C9-54166088B6FE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Wasm", "samples\UnoPlatformSample\UnoPlatformSample.Wasm\UnoPlatformSample.Wasm.csproj", "{59D2794E-1B4E-4AC6-89C2-F2142755EE27}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewModelsSamples", "samples\ViewModelsSamples\ViewModelsSamples.csproj", "{55A23CDB-01A5-49A4-8EC9-6A6B8E654667}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|arm64 = Debug|arm64 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|arm64 = Release|arm64 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Debug|arm64.ActiveCfg = Debug|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Debug|arm64.Build.0 = Debug|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Debug|x64.ActiveCfg = Debug|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Debug|x64.Build.0 = Debug|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Debug|x86.ActiveCfg = Debug|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Debug|x86.Build.0 = Debug|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Release|Any CPU.Build.0 = Release|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Release|arm64.ActiveCfg = Release|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Release|arm64.Build.0 = Release|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Release|x64.ActiveCfg = Release|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Release|x64.Build.0 = Release|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Release|x86.ActiveCfg = Release|Any CPU - {1D9A28EC-F444-4EA4-9EC9-E416897271AE}.Release|x86.Build.0 = Release|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Debug|arm64.ActiveCfg = Debug|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Debug|arm64.Build.0 = Debug|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Debug|x64.ActiveCfg = Debug|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Debug|x64.Build.0 = Debug|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Debug|x86.ActiveCfg = Debug|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Debug|x86.Build.0 = Debug|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Release|Any CPU.Build.0 = Release|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Release|arm64.ActiveCfg = Release|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Release|arm64.Build.0 = Release|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Release|x64.ActiveCfg = Release|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Release|x64.Build.0 = Release|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Release|x86.ActiveCfg = Release|Any CPU - {7B22725F-9F03-4D60-9B58-DCA36D2820AB}.Release|x86.Build.0 = Release|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Debug|arm64.ActiveCfg = Debug|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Debug|arm64.Build.0 = Debug|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Debug|x64.ActiveCfg = Debug|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Debug|x64.Build.0 = Debug|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Debug|x86.ActiveCfg = Debug|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Debug|x86.Build.0 = Debug|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Release|Any CPU.Build.0 = Release|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Release|arm64.ActiveCfg = Release|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Release|arm64.Build.0 = Release|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Release|x64.ActiveCfg = Release|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Release|x64.Build.0 = Release|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Release|x86.ActiveCfg = Release|Any CPU - {6FAD289A-7297-4CBD-903C-E632AFC5900C}.Release|x86.Build.0 = Release|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Debug|arm64.ActiveCfg = Debug|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Debug|arm64.Build.0 = Debug|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Debug|x64.ActiveCfg = Debug|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Debug|x64.Build.0 = Debug|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Debug|x86.ActiveCfg = Debug|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Debug|x86.Build.0 = Debug|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Release|Any CPU.Build.0 = Release|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Release|arm64.ActiveCfg = Release|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Release|arm64.Build.0 = Release|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Release|x64.ActiveCfg = Release|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Release|x64.Build.0 = Release|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Release|x86.ActiveCfg = Release|Any CPU - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD}.Release|x86.Build.0 = Release|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Debug|arm64.ActiveCfg = Debug|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Debug|arm64.Build.0 = Debug|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Debug|x64.ActiveCfg = Debug|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Debug|x64.Build.0 = Debug|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Debug|x86.ActiveCfg = Debug|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Debug|x86.Build.0 = Debug|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Release|Any CPU.Build.0 = Release|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Release|arm64.ActiveCfg = Release|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Release|arm64.Build.0 = Release|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Release|x64.ActiveCfg = Release|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Release|x64.Build.0 = Release|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Release|x86.ActiveCfg = Release|Any CPU - {739C38F2-4D2B-4ADF-8980-BC28F18876B3}.Release|x86.Build.0 = Release|Any CPU - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|Any CPU.ActiveCfg = Debug|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|Any CPU.Build.0 = Debug|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|Any CPU.Deploy.0 = Debug|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|arm64.ActiveCfg = Debug|arm64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|arm64.Build.0 = Debug|arm64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|arm64.Deploy.0 = Debug|arm64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|x64.ActiveCfg = Debug|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|x64.Build.0 = Debug|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|x64.Deploy.0 = Debug|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|x86.ActiveCfg = Debug|x86 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|x86.Build.0 = Debug|x86 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Debug|x86.Deploy.0 = Debug|x86 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|Any CPU.ActiveCfg = Release|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|Any CPU.Build.0 = Release|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|Any CPU.Deploy.0 = Release|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|arm64.ActiveCfg = Release|arm64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|arm64.Build.0 = Release|arm64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|arm64.Deploy.0 = Release|arm64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|x64.ActiveCfg = Release|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|x64.Build.0 = Release|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|x64.Deploy.0 = Release|x64 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|x86.ActiveCfg = Release|x86 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|x86.Build.0 = Release|x86 - {66F715C7-7009-4957-B249-C4A3B03F02C2}.Release|x86.Deploy.0 = Release|x86 - {1567153D-8F2C-4766-98C9-54166088B6FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Debug|arm64.ActiveCfg = Debug|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Debug|arm64.Build.0 = Debug|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Debug|x64.ActiveCfg = Debug|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Debug|x64.Build.0 = Debug|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Debug|x86.ActiveCfg = Debug|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Debug|x86.Build.0 = Debug|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Release|Any CPU.Build.0 = Release|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Release|arm64.ActiveCfg = Release|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Release|arm64.Build.0 = Release|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Release|x64.ActiveCfg = Release|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Release|x64.Build.0 = Release|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Release|x86.ActiveCfg = Release|Any CPU - {1567153D-8F2C-4766-98C9-54166088B6FE}.Release|x86.Build.0 = Release|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Debug|arm64.ActiveCfg = Debug|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Debug|arm64.Build.0 = Debug|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Debug|x64.ActiveCfg = Debug|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Debug|x64.Build.0 = Debug|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Debug|x86.ActiveCfg = Debug|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Debug|x86.Build.0 = Debug|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Release|Any CPU.ActiveCfg = Release|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Release|Any CPU.Build.0 = Release|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Release|arm64.ActiveCfg = Release|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Release|arm64.Build.0 = Release|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Release|x64.ActiveCfg = Release|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Release|x64.Build.0 = Release|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Release|x86.ActiveCfg = Release|Any CPU - {59D2794E-1B4E-4AC6-89C2-F2142755EE27}.Release|x86.Build.0 = Release|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Debug|Any CPU.Build.0 = Debug|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Debug|arm64.ActiveCfg = Debug|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Debug|arm64.Build.0 = Debug|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Debug|x64.ActiveCfg = Debug|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Debug|x64.Build.0 = Debug|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Debug|x86.ActiveCfg = Debug|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Debug|x86.Build.0 = Debug|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Release|Any CPU.ActiveCfg = Release|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Release|Any CPU.Build.0 = Release|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Release|arm64.ActiveCfg = Release|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Release|arm64.Build.0 = Release|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Release|x64.ActiveCfg = Release|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Release|x64.Build.0 = Release|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Release|x86.ActiveCfg = Release|Any CPU - {55A23CDB-01A5-49A4-8EC9-6A6B8E654667}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {FBB702F5-6B5A-4AE4-9DA8-85EBD95CB9FD} = {30634DDE-9E2E-47F7-AFD3-F00F175CDF17} - {739C38F2-4D2B-4ADF-8980-BC28F18876B3} = {30634DDE-9E2E-47F7-AFD3-F00F175CDF17} - {66F715C7-7009-4957-B249-C4A3B03F02C2} = {30634DDE-9E2E-47F7-AFD3-F00F175CDF17} - {59D2794E-1B4E-4AC6-89C2-F2142755EE27} = {30634DDE-9E2E-47F7-AFD3-F00F175CDF17} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {22556FAD-0868-4B3C-A205-85DF6407972B} - EndGlobalSection -EndGlobal From 7bddf8e43df3a7580a3a6a709315a846517f4e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 16:26:16 -0600 Subject: [PATCH 05/78] delete old uno --- samples/UnoPlatformSample/.vscode/launch.json | 46 - .../UnoPlatformSample/.vscode/settings.json | 7 - samples/UnoPlatformSample/.vscode/tasks.json | 53 - samples/UnoPlatformSample/.vsconfig | 38 - .../UnoPlatformSample/Directory.Build.props | 59 -- .../UnoPlatformSample/Directory.Build.targets | 2 - .../UnoPlatformSample.Base/AppHead.xaml | 17 - .../UnoPlatformSample.Base/AppHead.xaml.cs | 35 - .../Icons/appconfig.svg | 137 --- .../UnoPlatformSample.Base/Icons/iconapp.svg | 42 - .../Splash/splash_screen.svg | 137 --- .../UnoPlatformSample.Base/base.props | 25 - .../Serialization/WeatherForecastContext.cs | 42 - .../UnoPlatformSample.DataContracts.csproj | 8 - .../WeatherForecast.cs | 37 - .../Android/AndroidManifest.xml | 4 - .../Android/Assets/AboutAssets.txt | 22 - .../Android/Main.Android.cs | 64 -- .../Android/MainActivity.Android.cs | 37 - .../Android/Resources/AboutResources.txt | 47 - .../Android/Resources/values/Strings.xml | 5 - .../Android/Resources/values/Styles.xml | 23 - .../Android/environment.conf | 2 - .../MacCatalyst/Entitlements.plist | 6 - .../MacCatalyst/Info.plist | 29 - .../MacCatalyst/Main.maccatalyst.cs | 35 - .../LaunchImages.launchimage/Contents.json | 58 -- .../UnoPlatformSample.Mobile.csproj | 84 -- .../iOS/Entitlements.plist | 6 - .../UnoPlatformSample.Mobile/iOS/Info.plist | 51 - .../UnoPlatformSample.Mobile/iOS/Main.iOS.cs | 35 - .../LaunchImages.launchimage/Contents.json | 58 -- .../Apis/WeatherForecastApi.cs | 69 -- .../UnoPlatformSample.Server/GlobalUsings.cs | 25 - .../UnoPlatformSample.Server/Program.cs | 80 -- .../Properties/launchSettings.json | 33 - .../UnoPlatformSample.Server.csproj | 18 - .../appsettings.Development.json | 8 - .../UnoPlatformSample.Server/appsettings.json | 9 - .../Package.appxmanifest | 43 - .../UnoPlatformSample.Skia.Gtk/Program.cs | 42 - .../UnoPlatformSample.Skia.Gtk.csproj | 40 - .../UnoPlatformSample.Skia.Gtk/app.manifest | 77 -- .../UnoPlatformSample.Tests/AppInfoTests.cs | 40 - .../UnoPlatformSample.Tests/GlobalUsings.cs | 25 - .../UnoPlatformSample.Tests.csproj | 19 - .../UnoPlatformSample.UITests/Constants.cs | 33 - .../Given_MainPage.cs | 43 - .../UnoPlatformSample.UITests/GlobalUsings.cs | 28 - .../UnoPlatformSample.UITests/TestBase.cs | 102 -- .../UnoPlatformSample.UITests.csproj | 16 - .../UnoPlatformSample.Wasm/LinkerConfig.xml | 11 - .../UnoPlatformSample.Wasm/Program.cs | 35 - .../Properties/launchSettings.json | 30 - .../UnoPlatformSample.Wasm.csproj | 87 -- .../UnoPlatformSample.Wasm/WasmCSS/Fonts.css | 28 - .../WasmScripts/AppManifest.js | 3 - .../manifest.webmanifest | 10 - .../wwwroot/staticwebapp.config.json | 30 - .../UnoPlatformSample.Wasm/wwwroot/web.config | 78 -- .../Package.appxmanifest | 43 - .../Properties/launchsettings.json | 10 - .../Resources.lang-en-us.resw | 123 --- .../UnoPlatformSample.Windows.csproj | 71 -- .../UnoPlatformSample.Windows/app.manifest | 15 - .../UnoPlatformSample/UnoPlatformSample.sln | 296 ------ .../UnoPlatformSample/App.cs | 108 -- .../UnoPlatformSample/AppResources.xaml | 14 - .../UnoPlatformSample/Assets/Icons/back.svg | 3 - .../UnoPlatformSample/Assets/SharedAssets.md | 34 - .../Business/Models/AppConfig.cs | 28 - .../Business/Models/Entity.cs | 25 - .../UnoPlatformSample/GlobalSuppressions.cs | 8 - .../UnoPlatformSample/GlobalUsings.cs | 56 -- .../Infrastructure/DebugHandler.cs | 62 -- .../Axes/ColorsAndPosition/View.xaml | 31 - .../Axes/ColorsAndPosition/View.xaml.cs | 11 - .../Axes/Crosshairs/View.xaml | 22 - .../Axes/Crosshairs/View.xaml.cs | 11 - .../Axes/CustomSeparatorsInterval/View.xaml | 16 - .../CustomSeparatorsInterval/View.xaml.cs | 11 - .../Axes/DateTimeScaled/View.xaml | 16 - .../Axes/DateTimeScaled/View.xaml.cs | 11 - .../Axes/LabelsFormat/View.xaml | 17 - .../Axes/LabelsFormat/View.xaml.cs | 11 - .../Axes/LabelsFormat2/View.xaml | 17 - .../Axes/LabelsFormat2/View.xaml.cs | 11 - .../Axes/LabelsRotation/View.xaml | 39 - .../Axes/LabelsRotation/View.xaml.cs | 11 - .../Axes/Logarithmic/View.xaml | 16 - .../Axes/Logarithmic/View.xaml.cs | 11 - .../LiveChartsSamples/Axes/Multiple/View.xaml | 20 - .../Axes/Multiple/View.xaml.cs | 11 - .../Axes/NamedLabels/View.xaml | 29 - .../Axes/NamedLabels/View.xaml.cs | 11 - .../LiveChartsSamples/Axes/Paging/View.xaml | 30 - .../Axes/Paging/View.xaml.cs | 11 - .../LiveChartsSamples/Axes/Shared/View.xaml | 36 - .../Axes/Shared/View.xaml.cs | 11 - .../LiveChartsSamples/Axes/Style/View.xaml | 24 - .../LiveChartsSamples/Axes/Style/View.xaml.cs | 11 - .../Axes/TimeSpanScaled/View.xaml | 16 - .../Axes/TimeSpanScaled/View.xaml.cs | 11 - .../Bars/AutoUpdate/View.xaml | 30 - .../Bars/AutoUpdate/View.xaml.cs | 29 - .../LiveChartsSamples/Bars/Basic/View.xaml | 17 - .../LiveChartsSamples/Bars/Basic/View.xaml.cs | 11 - .../LiveChartsSamples/Bars/Custom/View.xaml | 18 - .../Bars/Custom/View.xaml.cs | 11 - .../Bars/DelayedAnimation/View.xaml | 18 - .../Bars/DelayedAnimation/View.xaml.cs | 11 - .../LiveChartsSamples/Bars/Layered/View.xaml | 18 - .../Bars/Layered/View.xaml.cs | 11 - .../LiveChartsSamples/Bars/Race/View.xaml | 26 - .../LiveChartsSamples/Bars/Race/View.xaml.cs | 13 - .../Bars/RowsWithLabels/View.xaml | 18 - .../Bars/RowsWithLabels/View.xaml.cs | 11 - .../LiveChartsSamples/Bars/Spacing/View.xaml | 18 - .../Bars/Spacing/View.xaml.cs | 11 - .../Bars/WithBackground/View.xaml | 18 - .../Bars/WithBackground/View.xaml.cs | 11 - .../LiveChartsSamples/Box/Basic/View.xaml | 17 - .../LiveChartsSamples/Box/Basic/View.xaml.cs | 11 - .../Design/LinearGradients/View.xaml | 18 - .../Design/LinearGradients/View.xaml.cs | 11 - .../Design/RadialGradients/View.xaml | 18 - .../Design/RadialGradients/View.xaml.cs | 11 - .../Design/StrokeDashArray/View.xaml | 18 - .../Design/StrokeDashArray/View.xaml.cs | 11 - .../LiveChartsSamples/Error/Basic/View.xaml | 35 - .../Error/Basic/View.xaml.cs | 11 - .../Events/AddPointOnClick/View.xaml | 20 - .../Events/AddPointOnClick/View.xaml.cs | 14 - .../Events/Cartesian/View.xaml | 21 - .../Events/Cartesian/View.xaml.cs | 11 - .../LiveChartsSamples/Events/Pie/View.xaml | 22 - .../LiveChartsSamples/Events/Pie/View.xaml.cs | 45 - .../LiveChartsSamples/Events/Polar/View.xaml | 21 - .../Events/Polar/View.xaml.cs | 45 - .../Financial/BasicCandlesticks/View.xaml | 21 - .../Financial/BasicCandlesticks/View.xaml.cs | 11 - .../General/Animations/View.xaml | 39 - .../General/Animations/View.xaml.cs | 11 - .../General/ChartToImage/View.xaml | 40 - .../General/ChartToImage/View.xaml.cs | 47 - .../General/ConditionalDraw/View.xaml | 17 - .../General/ConditionalDraw/View.xaml.cs | 11 - .../General/Legends/View.xaml | 32 - .../General/Legends/View.xaml.cs | 11 - .../General/MapPoints/View.xaml | 17 - .../General/MapPoints/View.xaml.cs | 11 - .../General/MultiThreading/View.xaml | 21 - .../General/MultiThreading/View.xaml.cs | 11 - .../General/MultiThreading2/View.xaml | 15 - .../General/MultiThreading2/View.xaml.cs | 28 - .../General/NullPoints/View.xaml | 18 - .../General/NullPoints/View.xaml.cs | 11 - .../General/RealTime/View.xaml | 18 - .../General/RealTime/View.xaml.cs | 11 - .../General/Scrollable/View.xaml | 45 - .../General/Scrollable/View.xaml.cs | 9 - .../General/Sections/View.xaml | 24 - .../General/Sections/View.xaml.cs | 11 - .../General/Sections2/View.xaml | 18 - .../General/Sections2/View.xaml.cs | 11 - .../General/TemplatedLegends/View.xaml | 23 - .../General/TemplatedLegends/View.xaml.cs | 11 - .../General/TemplatedTooltips/View.xaml | 23 - .../General/TemplatedTooltips/View.xaml.cs | 11 - .../General/Tooltips/View.xaml | 27 - .../General/Tooltips/View.xaml.cs | 11 - .../General/UserDefinedTypes/View.xaml | 18 - .../General/UserDefinedTypes/View.xaml.cs | 11 - .../General/Visibility/View.xaml | 27 - .../General/Visibility/View.xaml.cs | 11 - .../General/VisualElements/View.xaml | 23 - .../General/VisualElements/View.xaml.cs | 11 - .../LiveChartsSamples/Heat/Basic/View.xaml | 22 - .../LiveChartsSamples/Heat/Basic/View.xaml.cs | 11 - .../LiveChartsSamples/Lines/Area/View.xaml | 16 - .../LiveChartsSamples/Lines/Area/View.xaml.cs | 11 - .../Lines/AutoUpdate/View.xaml | 30 - .../Lines/AutoUpdate/View.xaml.cs | 29 - .../LiveChartsSamples/Lines/Basic/View.xaml | 14 - .../Lines/Basic/View.xaml.cs | 11 - .../LiveChartsSamples/Lines/Custom/View.xaml | 13 - .../Lines/Custom/View.xaml.cs | 11 - .../LiveChartsSamples/Lines/Padding/View.xaml | 21 - .../Lines/Padding/View.xaml.cs | 11 - .../Lines/Properties/View.xaml | 34 - .../Lines/Properties/View.xaml.cs | 11 - .../Lines/Straight/View.xaml | 13 - .../Lines/Straight/View.xaml.cs | 11 - .../LiveChartsSamples/Lines/XY/View.xaml | 14 - .../LiveChartsSamples/Lines/XY/View.xaml.cs | 11 - .../LiveChartsSamples/Lines/Zoom/View.xaml | 18 - .../LiveChartsSamples/Lines/Zoom/View.xaml.cs | 11 - .../LiveChartsSamples/Maps/World/View.xaml | 13 - .../LiveChartsSamples/Maps/World/View.xaml.cs | 11 - .../Pies/AngularGauge/View.xaml | 30 - .../Pies/AngularGauge/View.xaml.cs | 11 - .../Pies/AutoUpdate/View.xaml | 28 - .../Pies/AutoUpdate/View.xaml.cs | 29 - .../LiveChartsSamples/Pies/Basic/View.xaml | 16 - .../LiveChartsSamples/Pies/Basic/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Custom/View.xaml | 13 - .../Pies/Custom/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Doughnut/View.xaml | 20 - .../Pies/Doughnut/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Gauge/View.xaml | 46 - .../LiveChartsSamples/Pies/Gauge/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Gauge1/View.xaml | 18 - .../Pies/Gauge1/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Gauge2/View.xaml | 19 - .../Pies/Gauge2/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Gauge3/View.xaml | 19 - .../Pies/Gauge3/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Gauge4/View.xaml | 18 - .../Pies/Gauge4/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Gauge5/View.xaml | 30 - .../Pies/Gauge5/View.xaml.cs | 11 - .../LiveChartsSamples/Pies/Gauges/View.xaml | 125 --- .../Pies/Gauges/View.xaml.cs | 11 - .../Pies/NightingaleRose/View.xaml | 18 - .../Pies/NightingaleRose/View.xaml.cs | 11 - .../Pies/Processing/View.xaml | 51 - .../Pies/Processing/View.xaml.cs | 35 - .../LiveChartsSamples/Pies/Pushout/View.xaml | 18 - .../Pies/Pushout/View.xaml.cs | 11 - .../LiveChartsSamples/Polar/Basic/View.xaml | 22 - .../Polar/Basic/View.xaml.cs | 11 - .../Polar/Coordinates/View.xaml | 13 - .../Polar/Coordinates/View.xaml.cs | 11 - .../Polar/RadialArea/View.xaml | 13 - .../Polar/RadialArea/View.xaml.cs | 11 - .../Scatter/AutoUpdate/View.xaml | 30 - .../Scatter/AutoUpdate/View.xaml.cs | 29 - .../LiveChartsSamples/Scatter/Basic/View.xaml | 18 - .../Scatter/Basic/View.xaml.cs | 11 - .../Scatter/Bubbles/View.xaml | 18 - .../Scatter/Bubbles/View.xaml.cs | 11 - .../Scatter/Custom/View.xaml | 18 - .../Scatter/Custom/View.xaml.cs | 11 - .../StackedArea/Basic/View.xaml | 18 - .../StackedArea/Basic/View.xaml.cs | 11 - .../StackedArea/StepArea/View.xaml | 18 - .../StackedArea/StepArea/View.xaml.cs | 11 - .../StackedBars/Basic/View.xaml | 18 - .../StackedBars/Basic/View.xaml.cs | 11 - .../StackedBars/Groups/View.xaml | 13 - .../StackedBars/Groups/View.xaml.cs | 11 - .../StepLines/Area/View.xaml | 17 - .../StepLines/Area/View.xaml.cs | 11 - .../StepLines/AutoUpdate/View.xaml | 30 - .../StepLines/AutoUpdate/View.xaml.cs | 29 - .../StepLines/Basic/View.xaml | 18 - .../StepLines/Basic/View.xaml.cs | 11 - .../StepLines/Custom/View.xaml | 18 - .../StepLines/Custom/View.xaml.cs | 11 - .../StepLines/Properties/View.xaml | 34 - .../StepLines/Properties/View.xaml.cs | 11 - .../StepLines/Zoom/View.xaml | 23 - .../StepLines/Zoom/View.xaml.cs | 11 - .../Test/Dispose/UserControl1.xaml | 28 - .../Test/Dispose/UserControl1.xaml.cs | 11 - .../LiveChartsSamples/Test/Dispose/View.xaml | 37 - .../Test/Dispose/View.xaml.cs | 20 - .../VisualTest/DataTemplate/View.xaml | 24 - .../VisualTest/DataTemplate/View.xaml.cs | 11 - .../VisualTest/ReattachVisual/View.xaml | 55 - .../VisualTest/ReattachVisual/View.xaml.cs | 30 - .../VisualTest/Tabs/View.xaml | 23 - .../VisualTest/Tabs/View.xaml.cs | 11 - .../VisualTest/TwoChartsOneSeries/View.xaml | 32 - .../TwoChartsOneSeries/View.xaml.cs | 11 - .../Presentation/MainModel.cs | 50 - .../Presentation/MainPage.xaml | 69 -- .../Presentation/MainPage.xaml.cs | 54 - .../Presentation/SecondModel.cs | 27 - .../Presentation/SecondPage.xaml | 27 - .../Presentation/SecondPage.xaml.cs | 32 - .../UnoPlatformSample/Presentation/Shell.xaml | 35 - .../Presentation/Shell.xaml.cs | 34 - .../Presentation/ShellModel.cs | 40 - .../Services/Caching/IWeatherCache.cs | 30 - .../Services/Caching/WeatherCache.cs | 100 -- .../Services/Endpoints/IApiClient.cs | 32 - .../Strings/en/Resources.resw | 123 --- .../Strings/es/Resources.resw | 123 --- .../Strings/fr/Resources.resw | 123 --- .../Strings/pt-BR/Resources.resw | 123 --- .../Styles/ColorPaletteOverride.xaml | 65 -- .../Styles/ColorPaletteOverride.zip | Bin 5848 -> 0 bytes .../Styles/MaterialFontsOverride.xaml | 8 - .../UnoPlatformSample.csproj | 79 -- .../appsettings.development.json | 9 - .../UnoPlatformSample/appsettings.json | 16 - .../AssemblyInfo.cs | 32 - .../CartesianChart.xaml | 14 - .../CartesianChart.xaml.cs | 947 ------------------ .../GeoMap.xaml | 14 - .../GeoMap.xaml.cs | 279 ------ .../Helpers/LiveChartsPinchEventArgs.cs | 32 - .../Helpers/UnoPlatformHelpers.cs | 62 -- ...eChartsCore.SkiaSharpView.Uno.WinUI.csproj | 86 -- .../MotionCanvas.xaml | 14 - .../MotionCanvas.xaml.cs | 283 ------ .../PieChart.xaml | 14 - .../PieChart.xaml.cs | 762 -------------- .../PolarChart.xaml | 14 - .../PolarChart.xaml.cs | 859 ---------------- .../images/icon.png | Bin 7880 -> 0 bytes 312 files changed, 11567 deletions(-) delete mode 100644 samples/UnoPlatformSample/.vscode/launch.json delete mode 100644 samples/UnoPlatformSample/.vscode/settings.json delete mode 100644 samples/UnoPlatformSample/.vscode/tasks.json delete mode 100644 samples/UnoPlatformSample/.vsconfig delete mode 100644 samples/UnoPlatformSample/Directory.Build.props delete mode 100644 samples/UnoPlatformSample/Directory.Build.targets delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/appconfig.svg delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/iconapp.svg delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/Splash/splash_screen.svg delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/base.props delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.DataContracts/Serialization/WeatherForecastContext.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.DataContracts/UnoPlatformSample.DataContracts.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.DataContracts/WeatherForecast.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/AndroidManifest.xml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Assets/AboutAssets.txt delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Main.Android.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/MainActivity.Android.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/AboutResources.txt delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Strings.xml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Styles.xml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/environment.conf delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Entitlements.plist delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Info.plist delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Main.maccatalyst.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/UnoPlatformSample.Mobile.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Entitlements.plist delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Info.plist delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Main.iOS.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/Apis/WeatherForecastApi.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/GlobalUsings.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/Program.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/Properties/launchSettings.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/UnoPlatformSample.Server.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.Development.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Package.appxmanifest delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Program.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/app.manifest delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Tests/AppInfoTests.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Tests/GlobalUsings.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Tests/UnoPlatformSample.Tests.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/Constants.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/Given_MainPage.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/GlobalUsings.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/TestBase.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/UnoPlatformSample.UITests.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/LinkerConfig.xml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/Program.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/Properties/launchSettings.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmCSS/Fonts.css delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmScripts/AppManifest.js delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/manifest.webmanifest delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/staticwebapp.config.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/web.config delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/Package.appxmanifest delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/Properties/launchsettings.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/Resources.lang-en-us.resw delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/UnoPlatformSample.Windows.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/app.manifest delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample.sln delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/App.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/AppResources.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Assets/Icons/back.svg delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Assets/SharedAssets.md delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Business/Models/AppConfig.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Business/Models/Entity.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/GlobalSuppressions.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/GlobalUsings.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Infrastructure/DebugHandler.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainModel.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondModel.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/ShellModel.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/IWeatherCache.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/WeatherCache.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Services/Endpoints/IApiClient.cs delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Strings/en/Resources.resw delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Strings/es/Resources.resw delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Strings/fr/Resources.resw delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Strings/pt-BR/Resources.resw delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.zip delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Styles/MaterialFontsOverride.xaml delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/appsettings.development.json delete mode 100644 samples/UnoPlatformSample/UnoPlatformSample/appsettings.json delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/AssemblyInfo.cs delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml.cs delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/images/icon.png diff --git a/samples/UnoPlatformSample/.vscode/launch.json b/samples/UnoPlatformSample/.vscode/launch.json deleted file mode 100644 index e0ef2aa8b..000000000 --- a/samples/UnoPlatformSample/.vscode/launch.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "version": "0.2.0", - "configurations": [ - { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "name": "Debug (Chrome, WebAssembly)", - "type": "chrome", - "request": "launch", - "url": "http://localhost:5000", - "webRoot": "${workspaceFolder}/UnoPlatformSample.Wasm", - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "timeout": 30000, - "server": { - "runtimeExecutable": "dotnet", - "program": "run", - "outputCapture": "std", - "timeout": 30000, - "cwd": "${workspaceFolder}/UnoPlatformSample.Wasm" - } - }, - { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "name": "Skia.GTK (Debug)", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-skia-gtk", - // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/UnoPlatformSample.Skia.Gtk/bin/Debug/net7.0/UnoPlatformSample.Skia.Gtk.dll", - "args": [], - "env": { - "DOTNET_MODIFIABLE_ASSEMBLIES": "debug" - }, - "cwd": "${workspaceFolder}/UnoPlatformSample.Skia.Gtk", - // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console - "console": "internalConsole", - "stopAtEntry": false - } - ] -} diff --git a/samples/UnoPlatformSample/.vscode/settings.json b/samples/UnoPlatformSample/.vscode/settings.json deleted file mode 100644 index 23133fc7c..000000000 --- a/samples/UnoPlatformSample/.vscode/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "explorer.fileNesting.enabled": true, - "explorer.fileNesting.expand": false, - "explorer.fileNesting.patterns": { - "*.xaml": "$(capture).xaml.cs" - } -} diff --git a/samples/UnoPlatformSample/.vscode/tasks.json b/samples/UnoPlatformSample/.vscode/tasks.json deleted file mode 100644 index 32f202f6d..000000000 --- a/samples/UnoPlatformSample/.vscode/tasks.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build-wasm", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "publish-wasm", - "command": "dotnet", - "type": "process", - "args": [ - "publish", - "${workspaceFolder}/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-skia-gtk", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "publish-skia-gtk", - "command": "dotnet", - "type": "process", - "args": [ - "publish", - "${workspaceFolder}/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - } - ] -} diff --git a/samples/UnoPlatformSample/.vsconfig b/samples/UnoPlatformSample/.vsconfig deleted file mode 100644 index 1c9c22808..000000000 --- a/samples/UnoPlatformSample/.vsconfig +++ /dev/null @@ -1,38 +0,0 @@ -{ - "version": "1.0", - "components": [ - "Microsoft.VisualStudio.Component.CoreEditor", - "Microsoft.VisualStudio.Workload.CoreEditor", - "Microsoft.NetCore.Component.SDK", - "Microsoft.NetCore.Component.DevelopmentTools", - "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions", - "Microsoft.NetCore.Component.Web", - "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites", - "Microsoft.VisualStudio.Component.TextTemplating", - "Microsoft.VisualStudio.Component.IISExpress", - "Component.Microsoft.Web.LibraryManager", - "Microsoft.VisualStudio.ComponentGroup.Web", - "Microsoft.VisualStudio.Component.Web", - "Microsoft.VisualStudio.ComponentGroup.Web.Client", - "Microsoft.VisualStudio.Workload.NetWeb", - "Microsoft.VisualStudio.ComponentGroup.Azure.Prerequisites", - "Microsoft.VisualStudio.Workload.Azure", - "Microsoft.VisualStudio.Component.Windows10SDK.19041", - "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites", - "Microsoft.VisualStudio.Component.Debugger.JustInTime", - "Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging", - "Microsoft.VisualStudio.Workload.ManagedDesktop", - "Microsoft.Component.NetFX.Native", - "Microsoft.VisualStudio.Component.Graphics", - "Component.OpenJDK", - "Microsoft.VisualStudio.Component.MonoDebugger", - "Microsoft.VisualStudio.Component.Merq", - "Component.Xamarin.RemotedSimulator", - "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.TemplateEngine", - "Component.Xamarin", - "Component.Android.SDK32", - "Microsoft.VisualStudio.Workload.NetCrossPlat", - "Microsoft.VisualStudio.Workload.NetCoreTools", - "Microsoft.VisualStudio.ComponentGroup.Maui.All" - ] -} diff --git a/samples/UnoPlatformSample/Directory.Build.props b/samples/UnoPlatformSample/Directory.Build.props deleted file mode 100644 index 76f7aa4b4..000000000 --- a/samples/UnoPlatformSample/Directory.Build.props +++ /dev/null @@ -1,59 +0,0 @@ - - - 11 - enable - enable - - portable - True - true - - True - $(NoWarn);Uno0001;CS1998;CA1416;NU1507 - - en - - false - false - false - false - false - - - - - - true - 21.0 - - - - - true - 14.2 - iossimulator-x64 - - - - - true - 10.14 - osx-x64 - - - - - true - 14.0 - maccatalyst-x64 - - - - - true - 10.0.18362.0 - 10.0.18362.0 - - - - diff --git a/samples/UnoPlatformSample/Directory.Build.targets b/samples/UnoPlatformSample/Directory.Build.targets deleted file mode 100644 index 0d24ec238..000000000 --- a/samples/UnoPlatformSample/Directory.Build.targets +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml b/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml deleted file mode 100644 index 4edcdc464..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml.cs deleted file mode 100644 index 1a0a15ab1..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml.cs +++ /dev/null @@ -1,35 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample; - -public sealed partial class AppHead : App -{ - /// - /// Initializes the singleton application object. This is the first line of authored code - /// executed, and as such is the logical equivalent of main() or WinMain(). - /// - public AppHead() - { - this.InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/appconfig.svg b/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/appconfig.svg deleted file mode 100644 index 3106b1a8b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/appconfig.svg +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/iconapp.svg b/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/iconapp.svg deleted file mode 100644 index f621ea597..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/iconapp.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/Splash/splash_screen.svg b/samples/UnoPlatformSample/UnoPlatformSample.Base/Splash/splash_screen.svg deleted file mode 100644 index 3106b1a8b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Base/Splash/splash_screen.svg +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/base.props b/samples/UnoPlatformSample/UnoPlatformSample.Base/base.props deleted file mode 100644 index 10bfdc157..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Base/base.props +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/Serialization/WeatherForecastContext.cs b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/Serialization/WeatherForecastContext.cs deleted file mode 100644 index 68a17a7aa..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/Serialization/WeatherForecastContext.cs +++ /dev/null @@ -1,42 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System.Collections.Immutable; -using System.Text.Json.Serialization; - -namespace UnoPlatformSample.DataContracts.Serialization; -/* - * When using the JsonSerializerContext you must add the JsonSerializableAttribute - * for each type that you may need to serialize / deserialize including both the - * concrete type and any interface that the concrete type implements. - * For more information on the JsonSerializerContext see: - * https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation?WT.mc_id=DT-MVP-5002924 - */ -[JsonSerializable(typeof(WeatherForecast))] -[JsonSerializable(typeof(WeatherForecast[]))] -[JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IImmutableList))] -[JsonSerializable(typeof(ImmutableList))] -[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] -public partial class WeatherForecastContext : JsonSerializerContext -{ -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/UnoPlatformSample.DataContracts.csproj b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/UnoPlatformSample.DataContracts.csproj deleted file mode 100644 index a56e0b084..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/UnoPlatformSample.DataContracts.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - net7.0 - true - - $(NoWarn);CS1591 - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/WeatherForecast.cs b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/WeatherForecast.cs deleted file mode 100644 index a8fef0c79..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/WeatherForecast.cs +++ /dev/null @@ -1,37 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.DataContracts; - -/// -/// A Weather Forecast for a specific date -/// -/// Gets the Date of the Forecast. -/// Gets the Forecast Temperature in Celsius. -/// Get a description of how the weather will feel. -public record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) -{ - /// - /// Gets the Forecast Temperature in Fahrenheit - /// - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/AndroidManifest.xml b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/AndroidManifest.xml deleted file mode 100644 index 95ae07533..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Assets/AboutAssets.txt b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Assets/AboutAssets.txt deleted file mode 100644 index 210a93b80..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Assets/AboutAssets.txt +++ /dev/null @@ -1,22 +0,0 @@ -To add cross-platform image assets for your Uno Platform app, use the Assets folder -in the shared project instead. Assets in this folder are Android-only assets. - -Any raw assets you want to be deployed with your application can be placed in -this directory (and child directories) and given a Build Action of "AndroidAsset". - -These files will be deployed with you package and will be accessible using Android's -AssetManager, like this: - -public class ReadAsset : Activity -{ - protected override void OnCreate (Bundle bundle) - { - base.OnCreate (bundle); - - InputStream input = Assets.Open ("my_asset.txt"); - } -} - -Additionally, some Android functions will automatically load asset files: - -Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Main.Android.cs b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Main.Android.cs deleted file mode 100644 index dde1359a7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Main.Android.cs +++ /dev/null @@ -1,64 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Android.App; -using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; -using Com.Nostra13.Universalimageloader.Core; -using Microsoft.UI.Xaml.Media; - -namespace UnoPlatformSample.Droid; -[global::Android.App.ApplicationAttribute( - Label = "@string/ApplicationName", - Icon = "@mipmap/iconapp", - LargeHeap = true, - HardwareAccelerated = true, - Theme = "@style/AppTheme" -)] -public class Application : Microsoft.UI.Xaml.NativeApplication -{ - public Application(IntPtr javaReference, JniHandleOwnership transfer) - : base(() => new AppHead(), javaReference, transfer) - { - ConfigureUniversalImageLoader(); - } - - private static void ConfigureUniversalImageLoader() - { - // Create global configuration and initialize ImageLoader with this config - ImageLoaderConfiguration config = new ImageLoaderConfiguration - .Builder(Context) - .Build(); - - ImageLoader.Instance.Init(config); - - ImageSource.DefaultImageLoader = ImageLoader.Instance.LoadImageAsync; - } -} - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/MainActivity.Android.cs b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/MainActivity.Android.cs deleted file mode 100644 index f51cacc98..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/MainActivity.Android.cs +++ /dev/null @@ -1,37 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using Android.App; -using Android.Content.PM; -using Android.OS; -using Android.Views; -using Android.Widget; - -namespace UnoPlatformSample.Droid; -[Activity( - MainLauncher = true, - ConfigurationChanges = global::Uno.UI.ActivityHelper.AllConfigChanges, - WindowSoftInputMode = SoftInput.AdjustNothing | SoftInput.StateHidden -)] -public class MainActivity : Microsoft.UI.Xaml.ApplicationActivity -{ -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/AboutResources.txt b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/AboutResources.txt deleted file mode 100644 index 17e3b1333..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/AboutResources.txt +++ /dev/null @@ -1,47 +0,0 @@ -To add cross-platform image assets for your Uno Platform app, use the Assets folder -in the shared project instead. Resources in this folder are Android-only. - -Images, layout descriptions, binary blobs and string dictionaries can be included -in your application as resource files. Various Android APIs are designed to -operate on the resource IDs instead of dealing with images, strings or binary blobs -directly. - -For example, a sample Android app that contains a user interface layout (main.axml), -an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) -would keep its resources in the "Resources" directory of the application: - -Resources/ - drawable/ - icon.png - - layout/ - main.axml - - values/ - strings.xml - -In order to get the build system to recognize Android resources, set the build action to -"AndroidResource". The native Android APIs do not operate directly with filenames, but -instead operate on resource IDs. When you compile an Android application that uses resources, -the build system will package the resources for distribution and generate a class called "R" -(this is an Android convention) that contains the tokens for each one of the resources -included. For example, for the above Resources layout, this is what the R class would expose: - -public class R { - public class drawable { - public const int icon = 0x123; - } - - public class layout { - public const int main = 0x456; - } - - public class strings { - public const int first_string = 0xabc; - public const int second_string = 0xbcd; - } -} - -You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main -to reference the layout/main.axml file, or R.strings.first_string to reference the first -string in the dictionary file values/strings.xml. diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Strings.xml b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Strings.xml deleted file mode 100644 index 302d078a6..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - Hello World, Click Me! - UnoPlatformSample - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Styles.xml b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Styles.xml deleted file mode 100644 index fd16cd77f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Styles.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/environment.conf b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/environment.conf deleted file mode 100644 index fa6c2e32b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/environment.conf +++ /dev/null @@ -1,2 +0,0 @@ -# See this for more details: http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/ -MONO_GC_PARAMS=bridge-implementation=tarjan,nursery-size=32m,soft-heap-limit=256m \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Entitlements.plist b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Entitlements.plist deleted file mode 100644 index 24c310368..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Entitlements.plist +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Info.plist b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Info.plist deleted file mode 100644 index 752b37a66..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Info.plist +++ /dev/null @@ -1,29 +0,0 @@ - - - - - UIDeviceFamily - - 2 - - LSApplicationCategoryType - public.app-category.utilities - UILaunchStoryboardName - LaunchScreen - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - XSAppIconAssets - Media.xcassets/iconapp.appiconset - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Main.maccatalyst.cs b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Main.maccatalyst.cs deleted file mode 100644 index b1f31e7b7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Main.maccatalyst.cs +++ /dev/null @@ -1,35 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using UIKit; - -namespace UnoPlatformSample.MacCatalyst; -public class EntryPoint -{ - // This is the main entry point of the application. - public static void Main(string[] args) - { - // if you want to use a different Application Delegate class from "AppDelegate" - // you can specify it here. - UIApplication.Main(args, null, typeof(AppHead)); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json deleted file mode 100644 index 69555e440..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images": [ - { - "orientation": "portrait", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "2x", - "size": "640x960", - "idiom": "iphone" - }, - { - "orientation": "portrait", - "extent": "full-screen", - "minimum-system-version": "7.0", - "subtype": "retina4", - "scale": "2x", - "size": "640x1136", - "idiom": "iphone" - }, - { - "orientation": "portrait", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "1x", - "size": "768x1024", - "idiom": "ipad" - }, - { - "orientation": "landscape", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "1x", - "size": "1024x768", - "idiom": "ipad" - }, - { - "orientation": "portrait", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "2x", - "size": "1536x2048", - "idiom": "ipad" - }, - { - "orientation": "landscape", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "2x", - "size": "2048x1536", - "idiom": "ipad" - } - ], - "properties": {}, - "info": { - "version": 1, - "author": "" - } -} \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/UnoPlatformSample.Mobile.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/UnoPlatformSample.Mobile.csproj deleted file mode 100644 index 8d64964e5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/UnoPlatformSample.Mobile.csproj +++ /dev/null @@ -1,84 +0,0 @@ - - - net7.0-ios;net7.0-android;net7.0-maccatalyst - true - Exe - - UnoPlatformSample - - com.companyname.UnoPlatformSample - 2D6DC555-C58F-43A5-ACD9-3FECEB6ED3FD - - 1.0 - 1 - - Android\AndroidManifest.xml - - - - - True - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(MtouchExtraArgs) --setenv=MONO_GC_PARAMS=soft-heap-limit=512m,nursery-size=64m,evacuation-threshold=66,major=marksweep,concurrent-sweep - - $(MtouchExtraArgs) --registrar:static - - $(MtouchExtraArgs) --marshal-objectivec-exceptions:disable - - - - - - $(MtouchExtraArgs) --setenv=MONO_GC_PARAMS=soft-heap-limit=512m,nursery-size=64m,evacuation-threshold=66,major=marksweep,concurrent-sweep - - $(MtouchExtraArgs) --registrar:static - - $(MtouchExtraArgs) --marshal-objectivec-exceptions:disable - - false - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Entitlements.plist b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Entitlements.plist deleted file mode 100644 index 24c310368..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Entitlements.plist +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Info.plist b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Info.plist deleted file mode 100644 index 056bbaf6e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Info.plist +++ /dev/null @@ -1,51 +0,0 @@ - - - - - LSRequiresIPhoneOS - - UIDeviceFamily - - 1 - 2 - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - UILaunchImageMinimumOSVersion - 9.0 - UILaunchImageOrientation - Portrait - UILaunchImageSize - {320, 568} - XSAppIconAssets - Media.xcassets/iconapp.appiconset - UIApplicationSupportsIndirectInputEvents - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Main.iOS.cs b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Main.iOS.cs deleted file mode 100644 index 6549466b2..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Main.iOS.cs +++ /dev/null @@ -1,35 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using UIKit; - -namespace UnoPlatformSample.iOS; -public class EntryPoint -{ - // This is the main entry point of the application. - public static void Main(string[] args) - { - // if you want to use a different Application Delegate class from "AppDelegate" - // you can specify it here. - UIApplication.Main(args, null, typeof(AppHead)); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json deleted file mode 100644 index 69555e440..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images": [ - { - "orientation": "portrait", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "2x", - "size": "640x960", - "idiom": "iphone" - }, - { - "orientation": "portrait", - "extent": "full-screen", - "minimum-system-version": "7.0", - "subtype": "retina4", - "scale": "2x", - "size": "640x1136", - "idiom": "iphone" - }, - { - "orientation": "portrait", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "1x", - "size": "768x1024", - "idiom": "ipad" - }, - { - "orientation": "landscape", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "1x", - "size": "1024x768", - "idiom": "ipad" - }, - { - "orientation": "portrait", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "2x", - "size": "1536x2048", - "idiom": "ipad" - }, - { - "orientation": "landscape", - "extent": "full-screen", - "minimum-system-version": "7.0", - "scale": "2x", - "size": "2048x1536", - "idiom": "ipad" - } - ], - "properties": {}, - "info": { - "version": 1, - "author": "" - } -} \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/Apis/WeatherForecastApi.cs b/samples/UnoPlatformSample/UnoPlatformSample.Server/Apis/WeatherForecastApi.cs deleted file mode 100644 index 0d3881966..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Server/Apis/WeatherForecastApi.cs +++ /dev/null @@ -1,69 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Server.Apis; - -public static class WeatherForecastApi -{ - private const string Tag = "Weather"; - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - public static WebApplication MapWeatherApi(this WebApplication app) - { - app.MapGet("/api/weatherforecast", GetForecast) - .WithTags(Tag) - .WithName(nameof(GetForecast)); - return app; - } - - /// - /// Creates a make believe weather forecast for the next 5 days. - /// - /// - /// A fake 5 day forecast - /// A 5 Day Forecast - /// Weather Forecast returned - [Produces("application/json")] - [ProducesResponseType(typeof(IEnumerable), 200)] - private static IEnumerable GetForecast(ILoggerFactory loggerFactory) - { - var logger = loggerFactory.CreateLogger(nameof(WeatherForecastApi)); - logger.LogDebug("Getting Weather Forecast."); - - return Enumerable.Range(1, 5).Select(index => - new WeatherForecast( - DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - Random.Shared.Next(-20, 55), - Summaries[Random.Shared.Next(Summaries.Length)] - ) - ) - .Select(x => - { - logger.LogInformation("Weather forecast for {Date} is a {Summary} {TemperatureC}°C", x.Date, x.Summary, x.TemperatureC); - return x; - }) - .ToArray(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/GlobalUsings.cs b/samples/UnoPlatformSample/UnoPlatformSample.Server/GlobalUsings.cs deleted file mode 100644 index e57e9b3a4..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Server/GlobalUsings.cs +++ /dev/null @@ -1,25 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -global using Microsoft.AspNetCore.Mvc; -global using UnoPlatformSample.DataContracts; -global using UnoPlatformSample.Server.Apis; diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/Program.cs b/samples/UnoPlatformSample/UnoPlatformSample.Server/Program.cs deleted file mode 100644 index 50bffc72c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Server/Program.cs +++ /dev/null @@ -1,80 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using Uno.Wasm.Bootstrap.Server; -using UnoPlatformSample.DataContracts.Serialization; - -try -{ - var builder = WebApplication.CreateBuilder(args); - - // Configure the JsonOptions to use the generated WeatherForecastContext - builder.Services.Configure(options => - options.JsonSerializerOptions.AddContext()); - // Configure the RouteOptions to use lowercase URLs - builder.Services.Configure(options => - options.LowercaseUrls = true); - - // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle - builder.Services.AddEndpointsApiExplorer(); - builder.Services.AddSwaggerGen(c => - { - // Include XML comments for all included assemblies - Directory.EnumerateFiles(AppContext.BaseDirectory, "*.xml") - .Where(x => x.Contains("UnoPlatformSample") - && File.Exists(Path.Combine( - AppContext.BaseDirectory, - $"{Path.GetFileNameWithoutExtension(x)}.dll"))) - .ToList() - .ForEach(path => c.IncludeXmlComments(path)); - }); - - var app = builder.Build(); - - // Configure the HTTP request pipeline. - if (app.Environment.IsDevelopment()) - { - app.UseSwagger(); - app.UseSwaggerUI(); - } - - app.UseHttpsRedirection(); - - app.UseUnoFrameworkFiles(); - app.MapFallbackToFile("index.html"); - - app.MapWeatherApi(); - app.UseStaticFiles(); - - await app.RunAsync(); -} -catch (Exception ex) -{ - Console.Error.WriteLine("Application terminated unexpectedly"); - Console.Error.WriteLine(ex); -#if DEBUG - if (System.Diagnostics.Debugger.IsAttached) - { - System.Diagnostics.Debugger.Break(); - } -#endif -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/Properties/launchSettings.json b/samples/UnoPlatformSample/UnoPlatformSample.Server/Properties/launchSettings.json deleted file mode 100644 index 935d7a031..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Server/Properties/launchSettings.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:5000", - "sslPort": 5001 - } - }, - "profiles": { - "UnoPlatformSample.Server": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "", - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:5000;http://localhost:5001", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "", - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/UnoPlatformSample.Server.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Server/UnoPlatformSample.Server.csproj deleted file mode 100644 index f00aa6fc8..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Server/UnoPlatformSample.Server.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net7.0 - true - $(NoWarn);CS1591 - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.Development.json b/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.Development.json deleted file mode 100644 index 0c208ae91..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.json b/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.json deleted file mode 100644 index 10f68b8c8..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Package.appxmanifest b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Package.appxmanifest deleted file mode 100644 index 2e73cee57..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Package.appxmanifest +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - UnoPlatformSample - UnoPlatformSample - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Program.cs b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Program.cs deleted file mode 100644 index 6a527fc20..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Program.cs +++ /dev/null @@ -1,42 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System; -using GLib; -using Uno.UI.Runtime.Skia; - -namespace UnoPlatformSample.Skia.Gtk; -public class Program -{ - public static void Main(string[] args) - { - ExceptionManager.UnhandledException += delegate (UnhandledExceptionArgs expArgs) - { - Console.WriteLine("GLIB UNHANDLED EXCEPTION" + expArgs.ExceptionObject.ToString()); - expArgs.ExitApplication = true; - }; - - var host = new GtkHost(() => new AppHead(), args); - - host.Run(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj deleted file mode 100644 index 8c6a03ef3..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj +++ /dev/null @@ -1,40 +0,0 @@ - - - WinExe - Exe - net7.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/app.manifest b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/app.manifest deleted file mode 100644 index 2d1299be8..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/app.manifest +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PerMonitor - true - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Tests/AppInfoTests.cs b/samples/UnoPlatformSample/UnoPlatformSample.Tests/AppInfoTests.cs deleted file mode 100644 index 141cc0c30..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Tests/AppInfoTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Tests; - -public class AppInfoTests -{ - [SetUp] - public void Setup() - { - } - - [Test] - public void AppInfoCreation() - { - var appInfo = new AppConfig { Title = "Test" }; - - appInfo.Should().NotBeNull(); - appInfo.Title.Should().Be("Test"); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Tests/GlobalUsings.cs b/samples/UnoPlatformSample/UnoPlatformSample.Tests/GlobalUsings.cs deleted file mode 100644 index dcb9f8b4d..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Tests/GlobalUsings.cs +++ /dev/null @@ -1,25 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -global using FluentAssertions; -global using NUnit.Framework; -global using UnoPlatformSample.Business.Models; diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Tests/UnoPlatformSample.Tests.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Tests/UnoPlatformSample.Tests.csproj deleted file mode 100644 index d0c062f5c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Tests/UnoPlatformSample.Tests.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net7.0 - false - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/Constants.cs b/samples/UnoPlatformSample/UnoPlatformSample.UITests/Constants.cs deleted file mode 100644 index 1eacfc437..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.UITests/Constants.cs +++ /dev/null @@ -1,33 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.UITests; - -public class Constants -{ - public readonly static string WebAssemblyDefaultUri = "http://localhost:5000/"; - public readonly static string iOSAppName = "com.companyname.UnoPlatformSample"; - public readonly static string AndroidAppName = "com.companyname.UnoPlatformSample"; - public readonly static string iOSDeviceNameOrId = "iPad Pro (12.9-inch) (3rd generation)"; - - public readonly static Platform CurrentPlatform = Platform.Browser; -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/Given_MainPage.cs b/samples/UnoPlatformSample/UnoPlatformSample.UITests/Given_MainPage.cs deleted file mode 100644 index 1302b6680..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.UITests/Given_MainPage.cs +++ /dev/null @@ -1,43 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.UITests; - -public class Given_MainPage : TestBase -{ - [Test] - public void When_SmokeTest() - { - // NOTICE - // To run UITests, Run the WASM target without debugger. Note - // the port that is being used and update the Constants.cs file - // in the UITests project with the correct port number. - - // Query for the SecondPageButton and then tap it - Query xamlButton = q => q.All().Marked("SecondPageButton"); - App.WaitForElement(xamlButton); - App.Tap(xamlButton); - - // Take a screenshot and add it to the test results - TakeScreenshot("After tapped"); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/GlobalUsings.cs b/samples/UnoPlatformSample/UnoPlatformSample.UITests/GlobalUsings.cs deleted file mode 100644 index 7791f8d00..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.UITests/GlobalUsings.cs +++ /dev/null @@ -1,28 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -global using NUnit.Framework; -global using Uno.UITest; -global using Uno.UITest.Helpers.Queries; -global using Uno.UITests.Helpers; -global using Query = System.Func; - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/TestBase.cs b/samples/UnoPlatformSample/UnoPlatformSample.UITests/TestBase.cs deleted file mode 100644 index 425431c36..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.UITests/TestBase.cs +++ /dev/null @@ -1,102 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.UITests; - -public class TestBase -{ - private IApp? _app; - - static TestBase() - { - AppInitializer.TestEnvironment.AndroidAppName = Constants.AndroidAppName; - AppInitializer.TestEnvironment.WebAssemblyDefaultUri = Constants.WebAssemblyDefaultUri; - AppInitializer.TestEnvironment.iOSAppName = Constants.iOSAppName; - AppInitializer.TestEnvironment.AndroidAppName = Constants.AndroidAppName; - AppInitializer.TestEnvironment.iOSDeviceNameOrId = Constants.iOSDeviceNameOrId; - AppInitializer.TestEnvironment.CurrentPlatform = Constants.CurrentPlatform; - -#if DEBUG - AppInitializer.TestEnvironment.WebAssemblyHeadless = false; -#endif - - // Start the app only once, so the tests runs don't restart it - // and gain some time for the tests. - AppInitializer.ColdStartApp(); - } - - protected IApp App - { - get => _app!; - private set - { - _app = value; - Uno.UITest.Helpers.Queries.Helpers.App = value; - } - } - - [SetUp] - public void SetUpTest() - { - App = AppInitializer.AttachToApp(); - } - - [TearDown] - public void TearDownTest() - { - TakeScreenshot("teardown"); - } - - public FileInfo TakeScreenshot(string stepName) - { - var title = $"{TestContext.CurrentContext.Test.Name}_{stepName}" - .Replace(" ", "_") - .Replace(".", "_"); - - var fileInfo = App.Screenshot(title); - - var fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileInfo.Name); - if (fileNameWithoutExt != title) - { - var destFileName = Path - .Combine(Path.GetDirectoryName(fileInfo.FullName), title + Path.GetExtension(fileInfo.Name)); - - if (File.Exists(destFileName)) - { - File.Delete(destFileName); - } - - File.Move(fileInfo.FullName, destFileName); - - TestContext.AddTestAttachment(destFileName, stepName); - - fileInfo = new FileInfo(destFileName); - } - else - { - TestContext.AddTestAttachment(fileInfo.FullName, stepName); - } - - return fileInfo; - } - -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/UnoPlatformSample.UITests.csproj b/samples/UnoPlatformSample/UnoPlatformSample.UITests/UnoPlatformSample.UITests.csproj deleted file mode 100644 index c8514a734..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.UITests/UnoPlatformSample.UITests.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - net48 - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/LinkerConfig.xml b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/LinkerConfig.xml deleted file mode 100644 index df91b15b8..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/LinkerConfig.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Program.cs b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Program.cs deleted file mode 100644 index b99a57482..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Program.cs +++ /dev/null @@ -1,35 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Wasm; - -public class Program -{ - private static App? _app; - - public static int Main(string[] args) - { - Microsoft.UI.Xaml.Application.Start(_ => _app = new AppHead()); - - return 0; - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Properties/launchSettings.json b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Properties/launchSettings.json deleted file mode 100644 index 68ffba9ec..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Properties/launchSettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:8080", - "sslPort": 0 - } - }, - "profiles": { - "UnoPlatformSample.Wasm": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5000", - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj deleted file mode 100644 index de1950269..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj +++ /dev/null @@ -1,87 +0,0 @@ - - - Exe - net7.0 - $(NoWarn);NU1504;NU1505;NU1701 - - disable - manifest.webmanifest - Properties - - - true - $(DefineConstants);TRACE;DEBUG - portable - true - - false - - - - - - - - - - - True - $(DefineConstants);USE_UITESTS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmCSS/Fonts.css b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmCSS/Fonts.css deleted file mode 100644 index cccf7c8f3..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmCSS/Fonts.css +++ /dev/null @@ -1,28 +0,0 @@ -/** - When adding fonts here, make sure to add them using a base64 data uri, otherwise - fonts loading are delayed, and text may get displayed incorrectly. -*/ - -/* https://github.com/unoplatform/uno/issues/3954 */ -@font-face { - font-family: 'Segoe UI'; - src: local('system-ui'), local('Segoe UI'), local('-apple-system'), local('BlinkMacSystemFont'), local('Inter'), local('Cantarell'), local('Ubuntu'), local('Roboto'), local('Open Sans'), local('Noto Sans'), local('Helvetica Neue'), local('sans-serif'); -} - -@font-face { - font-family: 'Roboto'; - src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Light.ttf) format('truetype'); - font-weight: 300; -} - -@font-face { - font-family: 'Roboto'; - src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Regular.ttf) format('truetype'); - font-weight: 400; -} - -@font-face { - font-family: 'Roboto'; - src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Medium.ttf) format('truetype'); - font-weight: 500; -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmScripts/AppManifest.js b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmScripts/AppManifest.js deleted file mode 100644 index df845f84a..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmScripts/AppManifest.js +++ /dev/null @@ -1,3 +0,0 @@ -var UnoAppManifest = { - displayName: "UnoPlatformSample" -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/manifest.webmanifest b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/manifest.webmanifest deleted file mode 100644 index d6f24a1ac..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/manifest.webmanifest +++ /dev/null @@ -1,10 +0,0 @@ -{ - "background_color": "#ffffff", - "description": "UnoPlatformSample", - "display": "standalone", - "name": "UnoPlatformSample", - "short_name": "UnoPlatformSample", - "start_url": "/index.html", - "theme_color": "#ffffff", - "scope": "/" -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/staticwebapp.config.json b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/staticwebapp.config.json deleted file mode 100644 index 79c1b17c4..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/staticwebapp.config.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "navigationFallback": { - "rewrite": "/index.html", - "exclude": [ - "*.{css,js}", - "*.{png}", - "*.{c,h,wasm,clr,pdb,dat,txt}" - ] - }, - "routes": [ - { - "route": "/package_*", - "headers": { - "cache-control": "public, immutable, max-age=31536000" - } - }, - { - "route": "/*.ttf", - "headers": { - "cache-control": "public, immutable, max-age=31536000" - } - }, - { - "route": "/*", - "headers": { - "cache-control": "must-revalidate, max-age=3600" - } - } - ] -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/web.config b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/web.config deleted file mode 100644 index 8f5a860f5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/web.config +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Package.appxmanifest b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Package.appxmanifest deleted file mode 100644 index 2e73cee57..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Package.appxmanifest +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - UnoPlatformSample - UnoPlatformSample - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Properties/launchsettings.json b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Properties/launchsettings.json deleted file mode 100644 index edd66b1e1..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Properties/launchsettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "profiles": { - "UnoPlatformSample.Windows (Package)": { - "commandName": "MsixPackage" - }, - "UnoPlatformSample.Windows (Unpackaged)": { - "commandName": "Project" - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Resources.lang-en-us.resw b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Resources.lang-en-us.resw deleted file mode 100644 index fad04be56..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Resources.lang-en-us.resw +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Hello World! - - \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/UnoPlatformSample.Windows.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Windows/UnoPlatformSample.Windows.csproj deleted file mode 100644 index 3b1f672be..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Windows/UnoPlatformSample.Windows.csproj +++ /dev/null @@ -1,71 +0,0 @@ - - - WinExe - net7.0-windows10.0.19041.0 - 10.0.18362.0 - UnoWinUIQuickStart - x86;x64;arm64 - win10-x86;win10-x64;win10-arm64 - win10-$(Platform).pubxml - true - true - - - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/app.manifest b/samples/UnoPlatformSample/UnoPlatformSample.Windows/app.manifest deleted file mode 100644 index 0d40013de..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.Windows/app.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - true/PM - PerMonitorV2, PerMonitor - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample.sln b/samples/UnoPlatformSample/UnoPlatformSample.sln deleted file mode 100644 index a96869afc..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample.sln +++ /dev/null @@ -1,296 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.5.33530.505 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample", "UnoPlatformSample\UnoPlatformSample.csproj", "{6787E34A-0543-43B5-AF13-C49E81ECF2CA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.DataContracts", "UnoPlatformSample.DataContracts\UnoPlatformSample.DataContracts.csproj", "{05C90284-4A60-480E-8DF4-59BEBBDF7A88}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C3BAEDDD-EBF5-465A-96E3-919731C1C226}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Tests", "UnoPlatformSample.Tests\UnoPlatformSample.Tests.csproj", "{61DB2817-9F6D-4F3D-8171-B0B698B6E27D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.UITests", "UnoPlatformSample.UITests\UnoPlatformSample.UITests.csproj", "{CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backend", "Backend", "{56E8DD65-197A-4998-A3F9-AFB0809E17A7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Server", "UnoPlatformSample.Server\UnoPlatformSample.Server.csproj", "{DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{878FAD2B-22DE-4A0C-80C7-9C9EBFC4612A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Mobile", "UnoPlatformSample.Mobile\UnoPlatformSample.Mobile.csproj", "{396CB1FB-077C-4E1F-A571-5156E62B9111}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Windows", "UnoPlatformSample.Windows\UnoPlatformSample.Windows.csproj", "{FC803FFA-058E-4B66-B1A6-CE938C4E531F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Wasm", "UnoPlatformSample.Wasm\UnoPlatformSample.Wasm.csproj", "{30F96F54-B08E-4421-8680-5FB7AC8C70EF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Skia.Gtk", "UnoPlatformSample.Skia.Gtk\UnoPlatformSample.Skia.Gtk.csproj", "{E9116FC3-207F-4125-82CF-328544AE3317}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_LiveChartsSource", "_LiveChartsSource", "{9EF18573-A2AA-4F5B-9F56-52C40072721D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore", "..\..\src\LiveChartsCore\LiveChartsCore.csproj", "{BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView", "..\..\src\skiasharp\LiveChartsCore.SkiaSharp\LiveChartsCore.SkiaSharpView.csproj", "{EE9A269D-572E-4060-8147-9D6FFFBD3764}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "..\..\src\skiasharp\LiveChartsCore.SkiaSharpView.Uno.WinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{278A4841-66D1-41BD-A92B-D9E114227FBE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewModelsSamples", "..\ViewModelsSamples\ViewModelsSamples.csproj", "{545C171D-3E5E-454B-9F8A-4D507FF4449C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|arm64 = Debug|arm64 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|arm64 = Release|arm64 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Debug|arm64.ActiveCfg = Debug|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Debug|arm64.Build.0 = Debug|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Debug|x64.ActiveCfg = Debug|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Debug|x64.Build.0 = Debug|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Debug|x86.ActiveCfg = Debug|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Debug|x86.Build.0 = Debug|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Release|Any CPU.Build.0 = Release|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Release|arm64.ActiveCfg = Release|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Release|arm64.Build.0 = Release|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Release|x64.ActiveCfg = Release|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Release|x64.Build.0 = Release|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Release|x86.ActiveCfg = Release|Any CPU - {6787E34A-0543-43B5-AF13-C49E81ECF2CA}.Release|x86.Build.0 = Release|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Debug|Any CPU.Build.0 = Debug|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Debug|arm64.ActiveCfg = Debug|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Debug|arm64.Build.0 = Debug|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Debug|x64.ActiveCfg = Debug|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Debug|x64.Build.0 = Debug|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Debug|x86.ActiveCfg = Debug|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Debug|x86.Build.0 = Debug|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Release|Any CPU.ActiveCfg = Release|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Release|Any CPU.Build.0 = Release|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Release|arm64.ActiveCfg = Release|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Release|arm64.Build.0 = Release|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Release|x64.ActiveCfg = Release|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Release|x64.Build.0 = Release|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Release|x86.ActiveCfg = Release|Any CPU - {05C90284-4A60-480E-8DF4-59BEBBDF7A88}.Release|x86.Build.0 = Release|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Debug|arm64.ActiveCfg = Debug|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Debug|arm64.Build.0 = Debug|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Debug|x64.ActiveCfg = Debug|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Debug|x64.Build.0 = Debug|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Debug|x86.ActiveCfg = Debug|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Debug|x86.Build.0 = Debug|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Release|Any CPU.Build.0 = Release|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Release|arm64.ActiveCfg = Release|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Release|arm64.Build.0 = Release|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Release|x64.ActiveCfg = Release|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Release|x64.Build.0 = Release|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Release|x86.ActiveCfg = Release|Any CPU - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D}.Release|x86.Build.0 = Release|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Debug|arm64.ActiveCfg = Debug|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Debug|arm64.Build.0 = Debug|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Debug|x64.ActiveCfg = Debug|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Debug|x64.Build.0 = Debug|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Debug|x86.ActiveCfg = Debug|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Debug|x86.Build.0 = Debug|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Release|Any CPU.Build.0 = Release|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Release|arm64.ActiveCfg = Release|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Release|arm64.Build.0 = Release|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Release|x64.ActiveCfg = Release|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Release|x64.Build.0 = Release|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Release|x86.ActiveCfg = Release|Any CPU - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E}.Release|x86.Build.0 = Release|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Debug|arm64.ActiveCfg = Debug|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Debug|arm64.Build.0 = Debug|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Debug|x64.ActiveCfg = Debug|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Debug|x64.Build.0 = Debug|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Debug|x86.ActiveCfg = Debug|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Debug|x86.Build.0 = Debug|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Release|Any CPU.Build.0 = Release|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Release|arm64.ActiveCfg = Release|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Release|arm64.Build.0 = Release|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Release|x64.ActiveCfg = Release|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Release|x64.Build.0 = Release|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Release|x86.ActiveCfg = Release|Any CPU - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD}.Release|x86.Build.0 = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|Any CPU.Build.0 = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|arm64.ActiveCfg = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|arm64.Build.0 = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|arm64.Deploy.0 = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|x64.ActiveCfg = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|x64.Build.0 = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|x64.Deploy.0 = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|x86.ActiveCfg = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|x86.Build.0 = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Debug|x86.Deploy.0 = Debug|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|Any CPU.ActiveCfg = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|Any CPU.Build.0 = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|Any CPU.Deploy.0 = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|arm64.ActiveCfg = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|arm64.Build.0 = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|arm64.Deploy.0 = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|x64.ActiveCfg = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|x64.Build.0 = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|x64.Deploy.0 = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|x86.ActiveCfg = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|x86.Build.0 = Release|Any CPU - {396CB1FB-077C-4E1F-A571-5156E62B9111}.Release|x86.Deploy.0 = Release|Any CPU - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|Any CPU.ActiveCfg = Debug|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|Any CPU.Build.0 = Debug|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|Any CPU.Deploy.0 = Debug|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|arm64.ActiveCfg = Debug|arm64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|arm64.Build.0 = Debug|arm64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|arm64.Deploy.0 = Debug|arm64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|x64.ActiveCfg = Debug|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|x64.Build.0 = Debug|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|x64.Deploy.0 = Debug|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|x86.ActiveCfg = Debug|x86 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|x86.Build.0 = Debug|x86 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Debug|x86.Deploy.0 = Debug|x86 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|Any CPU.ActiveCfg = Release|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|Any CPU.Build.0 = Release|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|Any CPU.Deploy.0 = Release|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|arm64.ActiveCfg = Release|arm64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|arm64.Build.0 = Release|arm64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|arm64.Deploy.0 = Release|arm64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|x64.ActiveCfg = Release|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|x64.Build.0 = Release|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|x64.Deploy.0 = Release|x64 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|x86.ActiveCfg = Release|x86 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|x86.Build.0 = Release|x86 - {FC803FFA-058E-4B66-B1A6-CE938C4E531F}.Release|x86.Deploy.0 = Release|x86 - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Debug|arm64.ActiveCfg = Debug|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Debug|arm64.Build.0 = Debug|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Debug|x64.ActiveCfg = Debug|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Debug|x64.Build.0 = Debug|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Debug|x86.ActiveCfg = Debug|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Debug|x86.Build.0 = Debug|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Release|Any CPU.Build.0 = Release|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Release|arm64.ActiveCfg = Release|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Release|arm64.Build.0 = Release|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Release|x64.ActiveCfg = Release|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Release|x64.Build.0 = Release|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Release|x86.ActiveCfg = Release|Any CPU - {30F96F54-B08E-4421-8680-5FB7AC8C70EF}.Release|x86.Build.0 = Release|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Debug|arm64.ActiveCfg = Debug|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Debug|arm64.Build.0 = Debug|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Debug|x64.ActiveCfg = Debug|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Debug|x64.Build.0 = Debug|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Debug|x86.ActiveCfg = Debug|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Debug|x86.Build.0 = Debug|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Release|Any CPU.Build.0 = Release|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Release|arm64.ActiveCfg = Release|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Release|arm64.Build.0 = Release|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Release|x64.ActiveCfg = Release|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Release|x64.Build.0 = Release|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Release|x86.ActiveCfg = Release|Any CPU - {E9116FC3-207F-4125-82CF-328544AE3317}.Release|x86.Build.0 = Release|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Debug|arm64.ActiveCfg = Debug|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Debug|arm64.Build.0 = Debug|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Debug|x64.ActiveCfg = Debug|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Debug|x64.Build.0 = Debug|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Debug|x86.ActiveCfg = Debug|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Debug|x86.Build.0 = Debug|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Release|Any CPU.Build.0 = Release|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Release|arm64.ActiveCfg = Release|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Release|arm64.Build.0 = Release|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Release|x64.ActiveCfg = Release|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Release|x64.Build.0 = Release|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Release|x86.ActiveCfg = Release|Any CPU - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C}.Release|x86.Build.0 = Release|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Debug|arm64.ActiveCfg = Debug|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Debug|arm64.Build.0 = Debug|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Debug|x64.ActiveCfg = Debug|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Debug|x64.Build.0 = Debug|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Debug|x86.ActiveCfg = Debug|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Debug|x86.Build.0 = Debug|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Release|Any CPU.Build.0 = Release|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Release|arm64.ActiveCfg = Release|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Release|arm64.Build.0 = Release|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Release|x64.ActiveCfg = Release|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Release|x64.Build.0 = Release|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Release|x86.ActiveCfg = Release|Any CPU - {EE9A269D-572E-4060-8147-9D6FFFBD3764}.Release|x86.Build.0 = Release|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Debug|arm64.ActiveCfg = Debug|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Debug|arm64.Build.0 = Debug|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Debug|x64.ActiveCfg = Debug|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Debug|x64.Build.0 = Debug|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Debug|x86.ActiveCfg = Debug|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Debug|x86.Build.0 = Debug|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Release|Any CPU.Build.0 = Release|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Release|arm64.ActiveCfg = Release|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Release|arm64.Build.0 = Release|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Release|x64.ActiveCfg = Release|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Release|x64.Build.0 = Release|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Release|x86.ActiveCfg = Release|Any CPU - {278A4841-66D1-41BD-A92B-D9E114227FBE}.Release|x86.Build.0 = Release|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Debug|arm64.ActiveCfg = Debug|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Debug|arm64.Build.0 = Debug|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Debug|x64.ActiveCfg = Debug|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Debug|x64.Build.0 = Debug|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Debug|x86.ActiveCfg = Debug|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Debug|x86.Build.0 = Debug|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Release|Any CPU.Build.0 = Release|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Release|arm64.ActiveCfg = Release|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Release|arm64.Build.0 = Release|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Release|x64.ActiveCfg = Release|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Release|x64.Build.0 = Release|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Release|x86.ActiveCfg = Release|Any CPU - {545C171D-3E5E-454B-9F8A-4D507FF4449C}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {61DB2817-9F6D-4F3D-8171-B0B698B6E27D} = {C3BAEDDD-EBF5-465A-96E3-919731C1C226} - {CF1ECCFA-BF76-4AF1-B099-EA9EBFBE897E} = {C3BAEDDD-EBF5-465A-96E3-919731C1C226} - {DC45FF8C-77DE-4410-92AC-9BBDA8CFB9CD} = {56E8DD65-197A-4998-A3F9-AFB0809E17A7} - {396CB1FB-077C-4E1F-A571-5156E62B9111} = {878FAD2B-22DE-4A0C-80C7-9C9EBFC4612A} - {FC803FFA-058E-4B66-B1A6-CE938C4E531F} = {878FAD2B-22DE-4A0C-80C7-9C9EBFC4612A} - {30F96F54-B08E-4421-8680-5FB7AC8C70EF} = {878FAD2B-22DE-4A0C-80C7-9C9EBFC4612A} - {E9116FC3-207F-4125-82CF-328544AE3317} = {878FAD2B-22DE-4A0C-80C7-9C9EBFC4612A} - {BA7C8629-718F-4E3B-AC89-B442DD5F4F2C} = {9EF18573-A2AA-4F5B-9F56-52C40072721D} - {EE9A269D-572E-4060-8147-9D6FFFBD3764} = {9EF18573-A2AA-4F5B-9F56-52C40072721D} - {278A4841-66D1-41BD-A92B-D9E114227FBE} = {9EF18573-A2AA-4F5B-9F56-52C40072721D} - {545C171D-3E5E-454B-9F8A-4D507FF4449C} = {9EF18573-A2AA-4F5B-9F56-52C40072721D} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {08AAE7D4-A9D9-4066-ABAC-6EB3A2B1CABF} - EndGlobalSection -EndGlobal diff --git a/samples/UnoPlatformSample/UnoPlatformSample/App.cs b/samples/UnoPlatformSample/UnoPlatformSample/App.cs deleted file mode 100644 index 2238978a5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/App.cs +++ /dev/null @@ -1,108 +0,0 @@ -using LiveChartsCore; // mark -using LiveChartsCore.SkiaSharpView; // mark -using SkiaSharp; // mark - -namespace UnoPlatformSample; - -public class App : Application -{ - private static Window? _window; - public static IHost? Host { get; private set; } - - public record City(string Name, double Population); - - protected async override void OnLaunched(LaunchActivatedEventArgs args) - { - LiveCharts.Configure(config => // mark - config // mark - // you can override the theme - // .AddDarkTheme() // mark - - // In case you need a non-Latin based font, you must register a typeface for SkiaSharp - //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('汉')) // <- Chinese // mark - //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('あ')) // <- Japanese // mark - //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('헬')) // <- Korean // mark - //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('Ж')) // <- Russian // mark - - //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('أ')) // <- Arabic // mark - //.UseRightToLeftSettings() // Enables right to left tooltips // mark - - // finally register your own mappers - // you can learn more about mappers at: - // https://livecharts.dev/docs/{{ platform }}/{{ version }}/Overview.Mappers - .HasMap((city, point) => // mark - { // mark - // here we use the index as X, and the population as Y // mark - point.Coordinate = new(point.Index, city.Population); // mark - }) // mark - // .HasMap( .... ) // mark - // .HasMap( .... ) // mark - ); // mark - - var builder = this.CreateBuilder(args) - - // Add navigation support for toolkit controls such as TabBar and NavigationView - .UseToolkitNavigation() - .Configure(host => host -#if DEBUG - // Switch to Development environment when running in DEBUG - .UseEnvironment(Environments.Development) -#endif - .UseLogging(configure: (context, logBuilder) => - { - // Configure log levels for different categories of logging - logBuilder.SetMinimumLevel( - context.HostingEnvironment.IsDevelopment() ? - LogLevel.Information : - LogLevel.Warning); - }, enableUnoLogging: true) - .UseConfiguration(configure: configBuilder => - configBuilder - .EmbeddedSource() - .Section() - ) - // Enable localization (see appsettings.json for supported languages) - .UseLocalization() - // Register Json serializers (ISerializer and ISerializer) - .UseSerialization((context, services) => services - .AddContentSerializer(context) - .AddJsonTypeInfo(WeatherForecastContext.Default.IImmutableListWeatherForecast)) - .UseHttp((context, services) => services - // Register HttpClient -#if DEBUG - // DelegatingHandler will be automatically injected into Refit Client - .AddTransient() -#endif - .AddSingleton() - .AddRefitClient(context)) - .ConfigureServices((context, services) => - { - // TODO: Register your services - //services.AddSingleton(); - }) - .UseNavigation(ReactiveViewModelMappings.ViewModelMappings, RegisterRoutes) - ); - _window = builder.Window; - - Host = await builder.NavigateAsync(); - } - - private static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes) - { - views.Register( - new ViewMap(ViewModel: typeof(ShellModel)), - new ViewMap(), - new DataViewMap() - ); - - routes.Register( - new RouteMap("", View: views.FindByViewModel(), - Nested: new RouteMap[] - { - new RouteMap("Main", View: views.FindByViewModel()), - new RouteMap("Second", View: views.FindByViewModel()), - } - ) - ); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/AppResources.xaml b/samples/UnoPlatformSample/UnoPlatformSample/AppResources.xaml deleted file mode 100644 index 4e8f2bad1..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/AppResources.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Assets/Icons/back.svg b/samples/UnoPlatformSample/UnoPlatformSample/Assets/Icons/back.svg deleted file mode 100644 index bcd7851b9..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Assets/Icons/back.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Assets/SharedAssets.md b/samples/UnoPlatformSample/UnoPlatformSample/Assets/SharedAssets.md deleted file mode 100644 index 6d84997f1..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Assets/SharedAssets.md +++ /dev/null @@ -1,34 +0,0 @@ -See documentation about assets here : https://github.com/unoplatform/uno/blob/master/doc/articles/features/working-with-assets.md - -# Here is a cheat sheet: - -1. Add the image file to the `Assets` directory of a shared project. -2. Set the build action to `Content`. -3. (Recommended) Provide an asset for various scales/dpi - -## Examples - -``` -\Assets\Images\logo.scale-100.png -\Assets\Images\logo.scale-200.png -\Assets\Images\logo.scale-400.png - -\Assets\Images\scale-100\logo.png -\Assets\Images\scale-200\logo.png -\Assets\Images\scale-400\logo.png -``` - -## Table of scales - -| Scale | UWP | iOS | Android | -|-------|:-----------:|:--------:|:-------:| -| `100` | scale-100 | @1x | mdpi | -| `125` | scale-125 | N/A | N/A | -| `150` | scale-150 | N/A | hdpi | -| `200` | scale-200 | @2x | xhdpi | -| `300` | scale-300 | @3x | xxhdpi | -| `400` | scale-400 | N/A | xxxhdpi | - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/AppConfig.cs b/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/AppConfig.cs deleted file mode 100644 index 403791b1e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/AppConfig.cs +++ /dev/null @@ -1,28 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Business.Models; - -public record AppConfig -{ - public string? Title { get; init; } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/Entity.cs b/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/Entity.cs deleted file mode 100644 index 661c4f5ae..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/Entity.cs +++ /dev/null @@ -1,25 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Business.Models; - -public record Entity(string Name); diff --git a/samples/UnoPlatformSample/UnoPlatformSample/GlobalSuppressions.cs b/samples/UnoPlatformSample/UnoPlatformSample/GlobalSuppressions.cs deleted file mode 100644 index cb30c04b6..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/GlobalSuppressions.cs +++ /dev/null @@ -1,8 +0,0 @@ -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("Style", "IDE0005:Using directive is unnecessary.", Justification = "")] diff --git a/samples/UnoPlatformSample/UnoPlatformSample/GlobalUsings.cs b/samples/UnoPlatformSample/UnoPlatformSample/GlobalUsings.cs deleted file mode 100644 index 33afee5d4..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/GlobalUsings.cs +++ /dev/null @@ -1,56 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -global using System; -global using System.Collections.Generic; -global using System.Collections.Immutable; -global using System.Linq; -global using System.Net.Http; -global using System.Threading; -global using System.Threading.Tasks; -global using Microsoft.Extensions.DependencyInjection; -global using Microsoft.Extensions.Hosting; -global using Microsoft.Extensions.Localization; -global using Microsoft.Extensions.Logging; -global using Microsoft.Extensions.Options; -global using Microsoft.UI.Xaml; -global using Microsoft.UI.Xaml.Controls; -global using Microsoft.UI.Xaml.Media; -global using Microsoft.UI.Xaml.Navigation; -global using Refit; -global using Uno.Extensions; -global using Uno.Extensions.Configuration; -global using Uno.Extensions.Hosting; -global using Uno.Extensions.Http; -global using Uno.Extensions.Localization; -global using Uno.Extensions.Logging; -global using Uno.Extensions.Navigation; -global using UnoPlatformSample.Business.Models; -global using UnoPlatformSample.DataContracts; -global using UnoPlatformSample.DataContracts.Serialization; -global using UnoPlatformSample.Infrastructure; -global using UnoPlatformSample.Presentation; -global using UnoPlatformSample.Services.Caching; -global using UnoPlatformSample.Services.Endpoints; -global using Windows.ApplicationModel; -global using Application = Microsoft.UI.Xaml.Application; -global using ApplicationExecutionState = Windows.ApplicationModel.Activation.ApplicationExecutionState; diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Infrastructure/DebugHandler.cs b/samples/UnoPlatformSample/UnoPlatformSample/Infrastructure/DebugHandler.cs deleted file mode 100644 index b53ea6c96..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Infrastructure/DebugHandler.cs +++ /dev/null @@ -1,62 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Infrastructure; - -internal class DebugHttpHandler : DelegatingHandler -{ - private readonly ILogger _logger; - public DebugHttpHandler(ILogger logger, HttpMessageHandler? innerHandler = null) - : base(innerHandler ?? new HttpClientHandler()) - { - _logger = logger; - } - - protected async override Task SendAsync( - HttpRequestMessage request, - CancellationToken cancellationToken) - { - var response = await base.SendAsync(request, cancellationToken); -#if DEBUG - if(!response.IsSuccessStatusCode) - { - _logger.LogDebugMessage("Unsuccessful API Call"); - if(request.RequestUri is not null) - _logger.LogDebugMessage($"{request.RequestUri} ({request.Method})"); - foreach((var key, var values) in request.Headers.ToDictionary(x => x.Key, x => string.Join(", ", x.Value))) - { - _logger.LogDebugMessage($"{key}: {values}"); - } - - var content = request.Content is not null ? await request.Content.ReadAsStringAsync() : null; - if(!string.IsNullOrEmpty(content)) - { - _logger.LogDebugMessage(content); - } - - // Uncomment to automatically break when an API call fails while debugging - // System.Diagnostics.Debugger.Break(); - } -#endif - return response; - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml deleted file mode 100644 index 3a5bf2843..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml.cs deleted file mode 100644 index 2585ad11a..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.ColorsAndPosition; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml deleted file mode 100644 index 50740a29e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml.cs deleted file mode 100644 index 382f6287c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.Crosshairs; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml deleted file mode 100644 index de2c8c0fb..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml.cs deleted file mode 100644 index 9dcfdf2bd..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.CustomSeparatorsInterval; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml deleted file mode 100644 index cd2820427..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml.cs deleted file mode 100644 index aa27bc19b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.DateTimeScaled; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml deleted file mode 100644 index 0386813ba..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml.cs deleted file mode 100644 index a534423db..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.LabelsFormat; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml deleted file mode 100644 index a8e50d907..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml.cs deleted file mode 100644 index 9f544f827..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.LabelsFormat2; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml deleted file mode 100644 index ae2efe8c5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml.cs deleted file mode 100644 index 9709b4f8b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.LabelsRotation; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml deleted file mode 100644 index d95e9cb7c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml.cs deleted file mode 100644 index 47912b900..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.Logarithmic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml deleted file mode 100644 index cdb504641..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml.cs deleted file mode 100644 index f6b9b2806..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.Multiple; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml deleted file mode 100644 index 014b06401..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml.cs deleted file mode 100644 index 72d9a2e45..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.NamedLabels; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml deleted file mode 100644 index a90e90180..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml.cs deleted file mode 100644 index 996d8fb51..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.Paging; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml deleted file mode 100644 index 7f5030cef..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml.cs deleted file mode 100644 index dd75d46ac..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.Shared; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml deleted file mode 100644 index a07527a77..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml.cs deleted file mode 100644 index 83e4fad4d..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.Style; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml deleted file mode 100644 index 98fdba24c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml.cs deleted file mode 100644 index 76238c8a2..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Axes.TimeSpanScaled; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml deleted file mode 100644 index 0c18fafae..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml.cs deleted file mode 100644 index 130129262..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading.Tasks; -using ViewModelsSamples.Bars.AutoUpdate; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace UnoWinUISample.Bars.AutoUpdate; - -public sealed partial class View : UserControl -{ - private bool? _isStreaming = false; - - public View() - { - InitializeComponent(); - } - - private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) - { - var vm = (ViewModel)DataContext; - _isStreaming = _isStreaming is null ? true : !_isStreaming; - - while (_isStreaming.Value) - { - vm.RemoveItem(); - vm.AddItem(); - await Task.Delay(1000); - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml deleted file mode 100644 index a60aeab48..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml.cs deleted file mode 100644 index 9814f8f92..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Bars.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml deleted file mode 100644 index ca6e7d101..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml.cs deleted file mode 100644 index 6888aee9d..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Bars.Custom; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml deleted file mode 100644 index ad7fecf0d..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml.cs deleted file mode 100644 index 4b624be0b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Bars.DelayedAnimation; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml deleted file mode 100644 index 6b9c4031e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml.cs deleted file mode 100644 index 453c9e62f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Bars.Layered; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml deleted file mode 100644 index 3357be175..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml.cs deleted file mode 100644 index bd81a4a60..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Threading.Tasks; -using ViewModelsSamples.Bars.Race; -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Bars.Race; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml deleted file mode 100644 index 8b6d8291f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml.cs deleted file mode 100644 index f80d92559..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Bars.RowsWithLabels; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml deleted file mode 100644 index 49049ed7b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml.cs deleted file mode 100644 index e9fb41343..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Bars.Spacing; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml deleted file mode 100644 index 70c639b25..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml.cs deleted file mode 100644 index 4aa121455..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Bars.WithBackground; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml deleted file mode 100644 index 0dedab919..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml.cs deleted file mode 100644 index 995e859d6..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Box.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml deleted file mode 100644 index 10c989a13..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml.cs deleted file mode 100644 index fd33321a9..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Design.LinearGradients; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml deleted file mode 100644 index 210d8ddc7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml.cs deleted file mode 100644 index a0e4c0132..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Design.RadialGradients; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml deleted file mode 100644 index cff20ab25..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml.cs deleted file mode 100644 index 475957f9f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Design.StrokeDashArray; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml deleted file mode 100644 index e56953ced..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml.cs deleted file mode 100644 index 77f197bd0..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Error.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml deleted file mode 100644 index 4ed1ac64b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml.cs deleted file mode 100644 index 10e774723..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml.cs +++ /dev/null @@ -1,14 +0,0 @@ -using LiveChartsCore.Defaults; -using LiveChartsCore.Drawing; -using ViewModelsSamples.Events.AddPointOnClick; -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Events.AddPointOnClick; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml deleted file mode 100644 index ef5a12eb8..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml.cs deleted file mode 100644 index 202da84a5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Events.Cartesian; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml deleted file mode 100644 index dab2c85c5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml.cs deleted file mode 100644 index 66473207e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using LiveChartsCore.Kernel; -using LiveChartsCore.Kernel.Sketches; -using ViewModelsSamples.Events.Pie; -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Events.Pie; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } - - private void Chart_DataPointerDown( - IChartView chart, - IEnumerable points) - { - // notice in the chart event we are not able to use strongly typed points - // but we can cast the point.Context.DataSource to the actual type. - - foreach (var point in points) - { - if (point.Context.DataSource is City city) - { - Trace.WriteLine($"[chart.dataPointerDownEvent] clicked on {city.Name}"); - continue; - } - - if (point.Context.DataSource is int integer) - { - Trace.WriteLine($"[chart.dataPointerDownEvent] clicked on number {integer}"); - continue; - } - - // handle more possible types here... - // if (point.Context.DataSource is Foo foo) - // { - // ... - // } - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml deleted file mode 100644 index f4b4b11f9..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml.cs deleted file mode 100644 index 07fc232c9..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using LiveChartsCore.Kernel; -using LiveChartsCore.Kernel.Sketches; -using ViewModelsSamples.Events.Polar; -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Events.Polar; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } - - private void Chart_DataPointerDown( - IChartView chart, - IEnumerable points) - { - // notice in the chart event we are not able to use strongly typed points - // but we can cast the point.Context.DataSource to the actual type. - - foreach (var point in points) - { - if (point.Context.DataSource is City city) - { - Trace.WriteLine($"[chart.dataPointerDownEvent] clicked on {city.Name}"); - continue; - } - - if (point.Context.DataSource is int integer) - { - Trace.WriteLine($"[chart.dataPointerDownEvent] clicked on number {integer}"); - continue; - } - - // handle more possible types here... - // if (point.Context.DataSource is Foo foo) - // { - // ... - // } - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml deleted file mode 100644 index cd532f5b7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml.cs deleted file mode 100644 index 02d3a1db7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Financial.BasicCandlesticks; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml deleted file mode 100644 index 402e6b815..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml.cs deleted file mode 100644 index 0eee21d83..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.Animations; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml deleted file mode 100644 index a3df71a7f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml.cs deleted file mode 100644 index cedc0af70..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml.cs +++ /dev/null @@ -1,47 +0,0 @@ -using LiveChartsCore.SkiaSharpView.SKCharts; -using LiveChartsCore.SkiaSharpView.WinUI; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml; - -namespace UnoWinUISample.General.ChartToImage; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - - // in this case, when the view is loaded // mark - // we render our chart controls as images // mark - Loaded += View_Loaded; - } - - private void View_Loaded(object? sender, RoutedEventArgs e) - { - CreateImageFromCartesianControl(); - CreateImageFromPieControl(); - CreateImageFromGeoControl(); - } - - private void CreateImageFromCartesianControl() - { - // you can take any chart in the UI, and build an image from it // mark - var chartControl = (CartesianChart)FindName("cartesianChart"); - var skChart = new SKCartesianChart(chartControl) { Width = 900, Height = 600, }; - skChart.SaveImage("CartesianImageFromControl.png"); - } - - private void CreateImageFromPieControl() - { - var chartControl = (PieChart)FindName("pieChart"); - var skChart = new SKPieChart(chartControl) { Width = 900, Height = 600, }; - skChart.SaveImage("PieImageFromControl.png"); - } - - private void CreateImageFromGeoControl() - { - var chartControl = (GeoMap)FindName("geoChart"); - var skChart = new SKGeoMap(chartControl) { Width = 900, Height = 600, }; - skChart.SaveImage("MapImageFromControl.png"); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml deleted file mode 100644 index 44750fe66..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml.cs deleted file mode 100644 index 72c778e46..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.ConditionalDraw; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml deleted file mode 100644 index dd4704f63..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml.cs deleted file mode 100644 index 100bec92e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.Legends; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml deleted file mode 100644 index b800ce314..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml.cs deleted file mode 100644 index 74f447e96..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.MapPoints; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml deleted file mode 100644 index 63e6c7ae3..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml.cs deleted file mode 100644 index 8a33b1903..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.MultiThreading; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml deleted file mode 100644 index 63dd5bb17..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml.cs deleted file mode 100644 index c951bc0f0..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Controls; -using ViewModelsSamples.General.MultiThreading2; - -namespace UnoWinUISample.General.MultiThreading2; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - - var vm = new ViewModel(InvokeOnUIThread); - DataContext = vm; - } - - // this method takes another function as an argument. - // the idea is that we are invoking the passed action in the UI thread - // but the UI framework will let the view model how to do this. - // we will pass the InvokeOnUIThread method to our view model so the view model knows how - // to invoke an action in the UI thred. - private void InvokeOnUIThread(Action action) - { - // the InvokeOnUIThread method provided by livecharts is a simple helper class - // that handles the invoke in the multiple platforms Uno supports. - LiveChartsCore.SkiaSharpView.WinUI.Helpers.UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml deleted file mode 100644 index 6e3999d8a..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml.cs deleted file mode 100644 index 7f743809e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.NullPoints; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml deleted file mode 100644 index 81292eef7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml.cs deleted file mode 100644 index 812b3032c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.RealTime; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml deleted file mode 100644 index cfcdb7802..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml.cs deleted file mode 100644 index 49c12bf2a..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UnoWinUISample.General.Scrollable; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml deleted file mode 100644 index 654dbbdd8..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml.cs deleted file mode 100644 index 72d4f3d2f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.Sections; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml deleted file mode 100644 index ead9a91ee..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml.cs deleted file mode 100644 index 8c86ab55c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.Sections2; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml deleted file mode 100644 index 6c4faf2db..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml.cs deleted file mode 100644 index 23e27e5be..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.TemplatedLegends; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml deleted file mode 100644 index 6fd79eb8f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml.cs deleted file mode 100644 index be1fa82ec..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.TemplatedTooltips; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml deleted file mode 100644 index 23750d091..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml.cs deleted file mode 100644 index da0cee428..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.Tooltips; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml deleted file mode 100644 index 96dc3bada..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml.cs deleted file mode 100644 index 5846c6a95..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.UserDefinedTypes; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml deleted file mode 100644 index 4f205423e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml.cs deleted file mode 100644 index 091505e2f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.Visibility; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml deleted file mode 100644 index b14e2a269..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml.cs deleted file mode 100644 index 70fbc4805..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.General.VisualElements; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml deleted file mode 100644 index ccf290044..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml.cs deleted file mode 100644 index f65ca9c22..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Heat.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml deleted file mode 100644 index 4f1b434e7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml.cs deleted file mode 100644 index 204558cdf..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Lines.Area; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml deleted file mode 100644 index 5e97d3ad2..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml.cs deleted file mode 100644 index 4ab4830b9..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading.Tasks; -using ViewModelsSamples.Lines.AutoUpdate; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace UnoWinUISample.Lines.AutoUpdate; - -public sealed partial class View : UserControl -{ - private bool? _isStreaming = false; - - public View() - { - InitializeComponent(); - } - - private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) - { - var vm = (ViewModel)DataContext; - _isStreaming = _isStreaming is null ? true : !_isStreaming; - - while (_isStreaming.Value) - { - vm.RemoveItem(); - vm.AddItem(); - await Task.Delay(1000); - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml deleted file mode 100644 index 336ac534e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml.cs deleted file mode 100644 index e60788268..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Lines.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml deleted file mode 100644 index 04102680d..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml.cs deleted file mode 100644 index a706c4b1e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Lines.Custom; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml deleted file mode 100644 index 716afc5d7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml.cs deleted file mode 100644 index 57e15db64..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Lines.Padding; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml deleted file mode 100644 index 0004eb1fb..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml.cs deleted file mode 100644 index 76c3b305e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Lines.Properties; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml deleted file mode 100644 index a34fbfe01..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml.cs deleted file mode 100644 index 644e25c34..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Lines.Straight; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml deleted file mode 100644 index 4e49c0153..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml.cs deleted file mode 100644 index 43ae2ae10..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Lines.XY; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml deleted file mode 100644 index beca3d2e8..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml.cs deleted file mode 100644 index a7c447fed..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Lines.Zoom; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml deleted file mode 100644 index 2d01358c1..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml.cs deleted file mode 100644 index f73ab2343..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Maps.World; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml deleted file mode 100644 index bd9b9fc16..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml.cs deleted file mode 100644 index 63f36b09a..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.AngularGauge; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml deleted file mode 100644 index 616779106..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml.cs deleted file mode 100644 index 3dd01163f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading.Tasks; -using ViewModelsSamples.Pies.AutoUpdate; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace UnoWinUISample.Pies.AutoUpdate; - -public sealed partial class View : UserControl -{ - private bool? _isStreaming = false; - - public View() - { - InitializeComponent(); - } - - private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) - { - var vm = (ViewModel)DataContext; - _isStreaming = _isStreaming is null ? true : !_isStreaming; - - while (_isStreaming.Value) - { - vm.RemoveSeries(); - vm.AddSeries(); - await Task.Delay(1000); - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml deleted file mode 100644 index be0b554cb..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml.cs deleted file mode 100644 index 957fb5c4c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml deleted file mode 100644 index c8a511287..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml.cs deleted file mode 100644 index ca7b6cd68..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Custom; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml deleted file mode 100644 index e6c8b6dd2..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml.cs deleted file mode 100644 index 73b80aaca..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Doughnut; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml deleted file mode 100644 index 7f6eca655..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml.cs deleted file mode 100644 index 7fb79cd4c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Gauge; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml deleted file mode 100644 index 2f974973f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml.cs deleted file mode 100644 index a83518db2..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Gauge1; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml deleted file mode 100644 index 206a9416f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml.cs deleted file mode 100644 index 4db271ddf..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Gauge2; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml deleted file mode 100644 index e96131aaf..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml.cs deleted file mode 100644 index fa14dbf57..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Gauge3; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml deleted file mode 100644 index 0fb248dd3..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml.cs deleted file mode 100644 index a3747cdf3..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Gauge4; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml deleted file mode 100644 index 2cfaed47f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml.cs deleted file mode 100644 index 4931fdb55..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Gauge5; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml deleted file mode 100644 index e2a0cf0c6..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml.cs deleted file mode 100644 index c411740b3..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Gauges; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml deleted file mode 100644 index 320397055..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml.cs deleted file mode 100644 index 4663131a7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.NightingaleRose; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml deleted file mode 100644 index 56a3318a4..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml.cs deleted file mode 100644 index 49072dcf6..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using LiveChartsCore.SkiaSharpView.Painting; -using Windows.UI; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Media; - -namespace UnoWinUISample.Pies.Processing; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} - -public class PaintTaskToBrushConverter : IValueConverter -{ - public object Convert(object value, Type targetType, object parameter, string language) - { - var solidColor = (SolidColorPaint)value; - return new SolidColorBrush( - Color.FromArgb( - solidColor.Color.Alpha, - solidColor.Color.Red, - solidColor.Color.Green, - solidColor.Color.Blue)); - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml deleted file mode 100644 index 6092b802a..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml.cs deleted file mode 100644 index 1622dd189..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Pies.Pushout; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml deleted file mode 100644 index 649f54cd6..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml.cs deleted file mode 100644 index 5dea8731c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Polar.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml deleted file mode 100644 index f2ddbc6a5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml.cs deleted file mode 100644 index 3a34b930c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Polar.Coordinates; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml deleted file mode 100644 index 49cdc1464..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml.cs deleted file mode 100644 index 0dcffd9c3..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Polar.RadialArea; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml deleted file mode 100644 index 9ea73c216..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml.cs deleted file mode 100644 index 19e8d55e5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading.Tasks; -using ViewModelsSamples.Scatter.AutoUpdate; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace UnoWinUISample.Scatter.AutoUpdate; - -public sealed partial class View : UserControl -{ - private bool? _isStreaming = false; - - public View() - { - InitializeComponent(); - } - - private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) - { - var vm = (ViewModel)DataContext; - _isStreaming = _isStreaming is null ? true : !_isStreaming; - - while (_isStreaming.Value) - { - vm.RemoveItem(); - vm.AddItem(); - await Task.Delay(1000); - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml deleted file mode 100644 index 202047df5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml.cs deleted file mode 100644 index 8b6154f1b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Scatter.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml deleted file mode 100644 index 6fe5b96cc..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml.cs deleted file mode 100644 index 26b6685d7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Scatter.Bubbles; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml deleted file mode 100644 index 56115d380..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml.cs deleted file mode 100644 index f3b209098..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Scatter.Custom; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml deleted file mode 100644 index e58dbac74..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml.cs deleted file mode 100644 index ad8eeb104..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StackedArea.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml deleted file mode 100644 index d23e9113b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml.cs deleted file mode 100644 index 254e2dca4..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StackedArea.StepArea; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml deleted file mode 100644 index 8f4a82e34..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml.cs deleted file mode 100644 index 59d6480e5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StackedBars.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml deleted file mode 100644 index 962a535f0..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml.cs deleted file mode 100644 index bf5bf2b96..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StackedBars.Groups; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml deleted file mode 100644 index 8aefb074d..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml.cs deleted file mode 100644 index 0fc725ad0..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StepLines.Area; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml deleted file mode 100644 index 85f01518c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml.cs deleted file mode 100644 index b986705d4..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading.Tasks; -using ViewModelsSamples.StepLines.AutoUpdate; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace UnoWinUISample.StepLines.AutoUpdate; - -public sealed partial class View : UserControl -{ - private bool? _isStreaming = false; - - public View() - { - InitializeComponent(); - } - - private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) - { - var vm = (ViewModel)DataContext; - _isStreaming = _isStreaming is null ? true : !_isStreaming; - - while (_isStreaming.Value) - { - vm.RemoveItem(); - vm.AddItem(); - await Task.Delay(1000); - } - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml deleted file mode 100644 index 17a07e6b0..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml.cs deleted file mode 100644 index fa410e0ea..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StepLines.Basic; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml deleted file mode 100644 index 404a264c8..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml.cs deleted file mode 100644 index 97c9c0af3..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StepLines.Custom; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml deleted file mode 100644 index 7df82c379..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml.cs deleted file mode 100644 index 1b1a47669..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StepLines.Properties; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml deleted file mode 100644 index db1ed013b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml.cs deleted file mode 100644 index 1992367e9..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.StepLines.Zoom; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml deleted file mode 100644 index 97002bb1f..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml.cs deleted file mode 100644 index 6d66bd20c..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.Test.Dispose; - -public sealed partial class UserControl1 : UserControl -{ - public UserControl1() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml deleted file mode 100644 index 9538c14db..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml.cs deleted file mode 100644 index fa732a267..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace UnoWinUISample.Test.Dispose; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - - // the event is not attached using xaml? - button.AddHandler(PointerPressedEvent, new PointerEventHandler(Button_PointerPressed2), true); - } - - private void Button_PointerPressed2(object sender, PointerRoutedEventArgs e) - { - content.Content = new UserControl1(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml deleted file mode 100644 index 9eb50de17..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml.cs deleted file mode 100644 index 512b032bc..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.VisualTest.DataTemplate; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml deleted file mode 100644 index 01d47ca71..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml.cs deleted file mode 100644 index 22d994098..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.VisualTest.ReattachVisual; - -public sealed partial class View : UserControl -{ - private bool _isInVisualTree = true; - - public View() - { - InitializeComponent(); - } - - private void Button_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) - { - if (_isInVisualTree) - { - _ = parent.Children.Remove(chart); - _ = parent.Children.Remove(pieChart); - _ = parent.Children.Remove(polarChart); - _isInVisualTree = false; - return; - } - - parent.Children.Add(chart); - parent.Children.Add(pieChart); - parent.Children.Add(polarChart); - _isInVisualTree = true; - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml deleted file mode 100644 index 86f62d929..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml.cs deleted file mode 100644 index 58f4dda9b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.VisualTest.Tabs; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml deleted file mode 100644 index 7efad4b39..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml.cs deleted file mode 100644 index b58e98f3d..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace UnoWinUISample.VisualTest.TwoChartsOneSeries; - -public sealed partial class View : UserControl -{ - public View() - { - InitializeComponent(); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainModel.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainModel.cs deleted file mode 100644 index 5bb48cc89..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainModel.cs +++ /dev/null @@ -1,50 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using LiveChartsCore; -using LiveChartsCore.SkiaSharpView; -using Uno.Extensions.Reactive; - -namespace UnoPlatformSample.Presentation; -public partial record MainModel -{ - public string? Title { get; } - - public IState Name { get; } - - public MainModel( - INavigator navigator, - IStringLocalizer localizer) - { - _navigator = navigator; - Title = $"Main - {localizer["ApplicationName"]}"; - Name = State.Value(this, () => string.Empty); - } - - public async Task GoToSecond() - { - var name = await Name; - await _navigator.NavigateViewModelAsync(this, data: new Entity(name!)); - } - - private INavigator _navigator; -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml deleted file mode 100644 index d7ead8fd7..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs deleted file mode 100644 index 51fb0e5b5..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs +++ /dev/null @@ -1,54 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using Microsoft.UI.Xaml.Input; - -namespace UnoPlatformSample.Presentation; - -public sealed partial class MainPage : Page -{ - public MainPage() - { - this.InitializeComponent(); - - Samples = ViewModelsSamples.Index.Samples; - grid.DataContext = this; - - LoadSample("Design/LinearGradients"); - - } - - public string[] Samples { get; set; } - - private void Border_PointerPressed(object sender, PointerRoutedEventArgs e) - { - var ctx = (string)((FrameworkElement)sender).DataContext; - LoadSample(ctx); - } - - private void LoadSample(string route) - { - route = route.Replace('/', '.'); - var t = Type.GetType($"UnoWinUISample.{route}.View") ?? throw new FileNotFoundException($"{route} not found!"); - content.Content = Activator.CreateInstance(t); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondModel.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondModel.cs deleted file mode 100644 index 4c7be2989..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondModel.cs +++ /dev/null @@ -1,27 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Presentation; - -public partial record SecondModel(Entity Entity) -{ -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml deleted file mode 100644 index 034fc5d36..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml.cs deleted file mode 100644 index 8200ed04b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml.cs +++ /dev/null @@ -1,32 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Presentation; - -public sealed partial class SecondPage : Page -{ - public SecondPage() - { - this.InitializeComponent(); - } -} - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml deleted file mode 100644 index 200b62c1e..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml.cs deleted file mode 100644 index 75beed4b1..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml.cs +++ /dev/null @@ -1,34 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using Uno.Toolkit.UI; - -namespace UnoPlatformSample.Presentation; -public sealed partial class Shell : UserControl, IContentControlProvider -{ - public Shell() - { - this.InitializeComponent(); - } - - public ContentControl ContentControl => Splash; -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/ShellModel.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/ShellModel.cs deleted file mode 100644 index 4b7faea76..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/ShellModel.cs +++ /dev/null @@ -1,40 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace UnoPlatformSample.Presentation; - -public class ShellModel -{ - private INavigator Navigator { get; } - - public ShellModel(INavigator navigator) - { - Navigator = navigator; - - _ = Start(); - } - - public async Task Start() - { - await Navigator.NavigateViewModelAsync(this); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/IWeatherCache.cs b/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/IWeatherCache.cs deleted file mode 100644 index 487236daf..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/IWeatherCache.cs +++ /dev/null @@ -1,30 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System.Collections.Immutable; -using UnoPlatformSample.DataContracts; - -namespace UnoPlatformSample.Services.Caching; -public interface IWeatherCache -{ - ValueTask> GetForecast(CancellationToken token); -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/WeatherCache.cs b/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/WeatherCache.cs deleted file mode 100644 index a673d6c24..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/WeatherCache.cs +++ /dev/null @@ -1,100 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using Uno.Extensions.Serialization; -using Windows.Networking.Connectivity; -using Windows.Storage; - -namespace UnoPlatformSample.Services.Caching; -public sealed class WeatherCache : IWeatherCache -{ - private readonly IApiClient _api; - private readonly ISerializer _serializer; - private readonly ILogger _logger; - - public WeatherCache(IApiClient api, ISerializer serializer, ILogger logger) - { - _api = api; - _serializer = serializer; - _logger = logger; - } - - private bool IsConnected => NetworkInformation.GetInternetConnectionProfile().GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess; - - public async ValueTask> GetForecast(CancellationToken token) - { - var weatherText = await GetCachedWeather(); - if (!string.IsNullOrWhiteSpace(weatherText)) - { - return _serializer.FromString>(weatherText); - } - - if (!IsConnected) - { - _logger.LogWarning("App is offline and cannot connect to the API."); - throw new Exception("No internet connection"); - } - - var response = await _api.GetWeather(token); - - if (response.IsSuccessStatusCode && response.Content is not null) - { - var weather = response.Content; - await Save(weather, token); - return weather; - } - else if (response.Error is not null) - { - _logger.LogError(response.Error, "An error occurred while retrieving the latest Forecast."); - throw response.Error; - } - else - { - return ImmutableArray.Empty; - } - } - - private async ValueTask GetFile(CreationCollisionOption option) => - await ApplicationData.Current.TemporaryFolder.CreateFileAsync("weather.json", option); - - private async ValueTask GetCachedWeather() - { - var file = await GetFile(CreationCollisionOption.OpenIfExists); - var properties = await file.GetBasicPropertiesAsync(); - - // Reuse latest cache file if offline - // or if the file is less than 5 minutes old - if (IsConnected || DateTimeOffset.Now.AddMinutes(-5) > properties.DateModified) - { - return null; - } - - return await File.ReadAllTextAsync(file.Path); - } - - private async ValueTask Save(IImmutableList weather, CancellationToken token) - { - var weatherText = _serializer.ToString(weather); - var file = await GetFile(CreationCollisionOption.ReplaceExisting); - await File.WriteAllTextAsync(file.Path, weatherText); - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Services/Endpoints/IApiClient.cs b/samples/UnoPlatformSample/UnoPlatformSample/Services/Endpoints/IApiClient.cs deleted file mode 100644 index 645f5b973..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Services/Endpoints/IApiClient.cs +++ /dev/null @@ -1,32 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System.Collections.Immutable; -using UnoPlatformSample.DataContracts; - -namespace UnoPlatformSample.Services.Endpoints; -[Headers("Content-Type: application/json")] -public interface IApiClient -{ - [Get("/api/weatherforecast")] - Task>> GetWeather(CancellationToken cancellationToken = default); -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Strings/en/Resources.resw b/samples/UnoPlatformSample/UnoPlatformSample/Strings/en/Resources.resw deleted file mode 100644 index e54534102..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Strings/en/Resources.resw +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - UnoPlatformSample-en - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Strings/es/Resources.resw b/samples/UnoPlatformSample/UnoPlatformSample/Strings/es/Resources.resw deleted file mode 100644 index 98c09cd2d..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Strings/es/Resources.resw +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - UnoPlatformSample-es - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Strings/fr/Resources.resw b/samples/UnoPlatformSample/UnoPlatformSample/Strings/fr/Resources.resw deleted file mode 100644 index 9d7f9b16b..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Strings/fr/Resources.resw +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - UnoPlatformSample-fr - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Strings/pt-BR/Resources.resw b/samples/UnoPlatformSample/UnoPlatformSample/Strings/pt-BR/Resources.resw deleted file mode 100644 index e1ce2edb1..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Strings/pt-BR/Resources.resw +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - UnoPlatformSample-pt-BR - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.xaml deleted file mode 100644 index 2710b2912..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.xaml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - #5946D2 - #FFFFFF - #E5DEFF - #170065 - #6B4EA2 - #FFFFFF - #EBDDFF - #1F182B - #0061A4 - #FFFFFF - #CFE4FF - #001D36 - #B3261E - #F9DEDC - #FFFFFF - #410E0B - #FCFBFF - #1C1B1F - #FFFFFF - #1C1B1F - #F3EFF5 - #8B8494 - #79747E - #F4EFF4 - #313033 - #C8BFFF - #5946D2 - #C9C5D0 - - - #C7BFFF - #2A009F - #4129BA - #E4DFFF - #CDC2DC - #332D41 - #433C52 - #EBDDFF - #9FCAFF - #003258 - #00497E - #D1E4FF - #FFB4AB - #93000A - #690005 - #FFDAD6 - #1C1B1F - #E5E1E6 - #302D38 - #E6E1E5 - #47464F - #C9C5D0 - #928F99 - #1C1B1F - #E6E1E5 - #2A009F - #544794 - #57545D - - - \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.zip b/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.zip deleted file mode 100644 index dfac0a9d85660e9b75825dc27909894e739d47c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5848 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 GqyGTNNW$m< diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Styles/MaterialFontsOverride.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Styles/MaterialFontsOverride.xaml deleted file mode 100644 index 385d65953..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/Styles/MaterialFontsOverride.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - ms-appx:///Uno.Fonts.Roboto/Fonts/Roboto-Light.ttf#Roboto - ms-appx:///Uno.Fonts.Roboto/Fonts/Roboto-Medium.ttf#Roboto - ms-appx:///Uno.Fonts.Roboto/Fonts/Roboto-Regular.ttf#Roboto - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj b/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj deleted file mode 100644 index 728d8b3e4..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj +++ /dev/null @@ -1,79 +0,0 @@ - - - $(TargetFrameworks);net7.0-windows10.0.19041 - $(TargetFrameworks);net7.0;net7.0-ios;net7.0-android;net7.0-maccatalyst - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %(Filename) - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/appsettings.development.json b/samples/UnoPlatformSample/UnoPlatformSample/appsettings.development.json deleted file mode 100644 index 39c881c36..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/appsettings.development.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "AppConfig": { - "Title": "UnoPlatformSample - Dev" - }, - "ApiClient": { - "Url": "https://localhost:5001", - "UseNativeHandler": true - } -} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/appsettings.json b/samples/UnoPlatformSample/UnoPlatformSample/appsettings.json deleted file mode 100644 index 0e21252d4..000000000 --- a/samples/UnoPlatformSample/UnoPlatformSample/appsettings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "AppConfig": { - "Title": "UnoPlatformSample" - }, - "ApiClient": { - "UseNativeHandler": true - }, - "LocalizationConfiguration": { - "Cultures": [ - "es", - "fr", - "pt-BR", - "en" - ] - } -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/AssemblyInfo.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/AssemblyInfo.cs deleted file mode 100644 index 9f5a39c7a..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/AssemblyInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System.Runtime.CompilerServices; -#if !DEBUG -using System.Reflection; - -[assembly: AssemblyKeyFile("./../../../LiveCharts.snk")] -[assembly: InternalsVisibleTo("LiveChartsCore.BackersPackage, PublicKey=0024000004800000940000000602000000240000525341310004000001000100d53791eaa0d98b405ca858f39169be6af36ceb7a1bca3ca76c6905fd22fddf8c5e4ef2778a5d7a77ad12f08da711fecfc44795c7923739a2acac946b3f1719a6dfc238695bc69cf5d959b3fb6bc4d18d57a97ff8ed897e6b22a6b8155401ee368d77431e74178104b4adca73520b058b9be28d4ec129beb54871778167afa5ce")] -#else -[assembly: InternalsVisibleTo("LiveChartsCore.BackersPackage")] -#endif - diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml deleted file mode 100644 index 41bcfbc4a..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs deleted file mode 100644 index f6601147c..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs +++ /dev/null @@ -1,947 +0,0 @@ - -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Windows.Input; -using LiveChartsCore.Drawing; -using LiveChartsCore.Kernel; -using LiveChartsCore.Kernel.Events; -using LiveChartsCore.Kernel.Sketches; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.SkiaSharpView.Drawing; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using LiveChartsCore.SkiaSharpView.WinUI.Helpers; -using LiveChartsCore.SkiaSharpView.Painting; -using Microsoft.UI.Input; -using LiveChartsCore.VisualElements; -using System.Linq; -using LiveChartsCore.SkiaSharpView.SKCharts; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace LiveChartsCore.SkiaSharpView.WinUI; - -/// -public sealed partial class CartesianChart : UserControl, ICartesianChartView -{ - #region fields - - private Chart? _core; - private MotionCanvas? _motionCanvas; - private readonly CollectionDeepObserver _seriesObserver; - private readonly CollectionDeepObserver _xObserver; - private readonly CollectionDeepObserver _yObserver; - private readonly CollectionDeepObserver> _sectionsObserver; - private readonly CollectionDeepObserver> _visualsObserver; - private DateTime _panLocketUntil; - - #endregion - - /// - /// Initializes a new instance of the class. - /// - public CartesianChart() - { - LiveCharts.Configure(config => config.UseDefaults()); - - InitializeComponent(); - - _seriesObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - _xObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - _yObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - _sectionsObserver = new CollectionDeepObserver>( - OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - _visualsObserver = new CollectionDeepObserver>( - OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - - Loaded += OnLoaded; - Unloaded += OnUnloaded; - - SetValue(XAxesProperty, new ObservableCollection() - { - LiveCharts.DefaultSettings.GetProvider().GetDefaultCartesianAxis() - }); - SetValue(YAxesProperty, new ObservableCollection() - { - LiveCharts.DefaultSettings.GetProvider().GetDefaultCartesianAxis() - }); - SetValue(SeriesProperty, new ObservableCollection()); - SetValue(SectionsProperty, new ObservableCollection>()); - SetValue(VisualElementsProperty, new ObservableCollection>()); - SetValue(SyncContextProperty, new object()); - } - - #region dependency properties - - /// - /// The title property. - /// - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register( - nameof(Title), typeof(VisualElement), typeof(CartesianChart), new PropertyMetadata(null)); - - /// - /// The series property. - /// - public static readonly DependencyProperty SeriesProperty = - DependencyProperty.Register( - nameof(Series), typeof(IEnumerable), typeof(CartesianChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (CartesianChart)o; - var seriesObserver = chart._seriesObserver; - seriesObserver?.Dispose((IEnumerable)args.OldValue); - seriesObserver?.Initialize((IEnumerable)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The x axes property - /// - public static readonly DependencyProperty XAxesProperty = - DependencyProperty.Register( - nameof(XAxes), typeof(IEnumerable), typeof(CartesianChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (CartesianChart)o; - var observer = chart._xObserver; - observer?.Dispose((IEnumerable)args.OldValue); - observer?.Initialize((IEnumerable)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The y axes property - /// - public static readonly DependencyProperty YAxesProperty = - DependencyProperty.Register( - nameof(YAxes), typeof(IEnumerable), typeof(CartesianChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (CartesianChart)o; - var observer = chart._yObserver; - observer?.Dispose((IEnumerable)args.OldValue); - observer?.Initialize((IEnumerable)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The sections property - /// - public static readonly DependencyProperty SectionsProperty = - DependencyProperty.Register( - nameof(Sections), typeof(IEnumerable>), typeof(CartesianChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (CartesianChart)o; - var observer = chart._sectionsObserver; - observer?.Dispose((IEnumerable>)args.OldValue); - observer?.Initialize((IEnumerable>)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The visual elements property - /// - public static readonly DependencyProperty VisualElementsProperty = - DependencyProperty.Register( - nameof(VisualElements), typeof(IEnumerable>), typeof(CartesianChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (CartesianChart)o; - var observer = chart._visualsObserver; - observer?.Dispose((IEnumerable>)args.OldValue); - observer?.Initialize((IEnumerable>)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The sync context property - /// - public static readonly DependencyProperty SyncContextProperty = - DependencyProperty.Register( - nameof(SyncContext), typeof(object), typeof(CartesianChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (CartesianChart)o; - if (chart._motionCanvas != null) chart.CoreCanvas.Sync = args.NewValue; - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The zoom mode property - /// - public static readonly DependencyProperty DrawMarginFrameProperty = - DependencyProperty.Register( - nameof(DrawMarginFrame), typeof(DrawMarginFrame), typeof(CartesianChart), new PropertyMetadata(null)); - - /// - /// The zoom mode property - /// - public static readonly DependencyProperty ZoomModeProperty = - DependencyProperty.Register( - nameof(ZoomMode), typeof(ZoomAndPanMode), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.ZoomMode)); - - /// - /// The zooming speed property - /// - public static readonly DependencyProperty ZoomingSpeedProperty = - DependencyProperty.Register( - nameof(ZoomingSpeed), typeof(double), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.ZoomSpeed)); - - /// - /// The tool tip finding strategy property - /// - public static readonly DependencyProperty TooltipFindingStrategyProperty = - DependencyProperty.Register( - nameof(TooltipFindingStrategy), typeof(TooltipFindingStrategy), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipFindingStrategy, OnDependencyPropertyChanged)); - - /// - /// The draw margin property - /// - public static readonly DependencyProperty DrawMarginProperty = - DependencyProperty.Register( - nameof(DrawMargin), typeof(Margin), typeof(CartesianChart), new PropertyMetadata(null, OnDependencyPropertyChanged)); - - /// - /// The animations speed property - /// - public static readonly DependencyProperty AnimationsSpeedProperty = - DependencyProperty.Register( - nameof(AnimationsSpeed), typeof(TimeSpan), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.AnimationsSpeed, OnDependencyPropertyChanged)); - - /// - /// The easing function property - /// - public static readonly DependencyProperty EasingFunctionProperty = - DependencyProperty.Register( - nameof(EasingFunction), typeof(Func), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.EasingFunction, OnDependencyPropertyChanged)); - - /// - /// The legend position property - /// - public static readonly DependencyProperty LegendPositionProperty = - DependencyProperty.Register( - nameof(LegendPosition), typeof(LegendPosition), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendPosition, OnDependencyPropertyChanged)); - - /// - /// The legend background paint property - /// - public static readonly DependencyProperty LegendBackgroundPaintProperty = - DependencyProperty.Register( - nameof(LegendBackgroundPaint), typeof(IPaint), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendBackgroundPaint, OnDependencyPropertyChanged)); - - /// - /// The legend text paint property - /// - public static readonly DependencyProperty LegendTextPaintProperty = - DependencyProperty.Register( - nameof(LegendTextPaint), typeof(IPaint), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextPaint, OnDependencyPropertyChanged)); - - /// - /// The legend text size property - /// - public static readonly DependencyProperty LegendTextSizeProperty = - DependencyProperty.Register( - nameof(LegendTextSize), typeof(double?), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextSize, OnDependencyPropertyChanged)); - - /// - /// The tool tip position property - /// - public static readonly DependencyProperty TooltipPositionProperty = - DependencyProperty.Register( - nameof(TooltipPosition), typeof(TooltipPosition), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipPosition, OnDependencyPropertyChanged)); - - /// - /// The tooltip background paint property - /// - public static readonly DependencyProperty TooltipBackgroundPaintProperty = - DependencyProperty.Register( - nameof(TooltipBackgroundPaint), typeof(IPaint), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipBackgroundPaint, OnDependencyPropertyChanged)); - - /// - /// The tooltip text paint property - /// - public static readonly DependencyProperty TooltipTextPaintProperty = - DependencyProperty.Register( - nameof(TooltipTextPaint), typeof(IPaint), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextPaint, OnDependencyPropertyChanged)); - - /// - /// The tooltip text size property - /// - public static readonly DependencyProperty TooltipTextSizeProperty = - DependencyProperty.Register( - nameof(TooltipTextSize), typeof(double?), typeof(CartesianChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextSize, OnDependencyPropertyChanged)); - - /// - /// The update started command. - /// - public static readonly DependencyProperty UpdateStartedCommandProperty = - DependencyProperty.Register( - nameof(UpdateStartedCommand), typeof(ICommand), typeof(CartesianChart), - new PropertyMetadata(null)); - - /// - /// The pointer pressed command. - /// - public static readonly DependencyProperty PointerPressedCommandProperty = - DependencyProperty.Register( - nameof(PointerPressedCommand), typeof(ICommand), typeof(CartesianChart), - new PropertyMetadata(null)); - - /// - /// The pointer released command. - /// - public static readonly DependencyProperty PointerReleasedCommandProperty = - DependencyProperty.Register( - nameof(PointerReleasedCommand), typeof(ICommand), typeof(CartesianChart), - new PropertyMetadata(null)); - - /// - /// The pointer move command. - /// - public static readonly DependencyProperty PointerMoveCommandProperty = - DependencyProperty.Register( - nameof(PointerMoveCommand), typeof(ICommand), typeof(CartesianChart), - new PropertyMetadata(null)); - - /// - /// The data pointer down command property - /// - public static readonly DependencyProperty DataPointerDownCommandProperty = - DependencyProperty.Register( - nameof(DataPointerDownCommand), typeof(ICommand), typeof(CartesianChart), new PropertyMetadata(null)); - - /// - /// The chart point pointer down command property - /// - public static readonly DependencyProperty ChartPointPointerDownCommandProperty = - DependencyProperty.Register( - nameof(ChartPointPointerDownCommand), typeof(ICommand), typeof(CartesianChart), new PropertyMetadata(null)); - - /// - /// The chart point pointer down command property - /// - public static readonly DependencyProperty VisualElementsPointerDownCommandProperty = - DependencyProperty.Register( - nameof(VisualElementsPointerDownCommand), typeof(ICommand), typeof(CartesianChart), new PropertyMetadata(null)); - - #endregion - - #region events - - /// - public event ChartEventHandler? Measuring; - - /// - public event ChartEventHandler? UpdateStarted; - - /// - public event ChartEventHandler? UpdateFinished; - - /// - public event ChartPointsHandler? DataPointerDown; - - /// - public event ChartPointHandler? ChartPointPointerDown; - - /// - public event VisualElementsHandler? VisualElementsPointerDown; - - #endregion - - #region properties - - /// - bool IChartView.DesignerMode => Windows.ApplicationModel.DesignMode.DesignModeEnabled; - - /// - public IChart CoreChart => _core ?? throw new Exception("Core not set yet."); - - /// - public object SyncContext - { - get => GetValue(SyncContextProperty); - set => SetValue(SyncContextProperty, value); - } - - LvcColor IChartView.BackColor - { - get => Background is not SolidColorBrush b - ? new LvcColor() - : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); - set => SetValue(BackgroundProperty, new SolidColorBrush(Windows.UI.Color.FromArgb(value.A, value.R, value.G, value.B))); - } - - /// - public Margin DrawMargin - { - get => (Margin)GetValue(DrawMarginProperty); - set => SetValue(DrawMarginProperty, value); - } - - Margin? IChartView.DrawMargin - { - get => DrawMargin; - set => SetValue(DrawMarginProperty, value); - } - - LvcSize IChartView.ControlSize => _motionCanvas == null - ? throw new Exception("Canvas not found") - : new LvcSize { Width = (float)_motionCanvas.ActualWidth, Height = (float)_motionCanvas.ActualHeight }; - - /// - public MotionCanvas CoreCanvas => _motionCanvas == null ? throw new Exception("Canvas not found") : _motionCanvas.CanvasCore; - - CartesianChart ICartesianChartView.Core => - _core == null ? throw new Exception("core not found") : (CartesianChart)_core; - - /// - public VisualElement? Title - { - get => (VisualElement?)GetValue(TitleProperty); - set => SetValue(TitleProperty, value); - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty); - set => SetValue(SeriesProperty, value); - } - - /// - public IEnumerable XAxes - { - get => (IEnumerable)GetValue(XAxesProperty); - set => SetValue(XAxesProperty, value); - } - - /// - public IEnumerable YAxes - { - get => (IEnumerable)GetValue(YAxesProperty); - set => SetValue(YAxesProperty, value); - } - - /// - public IEnumerable> Sections - { - get => (IEnumerable>)GetValue(SectionsProperty); - set => SetValue(SectionsProperty, value); - } - - /// - public IEnumerable> VisualElements - { - get => (IEnumerable>)GetValue(VisualElementsProperty); - set => SetValue(VisualElementsProperty, value); - } - - /// - public DrawMarginFrame? DrawMarginFrame - { - get => (DrawMarginFrame)GetValue(DrawMarginFrameProperty); - set => SetValue(DrawMarginFrameProperty, value); - } - - /// - public ZoomAndPanMode ZoomMode - { - get => (ZoomAndPanMode)GetValue(ZoomModeProperty); - set => SetValue(ZoomModeProperty, value); - } - - ZoomAndPanMode ICartesianChartView.ZoomMode - { - get => ZoomMode; - set => SetValue(ZoomModeProperty, value); - } - - /// - public double ZoomingSpeed - { - get => (double)GetValue(ZoomingSpeedProperty); - set => SetValue(ZoomingSpeedProperty, value); - } - - double ICartesianChartView.ZoomingSpeed - { - get => ZoomingSpeed; - set => SetValue(ZoomingSpeedProperty, value); - } - - /// - public TooltipFindingStrategy TooltipFindingStrategy - { - get => (TooltipFindingStrategy)GetValue(TooltipFindingStrategyProperty); - set => SetValue(TooltipFindingStrategyProperty, value); - } - - /// - public TimeSpan AnimationsSpeed - { - get => (TimeSpan)GetValue(AnimationsSpeedProperty); - set => SetValue(AnimationsSpeedProperty, value); - } - - TimeSpan IChartView.AnimationsSpeed - { - get => AnimationsSpeed; - set => SetValue(AnimationsSpeedProperty, value); - } - - /// - public Func EasingFunction - { - get => (Func)GetValue(EasingFunctionProperty); - set => SetValue(EasingFunctionProperty, value); - } - - Func? IChartView.EasingFunction - { - get => EasingFunction; - set => SetValue(EasingFunctionProperty, value); - } - - /// - public LegendPosition LegendPosition - { - get => (LegendPosition)GetValue(LegendPositionProperty); - set => SetValue(LegendPositionProperty, value); - } - - LegendPosition IChartView.LegendPosition - { - get => LegendPosition; - set => SetValue(LegendPositionProperty, value); - } - - /// - public TooltipPosition TooltipPosition - { - get => (TooltipPosition)GetValue(TooltipPositionProperty); - set => SetValue(TooltipPositionProperty, value); - } - - /// - public IPaint? TooltipBackgroundPaint - { - get => (IPaint?)GetValue(TooltipBackgroundPaintProperty); - set => SetValue(TooltipBackgroundPaintProperty, value); - } - - /// - public IPaint? TooltipTextPaint - { - get => (IPaint?)GetValue(TooltipTextPaintProperty); - set => SetValue(TooltipTextPaintProperty, value); - } - - /// - public double? TooltipTextSize - { - get => (double?)GetValue(TooltipTextSizeProperty); - set => SetValue(TooltipTextSizeProperty, value); - } - - /// - public IChartTooltip? Tooltip { get; set; } = new SKDefaultTooltip(); - - /// - public IPaint? LegendBackgroundPaint - { - get => (IPaint?)GetValue(LegendBackgroundPaintProperty); - set => SetValue(LegendBackgroundPaintProperty, value); - } - - /// - public IPaint? LegendTextPaint - { - get => (IPaint?)GetValue(LegendTextPaintProperty); - set => SetValue(LegendTextPaintProperty, value); - } - - /// - public double? LegendTextSize - { - get => (double?)GetValue(LegendTextSizeProperty); - set => SetValue(LegendTextSizeProperty, value); - } - - /// - public IChartLegend? Legend { get; set; } = new SKDefaultLegend(); - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - public TimeSpan UpdaterThrottler { get; set; } = LiveCharts.DefaultSettings.UpdateThrottlingTimeout; - - /// - /// Gets or sets a command to execute when the chart update started. - /// - public ICommand? UpdateStartedCommand - { - get => (ICommand?)GetValue(UpdateStartedCommandProperty); - set => SetValue(UpdateStartedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer is pressed on the chart. - /// - public ICommand? PointerPressedCommand - { - get => (ICommand?)GetValue(PointerPressedCommandProperty); - set => SetValue(PointerPressedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer is released on the chart. - /// - public ICommand? PointerReleasedCommand - { - get => (ICommand?)GetValue(PointerReleasedCommandProperty); - set => SetValue(PointerReleasedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer moves over the chart. - /// - public ICommand? PointerMoveCommand - { - get => (ICommand?)GetValue(PointerMoveCommandProperty); - set => SetValue(PointerMoveCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a data or data points. - /// - public ICommand DataPointerDownCommand - { - get => (ICommand)GetValue(DataPointerDownCommandProperty); - set => SetValue(DataPointerDownCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a chart point. - /// - public ICommand ChartPointPointerDownCommand - { - get => (ICommand)GetValue(ChartPointPointerDownCommandProperty); - set => SetValue(ChartPointPointerDownCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a chart point. - /// - public ICommand? VisualElementsPointerDownCommand - { - get => (ICommand?)GetValue(VisualElementsPointerDownCommandProperty); - set => SetValue(VisualElementsPointerDownCommandProperty, value); - } - - #endregion - - /// - public double[] ScaleUIPoint(LvcPoint point, int xAxisIndex = 0, int yAxisIndex = 0) - { - if (_core == null) throw new Exception("core not found"); - var cartesianCore = (CartesianChart)_core; - return cartesianCore.ScaleUIPoint(point, xAxisIndex, yAxisIndex); - } - - /// - public LvcPointD ScalePixelsToData(LvcPointD point, int xAxisIndex = 0, int yAxisIndex = 0) - { - if (_core is not CartesianChart cc) throw new Exception("core not found"); - var xScaler = new Scaler(cc.DrawMarginLocation, cc.DrawMarginSize, cc.XAxes[xAxisIndex]); - var yScaler = new Scaler(cc.DrawMarginLocation, cc.DrawMarginSize, cc.YAxes[yAxisIndex]); - - return new LvcPointD { X = xScaler.ToChartValues(point.X), Y = yScaler.ToChartValues(point.Y) }; - } - - /// - public LvcPointD ScaleDataToPixels(LvcPointD point, int xAxisIndex = 0, int yAxisIndex = 0) - { - if (_core is not CartesianChart cc) throw new Exception("core not found"); - - var xScaler = new Scaler(cc.DrawMarginLocation, cc.DrawMarginSize, cc.XAxes[xAxisIndex]); - var yScaler = new Scaler(cc.DrawMarginLocation, cc.DrawMarginSize, cc.YAxes[yAxisIndex]); - - return new LvcPointD { X = xScaler.ToPixels(point.X), Y = yScaler.ToPixels(point.Y) }; - } - - /// - public IEnumerable GetPointsAt(LvcPoint point, TooltipFindingStrategy strategy = TooltipFindingStrategy.Automatic) - { - if (_core is not CartesianChart cc) throw new Exception("core not found"); - - if (strategy == TooltipFindingStrategy.Automatic) - strategy = cc.Series.GetTooltipFindingStrategy(); - - return cc.Series.SelectMany(series => series.FindHitPoints(cc, point, strategy)); - } - - /// - public IEnumerable> GetVisualsAt(LvcPoint point) - { - return _core is not CartesianChart cc - ? throw new Exception("core not found") - : cc.VisualElements.SelectMany(visual => ((VisualElement)visual).IsHitBy(_core, point)); - } - - void IChartView.InvokeOnUIThread(Action action) - { - UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); - } - - private void OnLoaded(object sender, RoutedEventArgs e) - { - var canvas = (MotionCanvas)FindName("motionCanvas"); - - _motionCanvas = canvas; - - if (_core is null) - { - var zoomingSection = new Drawing.Geometries.RectangleGeometry(); - var zoomingSectionPaint = new SolidColorPaint - { - IsFill = true, - Color = new SkiaSharp.SKColor(33, 150, 243, 50), - ZIndex = int.MaxValue - }; - zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); - canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); - - _core = new CartesianChart( - this, config => config.UseDefaults(), canvas.CanvasCore, zoomingSection); - - if (SyncContext != null) - _motionCanvas.CanvasCore.Sync = SyncContext; - - if (_core == null) throw new Exception("Core not found!"); - _core.Measuring += OnCoreMeasuring; - _core.UpdateStarted += OnCoreUpdateStarted; - _core.UpdateFinished += OnCoreUpdateFinished; - - PointerPressed += OnPointerPressed; - PointerMoved += OnPointerMoved; - PointerReleased += OnPointerReleased; - PointerWheelChanged += OnWheelChanged; - PointerExited += OnPointerExited; - - SizeChanged += OnSizeChanged; - - _motionCanvas.Pinched += OnCanvasPinched; - } - - _core.Load(); - _core.Update(); - } - - private void OnDeepCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - _core?.Update(); - } - - private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - _core?.Update(); - } - - private void OnSizeChanged(object? sender, SizeChangedEventArgs e) - { - if (_core == null) throw new Exception("Core not found!"); - _core.Update(); - } - - private void OnCoreUpdateFinished(IChartView chart) - { - UpdateFinished?.Invoke(this); - } - - private void OnCoreUpdateStarted(IChartView chart) - { - if (UpdateStartedCommand is not null) - { - var args = new ChartCommandArgs(this); - if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); - } - - UpdateStarted?.Invoke(this); - } - - private void OnCoreMeasuring(IChartView chart) - { - Measuring?.Invoke(this); - } - - private void OnPointerPressed(object? sender, PointerRoutedEventArgs e) - { - if (e.KeyModifiers > 0) return; - _ = CapturePointer(e.Pointer); - var p = e.GetCurrentPoint(this); - - if (PointerPressedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); - } - - var isRight = false; - if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) - { - var properties = e.GetCurrentPoint(this).Properties; - isRight = properties.IsRightButtonPressed; - } - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); - } - - private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) - { - if (DateTime.Now < _panLocketUntil) return; - - var p = e.GetCurrentPoint(motionCanvas); - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - } - - private void OnPointerReleased(object? sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } - - var isRight = false; - if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) - { - var properties = e.GetCurrentPoint(this).Properties; - isRight = properties.IsRightButtonPressed; - } - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); - ReleasePointerCapture(e.Pointer); - } - - private void OnPointerExited(object? sender, PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - - private void OnWheelChanged(object? sender, PointerRoutedEventArgs e) - { - if (_core == null) throw new Exception("core not found"); - var c = (CartesianChart)_core; - var p = e.GetCurrentPoint(this); - - c.Zoom( - new LvcPoint( - (float)p.Position.X, (float)p.Position.Y), - p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); - } - - private void OnCanvasPinched(object? sender, LiveChartsPinchEventArgs eventArgs) - { - if (_core == null) throw new Exception("core not found"); - var c = (CartesianChart)_core; - - c.Zoom(eventArgs.PinchStart, ZoomDirection.DefinedByScaleFactor, eventArgs.Scale, true); - _panLocketUntil = DateTime.Now.AddMilliseconds(500); - //_lastScale = eventArgs.Scale; - } - - private void OnUnloaded(object? sender, RoutedEventArgs e) - { - _core?.Unload(); - } - - private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) - { - var chart = (CartesianChart)o; - if (chart._core == null) return; - - chart._core.Update(); - } - - void IChartView.OnDataPointerDown(IEnumerable points, LvcPoint pointer) - { - DataPointerDown?.Invoke(this, points); - if (DataPointerDownCommand is not null && DataPointerDownCommand.CanExecute(points)) DataPointerDownCommand.Execute(points); - - var closest = points.FindClosestTo(pointer); - ChartPointPointerDown?.Invoke(this, closest); - if (ChartPointPointerDownCommand is not null && ChartPointPointerDownCommand.CanExecute(closest)) ChartPointPointerDownCommand.Execute(closest); - } - - void IChartView.OnVisualElementPointerDown( - IEnumerable> visualElements, LvcPoint pointer) - { - var args = new VisualElementsEventArgs(CoreChart, visualElements, pointer); - - VisualElementsPointerDown?.Invoke(this, args); - if (VisualElementsPointerDownCommand is not null && VisualElementsPointerDownCommand.CanExecute(args)) - VisualElementsPointerDownCommand.Execute(args); - } - - void IChartView.Invalidate() - { - CoreCanvas.Invalidate(); - } -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml deleted file mode 100644 index 99fa69eac..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml.cs deleted file mode 100644 index eb4414f15..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml.cs +++ /dev/null @@ -1,279 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using LiveChartsCore.Drawing; -using LiveChartsCore.Geo; -using LiveChartsCore.Kernel; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.SkiaSharpView.Drawing; -using LiveChartsCore.SkiaSharpView.Painting; -using SkiaSharp; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using LiveChartsCore.SkiaSharpView.WinUI.Helpers; - -namespace LiveChartsCore.SkiaSharpView.WinUI; - -/// -/// Defines a geographic map. -/// -public sealed partial class GeoMap : UserControl, IGeoMapView -{ - private readonly CollectionDeepObserver _seriesObserver; - private readonly GeoMap _core; - - /// - /// Initializes a new instance of the class. - /// - public GeoMap() - { - InitializeComponent(); - LiveCharts.Configure(config => config.UseDefaults()); - _core = new GeoMap(this); - - PointerPressed += OnPointerPressed; - PointerMoved += OnPointerMoved; - PointerReleased += OnPointerReleased; - PointerWheelChanged += OnWheelChanged; - PointerExited += OnPointerExited; - - SizeChanged += GeoMap_SizeChanged; - - _seriesObserver = new CollectionDeepObserver( - (object? sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), - (object? sender, PropertyChangedEventArgs e) => _core.Update(), - true); - - SetValue(SeriesProperty, Enumerable.Empty()); - SetValue(ActiveMapProperty, Maps.GetWorldMap()); - SetValue(SyncContextProperty, new object()); - - Unloaded += GeoMap_Unloaded; - } - - #region dependency props - - /// - /// The active map property - /// - public static readonly DependencyProperty ActiveMapProperty = - DependencyProperty.Register(nameof(ActiveMap), typeof(CoreMap), typeof(GeoMap), - new PropertyMetadata(null, OnDependencyPropertyChanged)); - - /// - /// The sync context property. - /// - public static readonly DependencyProperty SyncContextProperty = - DependencyProperty.Register( - nameof(SyncContext), typeof(object), typeof(GeoMap), new PropertyMetadata(null, OnDependencyPropertyChanged)); - - /// - /// The view command property. - /// - public static readonly DependencyProperty ViewCommandProperty = - DependencyProperty.Register( - nameof(ViewCommand), typeof(object), typeof(GeoMap), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (GeoMap)o; - chart._core.ViewTo(args.NewValue); - })); - - /// - /// The map projection property - /// - public static readonly DependencyProperty MapProjectionProperty = - DependencyProperty.Register(nameof(MapProjection), typeof(MapProjection), typeof(GeoMap), - new PropertyMetadata(MapProjection.Default, OnDependencyPropertyChanged)); - - /// - /// The series property - /// - public static readonly DependencyProperty SeriesProperty = - DependencyProperty.Register(nameof(Series), typeof(IEnumerable), - typeof(GeoMap), new PropertyMetadata(null, (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (GeoMap)o; - var seriesObserver = chart._seriesObserver; - seriesObserver?.Dispose((IEnumerable)args.OldValue); - seriesObserver?.Initialize((IEnumerable)args.NewValue); - chart._core.Update(); - })); - - /// - /// The stroke property - /// - public static readonly DependencyProperty StrokeProperty = - DependencyProperty.Register( - nameof(Stroke), typeof(IPaint), typeof(GeoMap), - new PropertyMetadata(new SolidColorPaint(new SKColor(255, 255, 255, 255)) { IsStroke = true }, OnDependencyPropertyChanged)); - - /// - /// The fill property - /// - public static readonly DependencyProperty FillProperty = - DependencyProperty.Register( - nameof(Fill), typeof(IPaint), typeof(GeoMap), - new PropertyMetadata(new SolidColorPaint(new SKColor(240, 240, 240, 255)) { IsFill = true }, OnDependencyPropertyChanged)); - - #endregion - - #region properties - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - bool IGeoMapView.DesignerMode => Windows.ApplicationModel.DesignMode.DesignModeEnabled; - - /// - public object SyncContext - { - get => GetValue(SyncContextProperty); - set => SetValue(SyncContextProperty, value); - } - - /// - public object? ViewCommand - { - get => GetValue(ViewCommandProperty); - set => SetValue(ViewCommandProperty, value); - } - - /// - public MotionCanvas Canvas => canvas.CanvasCore; - - /// - public CoreMap ActiveMap - { - get => (CoreMap)GetValue(ActiveMapProperty); - set => SetValue(ActiveMapProperty, value); - } - - /// - float IGeoMapView.Width => (float)ActualWidth; - - /// - float IGeoMapView.Height => (float)ActualHeight; - - /// - public MapProjection MapProjection - { - get => (MapProjection)GetValue(MapProjectionProperty); - set => SetValue(MapProjectionProperty, value); - } - - /// - public IPaint? Stroke - { - get => (IPaint)GetValue(StrokeProperty); - set - { - if (value is not null) value.IsStroke = true; - SetValue(StrokeProperty, value); - } - } - - /// - public IPaint? Fill - { - get => (IPaint)GetValue(FillProperty); - set - { - if (value is not null) value.IsFill = true; - SetValue(FillProperty, value); - } - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty); - set => SetValue(SeriesProperty, value); - } - - #endregion - - void IGeoMapView.InvokeOnUIThread(Action action) - { - UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); - } - - private void GeoMap_SizeChanged(object sender, SizeChangedEventArgs e) - { - _core.Update(); - } - - private void GeoMap_Unloaded(object sender, RoutedEventArgs e) - { - _core.Unload(); - } - - private void OnPointerPressed(object sender, PointerRoutedEventArgs e) - { - _ = CapturePointer(e.Pointer); - var p = e.GetCurrentPoint(this); - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - } - - private void OnPointerMoved(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - } - - private void OnPointerReleased(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - ReleasePointerCapture(e.Pointer); - } - - private void OnPointerExited(object sender, PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - - private void OnWheelChanged(object sender, PointerRoutedEventArgs e) - { - if (_core == null) throw new Exception("core not found"); - var p = e.GetCurrentPoint(this); - - _core.ViewTo( - new ZoomOnPointerView( - new LvcPoint((float)p.Position.X, (float)p.Position.Y), - p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut)); - } - - private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) - { - var chart = (GeoMap)o; - chart._core.Update(); - } -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs deleted file mode 100644 index 223a2b6ac..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs +++ /dev/null @@ -1,32 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using LiveChartsCore.Drawing; - -namespace LiveChartsCore.SkiaSharpView.WinUI.Helpers; - -public class LiveChartsPinchEventArgs -{ - public float Scale { get; set; } - - public LvcPoint PinchStart { get; set; } -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs deleted file mode 100644 index 233535643..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs +++ /dev/null @@ -1,62 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System; -using System.Runtime.InteropServices; -using Microsoft.UI.Dispatching; - -namespace LiveChartsCore.SkiaSharpView.WinUI.Helpers; - -/// -/// Defines Uno platform helpers. -/// -public static class UnoPlatformHelpers -{ - /// - /// Determines whether the assembly is running in web assembly. - /// - public static bool IsWebAssembly { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")); - - /// - /// Invokes a given acction in the UI thread. - /// - /// The action. - /// The dispatcher queue - public static void InvokeOnUIThread(Action action, DispatcherQueue dispatcherQueue) - { - if (IsWebAssembly) - { - action(); - return; - } - - _ = dispatcherQueue.TryEnqueue( - DispatcherQueuePriority.Normal, () => action()); - } -} - -/// -/// Defines a custom pinch event handler. -/// -/// -/// -public delegate void PinchHandler(object sender, LiveChartsPinchEventArgs eventArgs); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj deleted file mode 100644 index 186519d86..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj +++ /dev/null @@ -1,86 +0,0 @@ - - - net6.0-windows10.0.18362;netstandard2.0;net6.0-ios;net6.0-macos;net6.0-maccatalyst;net6.0-android - - true - - enable - 11.0 - 2.0.0-beta.950 - icon.png - Simple, flexible, interactive and powerful data visualization for Uno.WinUI. - MIT - BetoRodriguez - true - snupkg - https://github.com/beto-rodriguez/LiveCharts2 - Properties - LiveChartsCore.SkiaSharpView.WinUI - LiveChartsCore.SkiaSharpView.Uno.WinUI - en-US - bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml - - - - - - - - - - - - - - - %(Filename) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %(Filename) - - - %(Filename) - - - %(Filename) - - - %(Filename) - - - %(Filename) - - - - - - diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml deleted file mode 100644 index f436fdf64..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs deleted file mode 100644 index 23a695114..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs +++ /dev/null @@ -1,283 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using LiveChartsCore.Drawing; -using LiveChartsCore.Kernel; -using LiveChartsCore.Motion; -using LiveChartsCore.SkiaSharpView.Drawing; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using LiveChartsCore.SkiaSharpView.WinUI.Helpers; -using SkiaSharp.Views.Windows; -using Windows.Graphics.Display; - -#if __ANDROID__ -using Android.Views; -#endif - -namespace LiveChartsCore.SkiaSharpView.WinUI; - -/// -public sealed partial class MotionCanvas : UserControl -{ - private readonly SKXamlCanvas _skiaElement; - private bool _isDrawingLoopRunning; - - /// - /// Initializes a new instance of the class. - /// - public MotionCanvas() - { - InitializeComponent(); - Loaded += OnLoaded; - Unloaded += OnUnloaded; - - var canvas = (SKXamlCanvas)FindName("canvas"); - _skiaElement = canvas; - _skiaElement.PaintSurface += OnPaintSurface; - -#if __ANDROID__ - _scaleDetector = new ScaleGestureDetector(Context, new AndroidScaleListener(this)); -#endif - } - - #region properties - - /// - /// The paint tasks property - /// - public static readonly DependencyProperty PaintTasksProperty = - DependencyProperty.Register( - nameof(PaintTasks), typeof(List>), typeof(MotionCanvas), - new PropertyMetadata(new List>(), new PropertyChangedCallback(OnPaintTaskChanged))); - - /// - /// Gets or sets the paint tasks. - /// - /// - /// The paint tasks. - /// - public List> PaintTasks - { - get => (List>)GetValue(PaintTasksProperty); - set => SetValue(PaintTasksProperty, value); - } - - /// - /// Gets or sets the frames per second. - /// - /// - /// The frames per second. - /// - public double MaxFps { get; set; } = 60; - - /// - /// Gets the canvas core. - /// - /// - /// The canvas core. - /// - public MotionCanvas CanvasCore { get; } = new(); - - #endregion - - /// - /// Called when the canvas detects a pinch gesture. - /// - public event PinchHandler? Pinched; - - private void OnLoaded(object sender, RoutedEventArgs e) - { - CanvasCore.Invalidated += OnCanvasCoreInvalidated; - } - - private void OnPaintSurface(object? sender, SKPaintSurfaceEventArgs args) - { -#if HAS_UNO_WINUI - var scale = DisplayInformation.GetForCurrentView().LogicalDpi / 96.0f; - args.Surface.Canvas.Scale((float)scale, (float)scale); - CanvasCore.DrawFrame(new SkiaSharpDrawingContext(CanvasCore, args.Info, args.Surface, args.Surface.Canvas)); -#else - var scaleFactor = XamlRoot.RasterizationScale; - args.Surface.Canvas.Scale((float)scaleFactor, (float)scaleFactor); - CanvasCore.DrawFrame(new SkiaSharpDrawingContext(CanvasCore, args.Info, args.Surface, args.Surface.Canvas)); -#endif - } - - private async void RunDrawingLoop() - { - if (_isDrawingLoopRunning || _skiaElement == null) return; - _isDrawingLoopRunning = true; - - var ts = TimeSpan.FromSeconds(1 / MaxFps); - while (!CanvasCore.IsValid) - { - _skiaElement.Invalidate(); - await Task.Delay(ts); - } - - _isDrawingLoopRunning = false; - } - - private void OnCanvasCoreInvalidated(MotionCanvas sender) - { - RunDrawingLoop(); - } - - private static void OnPaintTaskChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) - { - var motionCanvas = (MotionCanvas)sender; - - var tasks = new HashSet>(); - - foreach (var item in motionCanvas.PaintTasks ?? Enumerable.Empty>()) - { - item.PaintTask.SetGeometries(motionCanvas.CanvasCore, item.Geometries); - _ = tasks.Add(item.PaintTask); - } - - motionCanvas.CanvasCore.SetPaintTasks(tasks); - } - - private void OnUnloaded(object sender, RoutedEventArgs e) - { - CanvasCore.Invalidated -= OnCanvasCoreInvalidated; - CanvasCore.Dispose(); - } - - #region ANDROID -#if __ANDROID__ - // based on: - //https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/touch/android-touch-walkthrough - - private readonly ScaleGestureDetector _scaleDetector; - - private int _activePointerId = -1; - private float _lastTouchX; - private float _lastTouchY; - private float _posX; - private float _posY; - - private class AndroidScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener - { - private readonly MotionCanvas _canvas; - - public AndroidScaleListener(MotionCanvas canvas) - { - _canvas = canvas; - } - - /// - /// Called on scale gesture. - /// - /// - /// - public override bool OnScale(ScaleGestureDetector? detector) - { - if (detector is null) return false; - - if (detector.ScaleFactor != 1.0f) - { - _canvas.InvokePinch( - new LiveChartsPinchEventArgs - { - PinchStart = new LvcPoint { X = _canvas._lastTouchX, Y = _canvas._lastTouchY }, - Scale = detector.ScaleFactor - }); - } - return true; - } - } - - public override bool OnTouchEvent(MotionEvent? ev) - { - if (ev is null) return false; - - _ = _scaleDetector.OnTouchEvent(ev); - - var action = ev.Action & MotionEventActions.Mask; - int pointerIndex; - - switch (action) - { - case MotionEventActions.Down: - _lastTouchX = ev.GetX(); - _lastTouchY = ev.GetY(); - _activePointerId = ev.GetPointerId(0); - break; - - case MotionEventActions.Move: - pointerIndex = ev.FindPointerIndex(_activePointerId); - var x = ev.GetX(pointerIndex); - var y = ev.GetY(pointerIndex); - if (!_scaleDetector.IsInProgress) - { - // Only move the ScaleGestureDetector isn't already processing a gesture. - var deltaX = x - _lastTouchX; - var deltaY = y - _lastTouchY; - _posX += deltaX; - _posY += deltaY; - } - - _lastTouchX = x; - _lastTouchY = y; - break; - - case MotionEventActions.Up: - case MotionEventActions.Cancel: - // We no longer need to keep track of the active pointer. - _activePointerId = -1; - break; - - case MotionEventActions.PointerUp: - // check to make sure that the pointer that went up is for the gesture we're tracking. - pointerIndex = (int)(ev.Action & MotionEventActions.PointerIndexMask) >> (int)MotionEventActions.PointerIndexShift; - var pointerId = ev.GetPointerId(pointerIndex); - if (pointerId == _activePointerId) - { - // This was our active pointer going up. Choose a new - // action pointer and adjust accordingly - var newPointerIndex = pointerIndex == 0 ? 1 : 0; - _lastTouchX = ev.GetX(newPointerIndex); - _lastTouchY = ev.GetY(newPointerIndex); - _activePointerId = ev.GetPointerId(newPointerIndex); - } - break; - - default: - break; - } - - return true; - } - - private void InvokePinch(LiveChartsPinchEventArgs args) - { - Pinched?.Invoke(this, args); - } -#endif - #endregion -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml deleted file mode 100644 index fa32efc41..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs deleted file mode 100644 index c9079aa73..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs +++ /dev/null @@ -1,762 +0,0 @@ - -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using System.Windows.Input; -using LiveChartsCore.Drawing; -using LiveChartsCore.Kernel; -using LiveChartsCore.Kernel.Events; -using LiveChartsCore.Kernel.Sketches; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.SkiaSharpView.Drawing; -using LiveChartsCore.SkiaSharpView.SKCharts; -using LiveChartsCore.SkiaSharpView.WinUI.Helpers; -using LiveChartsCore.VisualElements; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; - -namespace LiveChartsCore.SkiaSharpView.WinUI; - -/// -public sealed partial class PieChart : UserControl, IPieChartView -{ - private Chart? _core; - private MotionCanvas? _canvas; - private readonly CollectionDeepObserver _seriesObserver; - private readonly CollectionDeepObserver> _visualsObserver; - - /// - /// Initializes a new instance of the class. - /// - public PieChart() - { - LiveCharts.Configure(config => config.UseDefaults()); - - InitializeComponent(); - - _seriesObserver = new CollectionDeepObserver( - (object? sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), - (object? sender, PropertyChangedEventArgs e) => _core?.Update()); - _visualsObserver = new CollectionDeepObserver>( - (object? sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), - (object? sender, PropertyChangedEventArgs e) => _core?.Update()); - - Loaded += OnLoaded; - Unloaded += OnUnloaded; - - SetValue(SeriesProperty, new ObservableCollection()); - SetValue(VisualElementsProperty, new ObservableCollection>()); - SetValue(SyncContextProperty, new object()); - } - - #region dependency properties - - /// - /// The title property. - /// - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register( - nameof(Title), typeof(VisualElement), typeof(PieChart), new PropertyMetadata(null)); - - /// - /// The series property - /// - public static readonly DependencyProperty SeriesProperty = - DependencyProperty.Register( - nameof(Series), typeof(IEnumerable), typeof(PieChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (PieChart)o; - var seriesObserver = chart._seriesObserver; - seriesObserver?.Dispose((IEnumerable)args.OldValue); - seriesObserver?.Initialize((IEnumerable)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The visual elements property - /// - public static readonly DependencyProperty VisualElementsProperty = - DependencyProperty.Register( - nameof(VisualElements), typeof(IEnumerable>), typeof(PieChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (PieChart)o; - var observer = chart._visualsObserver; - observer?.Dispose((IEnumerable>)args.OldValue); - observer?.Initialize((IEnumerable>)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The sync context property - /// - public static readonly DependencyProperty SyncContextProperty = - DependencyProperty.Register( - nameof(SyncContext), typeof(object), typeof(PieChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (PieChart)o; - if (chart._canvas != null) chart.CoreCanvas.Sync = args.NewValue; - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The IsClockwise property - /// - public static readonly DependencyProperty IsClockwiseProperty = - DependencyProperty.Register( - nameof(IsClockwise), typeof(bool), typeof(PieChart), new PropertyMetadata(true, OnDependencyPropertyChanged)); - - /// - /// The initial rotation property - /// - public static readonly DependencyProperty InitialRotationProperty = - DependencyProperty.Register( - nameof(InitialRotation), typeof(double), typeof(PieChart), new PropertyMetadata(0d, OnDependencyPropertyChanged)); - - /// - /// The maximum angle property - /// - public static readonly DependencyProperty MaxAngleProperty = - DependencyProperty.Register( - nameof(MaxAngle), typeof(double), typeof(PieChart), new PropertyMetadata(360d, OnDependencyPropertyChanged)); - - /// - /// The total property - /// - public static readonly DependencyProperty MaxValueProperty = - DependencyProperty.Register( - nameof(MaxValue), typeof(double?), typeof(PieChart), new PropertyMetadata(null, OnDependencyPropertyChanged)); - - /// - /// The start property - /// - public static readonly DependencyProperty MinValueProperty = - DependencyProperty.Register( - nameof(MinValue), typeof(double), typeof(PieChart), new PropertyMetadata(0d, OnDependencyPropertyChanged)); - - /// - /// The draw margin property - /// - public static readonly DependencyProperty DrawMarginProperty = - DependencyProperty.Register( - nameof(DrawMargin), typeof(Margin), typeof(PieChart), new PropertyMetadata(null, OnDependencyPropertyChanged)); - - /// - /// The animations speed property - /// - public static readonly DependencyProperty AnimationsSpeedProperty = - DependencyProperty.Register( - nameof(AnimationsSpeed), typeof(TimeSpan), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.AnimationsSpeed, OnDependencyPropertyChanged)); - - /// - /// The easing function property - /// - public static readonly DependencyProperty EasingFunctionProperty = - DependencyProperty.Register( - nameof(EasingFunction), typeof(Func), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.EasingFunction, OnDependencyPropertyChanged)); - - /// - /// The legend position property - /// - public static readonly DependencyProperty LegendPositionProperty = - DependencyProperty.Register( - nameof(LegendPosition), typeof(LegendPosition), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendPosition, OnDependencyPropertyChanged)); - - /// - /// The legend background paint property - /// - public static readonly DependencyProperty LegendBackgroundPaintProperty = - DependencyProperty.Register( - nameof(LegendBackgroundPaint), typeof(IPaint), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendBackgroundPaint, OnDependencyPropertyChanged)); - - /// - /// The legend text paint property - /// - public static readonly DependencyProperty LegendTextPaintProperty = - DependencyProperty.Register( - nameof(LegendTextPaint), typeof(IPaint), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextPaint, OnDependencyPropertyChanged)); - - /// - /// The legend text size property - /// - public static readonly DependencyProperty LegendTextSizeProperty = - DependencyProperty.Register( - nameof(LegendTextSize), typeof(double?), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextSize, OnDependencyPropertyChanged)); - - /// - /// The tool tip position property - /// - public static readonly DependencyProperty TooltipPositionProperty = - DependencyProperty.Register( - nameof(TooltipPosition), typeof(TooltipPosition), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipPosition, OnDependencyPropertyChanged)); - - /// - /// The tooltip background paint property - /// - public static readonly DependencyProperty TooltipBackgroundPaintProperty = - DependencyProperty.Register( - nameof(TooltipBackgroundPaint), typeof(IPaint), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipBackgroundPaint, OnDependencyPropertyChanged)); - - /// - /// The tooltip text paint property - /// - public static readonly DependencyProperty TooltipTextPaintProperty = - DependencyProperty.Register( - nameof(TooltipTextPaint), typeof(IPaint), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextPaint, OnDependencyPropertyChanged)); - - /// - /// The tooltip text size property - /// - public static readonly DependencyProperty TooltipTextSizeProperty = - DependencyProperty.Register( - nameof(TooltipTextSize), typeof(double?), typeof(PieChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextSize, OnDependencyPropertyChanged)); - - /// - /// The update started command. - /// - public static readonly DependencyProperty UpdateStartedCommandProperty = - DependencyProperty.Register( - nameof(UpdateStartedCommand), typeof(ICommand), typeof(PieChart), - new PropertyMetadata(null)); - - /// - /// The pointer pressed command. - /// - public static readonly DependencyProperty PointerPressedCommandProperty = - DependencyProperty.Register( - nameof(PointerPressedCommand), typeof(ICommand), typeof(PieChart), - new PropertyMetadata(null)); - - /// - /// The pointer released command. - /// - public static readonly DependencyProperty PointerReleasedCommandProperty = - DependencyProperty.Register( - nameof(PointerReleasedCommand), typeof(ICommand), typeof(PieChart), - new PropertyMetadata(null)); - - /// - /// The pointer move command. - /// - public static readonly DependencyProperty PointerMoveCommandProperty = - DependencyProperty.Register( - nameof(PointerMoveCommand), typeof(ICommand), typeof(PieChart), - new PropertyMetadata(null)); - - /// - /// The data pointer down command property - /// - public static readonly DependencyProperty DataPointerDownCommandProperty = - DependencyProperty.Register( - nameof(DataPointerDownCommand), typeof(ICommand), typeof(PieChart), new PropertyMetadata(null)); - - /// - /// The data pointer down command property - /// - public static readonly DependencyProperty ChartPointPointerDownCommandProperty = - DependencyProperty.Register( - nameof(ChartPointPointerDownCommand), typeof(ICommand), typeof(PieChart), new PropertyMetadata(null)); - - /// - /// The chart point pointer down command property - /// - public static readonly DependencyProperty VisualElementsPointerDownCommandProperty = - DependencyProperty.Register( - nameof(VisualElementsPointerDownCommand), typeof(ICommand), typeof(PieChart), new PropertyMetadata(null)); - - #endregion - - #region events - - /// - public event ChartEventHandler? Measuring; - - /// - public event ChartEventHandler? UpdateStarted; - - /// - public event ChartEventHandler? UpdateFinished; - - /// - public event ChartPointsHandler? DataPointerDown; - - /// - public event ChartPointHandler? ChartPointPointerDown; - - /// - public event VisualElementsHandler? VisualElementsPointerDown; - - #endregion - - #region properties - - /// - bool IChartView.DesignerMode => Windows.ApplicationModel.DesignMode.DesignModeEnabled; - - /// - public IChart CoreChart => _core ?? throw new Exception("Core not set yet."); - - PieChart IPieChartView.Core - => _core == null ? throw new Exception("core not found") : (PieChart)_core; - - LvcColor IChartView.BackColor - { - get => Background is not SolidColorBrush b - ? new LvcColor() - : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); - set => SetValue(BackgroundProperty, new SolidColorBrush(Windows.UI.Color.FromArgb(value.A, value.R, value.G, value.B))); - } - - /// - public object SyncContext - { - get => GetValue(SyncContextProperty); - set => SetValue(SyncContextProperty, value); - } - - /// - public VisualElement? Title - { - get => (VisualElement?)GetValue(TitleProperty); - set => SetValue(TitleProperty, value); - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty); - set => SetValue(SeriesProperty, value); - } - - /// - public IEnumerable> VisualElements - { - get => (IEnumerable>)GetValue(VisualElementsProperty); - set => SetValue(VisualElementsProperty, value); - } - - /// - public bool IsClockwise - { - get => (bool)GetValue(IsClockwiseProperty); - set => SetValue(IsClockwiseProperty, value); - } - - /// - public double InitialRotation - { - get => (double)GetValue(InitialRotationProperty); - set => SetValue(InitialRotationProperty, value); - } - - /// - public double MaxAngle - { - get => (double)GetValue(MaxAngleProperty); - set => SetValue(MaxAngleProperty, value); - } - - /// - [Obsolete($"Use {nameof(MaxValue)} instead.")] - public double? Total - { - get => (double?)GetValue(MaxValueProperty); - set => SetValue(MaxValueProperty, value); - } - - /// - public double? MaxValue - { - get => (double?)GetValue(MaxValueProperty); - set => SetValue(MaxValueProperty, value); - } - - /// - public double MinValue - { - get => (double)GetValue(MinValueProperty); - set => SetValue(MinValueProperty, value); - } - - /// - public Margin DrawMargin - { - get => (Margin)GetValue(DrawMarginProperty); - set => SetValue(DrawMarginProperty, value); - } - - Margin? IChartView.DrawMargin - { - get => DrawMargin; - set => SetValue(DrawMarginProperty, value); - } - - LvcSize IChartView.ControlSize => _canvas == null - ? throw new Exception("Canvas not found") - : new LvcSize { Width = (float)_canvas.ActualWidth, Height = (float)_canvas.ActualHeight }; - - /// - public MotionCanvas CoreCanvas => _canvas == null ? throw new Exception("Canvas not found") : _canvas.CanvasCore; - - /// - public TimeSpan AnimationsSpeed - { - get => (TimeSpan)GetValue(AnimationsSpeedProperty); - set => SetValue(AnimationsSpeedProperty, value); - } - - TimeSpan IChartView.AnimationsSpeed - { - get => AnimationsSpeed; - set => SetValue(AnimationsSpeedProperty, value); - } - - /// - public Func EasingFunction - { - get => (Func)GetValue(EasingFunctionProperty); - set => SetValue(EasingFunctionProperty, value); - } - - Func? IChartView.EasingFunction - { - get => EasingFunction; - set => SetValue(EasingFunctionProperty, value); - } - - /// - public LegendPosition LegendPosition - { - get => (LegendPosition)GetValue(LegendPositionProperty); - set => SetValue(LegendPositionProperty, value); - } - - /// - public TooltipPosition TooltipPosition - { - get => (TooltipPosition)GetValue(TooltipPositionProperty); - set => SetValue(TooltipPositionProperty, value); - } - - /// - public IPaint? TooltipBackgroundPaint - { - get => (IPaint?)GetValue(TooltipBackgroundPaintProperty); - set => SetValue(TooltipBackgroundPaintProperty, value); - } - - /// - public IPaint? TooltipTextPaint - { - get => (IPaint?)GetValue(TooltipTextPaintProperty); - set => SetValue(TooltipTextPaintProperty, value); - } - - /// - public double? TooltipTextSize - { - get => (double?)GetValue(TooltipTextSizeProperty); - set => SetValue(TooltipTextSizeProperty, value); - } - - /// - public IChartTooltip? Tooltip { get; set; } = new SKDefaultTooltip(); - - /// - public IPaint? LegendBackgroundPaint - { - get => (IPaint?)GetValue(LegendBackgroundPaintProperty); - set => SetValue(LegendBackgroundPaintProperty, value); - } - - /// - public IPaint? LegendTextPaint - { - get => (IPaint?)GetValue(LegendTextPaintProperty); - set => SetValue(LegendTextPaintProperty, value); - } - - /// - public double? LegendTextSize - { - get => (double?)GetValue(LegendTextSizeProperty); - set => SetValue(LegendTextSizeProperty, value); - } - - /// - public IChartLegend? Legend { get; set; } = new SKDefaultLegend(); - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - public TimeSpan UpdaterThrottler { get; set; } = LiveCharts.DefaultSettings.UpdateThrottlingTimeout; - - /// - /// Gets or sets a command to execute when the chart update started. - /// - public ICommand? UpdateStartedCommand - { - get => (ICommand?)GetValue(UpdateStartedCommandProperty); - set => SetValue(UpdateStartedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer is pressed on the chart. - /// - public ICommand? PointerPressedCommand - { - get => (ICommand?)GetValue(PointerPressedCommandProperty); - set => SetValue(PointerPressedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer is released on the chart. - /// - public ICommand? PointerReleasedCommand - { - get => (ICommand?)GetValue(PointerReleasedCommandProperty); - set => SetValue(PointerReleasedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer moves over the chart. - /// - public ICommand? PointerMoveCommand - { - get => (ICommand?)GetValue(PointerMoveCommandProperty); - set => SetValue(PointerMoveCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a data or data points. - /// - public ICommand DataPointerDownCommand - { - get => (ICommand)GetValue(DataPointerDownCommandProperty); - set => SetValue(DataPointerDownCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a chart point. - /// - public ICommand ChartPointPointerDownCommand - { - get => (ICommand)GetValue(ChartPointPointerDownCommandProperty); - set => SetValue(ChartPointPointerDownCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a chart point. - /// - public ICommand? VisualElementsPointerDownCommand - { - get => (ICommand?)GetValue(VisualElementsPointerDownCommandProperty); - set => SetValue(VisualElementsPointerDownCommandProperty, value); - } - - #endregion - - /// - public IEnumerable GetPointsAt(LvcPoint point, TooltipFindingStrategy strategy = TooltipFindingStrategy.Automatic) - { - if (_core is not PieChart cc) throw new Exception("core not found"); - - if (strategy == TooltipFindingStrategy.Automatic) - strategy = cc.Series.GetTooltipFindingStrategy(); - - return cc.Series.SelectMany(series => series.FindHitPoints(cc, point, strategy)); - } - - /// - public IEnumerable> GetVisualsAt(LvcPoint point) - { - return _core is not PieChart cc - ? throw new Exception("core not found") - : cc.VisualElements.SelectMany(visual => ((VisualElement)visual).IsHitBy(_core, point)); - } - - void IChartView.InvokeOnUIThread(Action action) - { - UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); - } - - private void OnLoaded(object sender, RoutedEventArgs e) - { - var canvas = (MotionCanvas)FindName("motionCanvas"); - _canvas = canvas; - - if (_core is null) - { - _core = new PieChart(this, config => config.UseDefaults(), canvas.CanvasCore); - - if (SyncContext != null) - _canvas.CanvasCore.Sync = SyncContext; - - if (_core == null) throw new Exception("Core not found!"); - _core.Update(); - - _core.Measuring += OnCoreMeasuring; - _core.UpdateStarted += OnCoreUpdateStarted; - _core.UpdateFinished += OnCoreUpdateFinished; - - PointerPressed += OnPointerPressed; - PointerReleased += PieChart_PointerReleased; - SizeChanged += OnSizeChanged; - PointerMoved += OnPointerMoved; - PointerExited += OnPointerExited; - } - - _core.Load(); - _core.Update(); - } - - private void OnSizeChanged(object sender, SizeChangedEventArgs e) - { - if (_core == null) throw new Exception("Core not found!"); - _core.Update(); - } - - private void OnPointerPressed(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - - if (PointerPressedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); - } - - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); - } - - private void PieChart_PointerReleased(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } - } - - private void OnPointerMoved(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(motionCanvas); - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - } - - private void OnCoreUpdateFinished(IChartView chart) - { - UpdateFinished?.Invoke(this); - } - - private void OnCoreUpdateStarted(IChartView chart) - { - if (UpdateStartedCommand is not null) - { - var args = new ChartCommandArgs(this); - if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); - } - - UpdateStarted?.Invoke(this); - } - - private void OnCoreMeasuring(IChartView chart) - { - Measuring?.Invoke(this); - } - - private void OnPointerExited(object sender, PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - - private void OnUnloaded(object sender, RoutedEventArgs e) - { - _core?.Unload(); - } - - private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) - { - var chart = (PieChart)o; - if (chart._core == null) return; - - chart._core.Update(); - } - - void IChartView.OnDataPointerDown(IEnumerable points, LvcPoint pointer) - { - DataPointerDown?.Invoke(this, points); - if (DataPointerDownCommand is not null && DataPointerDownCommand.CanExecute(points)) DataPointerDownCommand.Execute(points); - - var closest = points.FindClosestTo(pointer); - ChartPointPointerDown?.Invoke(this, closest); - if (ChartPointPointerDownCommand is not null && ChartPointPointerDownCommand.CanExecute(closest)) ChartPointPointerDownCommand.Execute(closest); - } - - void IChartView.OnVisualElementPointerDown( - IEnumerable> visualElements, LvcPoint pointer) - { - var args = new VisualElementsEventArgs(CoreChart, visualElements, pointer); - - VisualElementsPointerDown?.Invoke(this, args); - if (VisualElementsPointerDownCommand is not null && VisualElementsPointerDownCommand.CanExecute(args)) - VisualElementsPointerDownCommand.Execute(args); - } - - void IChartView.Invalidate() - { - CoreCanvas.Invalidate(); - } -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml deleted file mode 100644 index 437f2b7de..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs deleted file mode 100644 index 10ec031ec..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs +++ /dev/null @@ -1,859 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using System.Windows.Input; -using LiveChartsCore.Drawing; -using LiveChartsCore.Kernel; -using LiveChartsCore.Kernel.Events; -using LiveChartsCore.Kernel.Sketches; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.SkiaSharpView.Drawing; -using LiveChartsCore.SkiaSharpView.SKCharts; -using LiveChartsCore.SkiaSharpView.WinUI.Helpers; -using LiveChartsCore.VisualElements; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace LiveChartsCore.SkiaSharpView.WinUI; - -/// -public sealed partial class PolarChart : UserControl, IPolarChartView -{ - #region fields - - private Chart? _core; - private MotionCanvas? _canvas; - private readonly CollectionDeepObserver _seriesObserver; - private readonly CollectionDeepObserver _angleObserver; - private readonly CollectionDeepObserver _radiusObserver; - private readonly CollectionDeepObserver> _visualsObserver; - - #endregion - - /// - /// Initializes a new instance of the class. - /// - public PolarChart() - { - LiveCharts.Configure(config => config.UseDefaults()); - - InitializeComponent(); - - _seriesObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - _angleObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - _radiusObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - _visualsObserver = new CollectionDeepObserver>( - OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); - - Loaded += OnLoaded; - Unloaded += OnUnloaded; - - SetValue(AngleAxesProperty, new ObservableCollection() - { - LiveCharts.DefaultSettings.GetProvider().GetDefaultPolarAxis() - }); - SetValue(RadiusAxesProperty, new ObservableCollection() - { - LiveCharts.DefaultSettings.GetProvider().GetDefaultPolarAxis() - }); - SetValue(SeriesProperty, new ObservableCollection()); - SetValue(VisualElementsProperty, new ObservableCollection>()); - SetValue(SyncContextProperty, new object()); - } - - #region dependency properties - - /// - /// The fit to bounds property. - /// - public static readonly DependencyProperty FitToBoundsProperty = - DependencyProperty.Register( - nameof(FitToBounds), typeof(bool), typeof(PolarChart), new PropertyMetadata(false, OnDependencyPropertyChanged)); - - /// - /// The inner radius property. - /// - public static readonly DependencyProperty TotalAngleProperty = - DependencyProperty.Register( - nameof(TotalAngle), typeof(double), typeof(PolarChart), new PropertyMetadata(360d, OnDependencyPropertyChanged)); - - /// - /// The inner radius property. - /// - public static readonly DependencyProperty InnerRadiusProperty = - DependencyProperty.Register( - nameof(InnerRadius), typeof(double), typeof(PolarChart), new PropertyMetadata(0d, OnDependencyPropertyChanged)); - - /// - /// The initial rotation property. - /// - public static readonly DependencyProperty InitialRotationProperty = - DependencyProperty.Register( - nameof(InitialRotation), typeof(double), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.PolarInitialRotation, OnDependencyPropertyChanged)); - - /// - /// The title property. - /// - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register( - nameof(Title), typeof(VisualElement), typeof(PolarChart), new PropertyMetadata(null)); - - /// - /// The series property. - /// - public static readonly DependencyProperty SeriesProperty = - DependencyProperty.Register( - nameof(Series), typeof(IEnumerable), typeof(PolarChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (PolarChart)o; - var seriesObserver = chart._seriesObserver; - seriesObserver?.Dispose((IEnumerable)args.OldValue); - seriesObserver?.Initialize((IEnumerable)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The visual elements property - /// - public static readonly DependencyProperty VisualElementsProperty = - DependencyProperty.Register( - nameof(VisualElements), typeof(IEnumerable>), typeof(PolarChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (PolarChart)o; - var observer = chart._visualsObserver; - observer?.Dispose((IEnumerable>)args.OldValue); - observer?.Initialize((IEnumerable>)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The x axes property. - /// - public static readonly DependencyProperty AngleAxesProperty = - DependencyProperty.Register( - nameof(AngleAxes), typeof(IEnumerable), typeof(PolarChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (PolarChart)o; - var observer = chart._angleObserver; - observer?.Dispose((IEnumerable)args.OldValue); - observer?.Initialize((IEnumerable)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The y axes property. - /// - public static readonly DependencyProperty RadiusAxesProperty = - DependencyProperty.Register( - nameof(RadiusAxes), typeof(IEnumerable), typeof(PolarChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (PolarChart)o; - var observer = chart._radiusObserver; - observer?.Dispose((IEnumerable)args.OldValue); - observer?.Initialize((IEnumerable)args.NewValue); - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The sync context property. - /// - public static readonly DependencyProperty SyncContextProperty = - DependencyProperty.Register( - nameof(SyncContext), typeof(object), typeof(PolarChart), new PropertyMetadata(null, - (DependencyObject o, DependencyPropertyChangedEventArgs args) => - { - var chart = (PolarChart)o; - if (chart._canvas != null) chart.CoreCanvas.Sync = args.NewValue; - if (chart._core == null) return; - chart._core.Update(); - })); - - /// - /// The tool tip finding strategy property. - /// - public static readonly DependencyProperty TooltipFindingStrategyProperty = - DependencyProperty.Register( - nameof(TooltipFindingStrategy), typeof(TooltipFindingStrategy), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipFindingStrategy, OnDependencyPropertyChanged)); - - /// - /// The animations speed property. - /// - public static readonly DependencyProperty AnimationsSpeedProperty = - DependencyProperty.Register( - nameof(AnimationsSpeed), typeof(TimeSpan), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.AnimationsSpeed, OnDependencyPropertyChanged)); - - /// - /// The easing function property. - /// - public static readonly DependencyProperty EasingFunctionProperty = - DependencyProperty.Register( - nameof(EasingFunction), typeof(Func), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.EasingFunction, OnDependencyPropertyChanged)); - - /// - /// The legend position property. - /// - public static readonly DependencyProperty LegendPositionProperty = - DependencyProperty.Register( - nameof(LegendPosition), typeof(LegendPosition), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendPosition, OnDependencyPropertyChanged)); - - /// - /// The legend background paint property - /// - public static readonly DependencyProperty LegendBackgroundPaintProperty = - DependencyProperty.Register( - nameof(LegendBackgroundPaint), typeof(IPaint), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendBackgroundPaint, OnDependencyPropertyChanged)); - - /// - /// The legend text paint property - /// - public static readonly DependencyProperty LegendTextPaintProperty = - DependencyProperty.Register( - nameof(LegendTextPaint), typeof(IPaint), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextPaint, OnDependencyPropertyChanged)); - - /// - /// The legend text size property - /// - public static readonly DependencyProperty LegendTextSizeProperty = - DependencyProperty.Register( - nameof(LegendTextSize), typeof(double?), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextSize, OnDependencyPropertyChanged)); - - /// - /// The tool tip position property. - /// - public static readonly DependencyProperty TooltipPositionProperty = - DependencyProperty.Register( - nameof(TooltipPosition), typeof(TooltipPosition), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipPosition, OnDependencyPropertyChanged)); - - /// - /// The tooltip background paint property - /// - public static readonly DependencyProperty TooltipBackgroundPaintProperty = - DependencyProperty.Register( - nameof(TooltipBackgroundPaint), typeof(IPaint), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipBackgroundPaint, OnDependencyPropertyChanged)); - - /// - /// The tooltip text paint property - /// - public static readonly DependencyProperty TooltipTextPaintProperty = - DependencyProperty.Register( - nameof(TooltipTextPaint), typeof(IPaint), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextPaint, OnDependencyPropertyChanged)); - - /// - /// The tooltip text size property - /// - public static readonly DependencyProperty TooltipTextSizeProperty = - DependencyProperty.Register( - nameof(TooltipTextSize), typeof(double?), typeof(PolarChart), - new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextSize, OnDependencyPropertyChanged)); - - /// - /// The update started command. - /// - public static readonly DependencyProperty UpdateStartedCommandProperty = - DependencyProperty.Register( - nameof(UpdateStartedCommand), typeof(ICommand), typeof(PolarChart), - new PropertyMetadata(null)); - - /// - /// The pointer pressed command. - /// - public static readonly DependencyProperty PointerPressedCommandProperty = - DependencyProperty.Register( - nameof(PointerPressedCommand), typeof(ICommand), typeof(PolarChart), - new PropertyMetadata(null)); - - /// - /// The pointer released command. - /// - public static readonly DependencyProperty PointerReleasedCommandProperty = - DependencyProperty.Register( - nameof(PointerReleasedCommand), typeof(ICommand), typeof(PolarChart), - new PropertyMetadata(null)); - - /// - /// The pointer move command. - /// - public static readonly DependencyProperty PointerMoveCommandProperty = - DependencyProperty.Register( - nameof(PointerMoveCommand), typeof(ICommand), typeof(PolarChart), - new PropertyMetadata(null)); - - /// - /// The data pointer down command property - /// - public static readonly DependencyProperty DataPointerDownCommandProperty = - DependencyProperty.Register( - nameof(DataPointerDownCommand), typeof(ICommand), typeof(PolarChart), new PropertyMetadata(null)); - - /// - /// The chart point pointer down command property - /// - public static readonly DependencyProperty ChartPointPointerDownCommandProperty = - DependencyProperty.Register( - nameof(ChartPointPointerDownCommand), typeof(ICommand), typeof(PolarChart), new PropertyMetadata(null)); - - /// - /// The chart point pointer down command property - /// - public static readonly DependencyProperty VisualElementsPointerDownCommandProperty = - DependencyProperty.Register( - nameof(VisualElementsPointerDownCommand), typeof(ICommand), typeof(PolarChart), new PropertyMetadata(null)); - - #endregion - - #region events - - /// - public event ChartEventHandler? Measuring; - - /// - public event ChartEventHandler? UpdateStarted; - - /// - public event ChartEventHandler? UpdateFinished; - - /// - public event ChartPointsHandler? DataPointerDown; - - /// - public event ChartPointHandler? ChartPointPointerDown; - - /// - public event VisualElementsHandler? VisualElementsPointerDown; - - #endregion - - #region properties - - /// - bool IChartView.DesignerMode => Windows.ApplicationModel.DesignMode.DesignModeEnabled; - - /// - public IChart CoreChart => _core ?? throw new Exception("Core not set yet."); - - /// - public object SyncContext - { - get => GetValue(SyncContextProperty); - set => SetValue(SyncContextProperty, value); - } - - LvcColor IChartView.BackColor - { - get => Background is not SolidColorBrush b - ? new LvcColor() - : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); - set => SetValue(BackgroundProperty, new SolidColorBrush(Windows.UI.Color.FromArgb(value.A, value.R, value.G, value.B))); - } - - /// - public Margin? DrawMargin - { - get => null; - set => throw new NotImplementedException(); - } - - Margin? IChartView.DrawMargin - { - get => DrawMargin; - set => throw new NotImplementedException(); - } - - LvcSize IChartView.ControlSize => _canvas == null - ? throw new Exception("Canvas not found") - : new LvcSize { Width = (float)_canvas.ActualWidth, Height = (float)_canvas.ActualHeight }; - - /// - public MotionCanvas CoreCanvas => _canvas == null ? throw new Exception("Canvas not found") : _canvas.CanvasCore; - - PolarChart IPolarChartView.Core => - _core == null ? throw new Exception("core not found") : (PolarChart)_core; - - /// - public bool FitToBounds - { - get => (bool)GetValue(FitToBoundsProperty); - set => SetValue(FitToBoundsProperty, value); - } - - /// - public double TotalAngle - { - get => (double)GetValue(TotalAngleProperty); - set => SetValue(TotalAngleProperty, value); - } - - /// - public double InnerRadius - { - get => (double)GetValue(InnerRadiusProperty); - set => SetValue(InnerRadiusProperty, value); - } - - /// - public double InitialRotation - { - get => (double)GetValue(InitialRotationProperty); - set => SetValue(InitialRotationProperty, value); - } - - /// - public VisualElement? Title - { - get => (VisualElement?)GetValue(TitleProperty); - set => SetValue(TitleProperty, value); - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty); - set => SetValue(SeriesProperty, value); - } - - /// - public IEnumerable AngleAxes - { - get => (IEnumerable)GetValue(AngleAxesProperty); - set => SetValue(AngleAxesProperty, value); - } - - /// - public IEnumerable RadiusAxes - { - get => (IEnumerable)GetValue(RadiusAxesProperty); - set => SetValue(RadiusAxesProperty, value); - } - - /// - public IEnumerable> VisualElements - { - get => (IEnumerable>)GetValue(VisualElementsProperty); - set => SetValue(VisualElementsProperty, value); - } - - /// - public TimeSpan AnimationsSpeed - { - get => (TimeSpan)GetValue(AnimationsSpeedProperty); - set => SetValue(AnimationsSpeedProperty, value); - } - - TimeSpan IChartView.AnimationsSpeed - { - get => AnimationsSpeed; - set => SetValue(AnimationsSpeedProperty, value); - } - - /// - public Func EasingFunction - { - get => (Func)GetValue(EasingFunctionProperty); - set => SetValue(EasingFunctionProperty, value); - } - - Func? IChartView.EasingFunction - { - get => EasingFunction; - set => SetValue(EasingFunctionProperty, value); - } - - /// - public LegendPosition LegendPosition - { - get => (LegendPosition)GetValue(LegendPositionProperty); - set => SetValue(LegendPositionProperty, value); - } - - LegendPosition IChartView.LegendPosition - { - get => LegendPosition; - set => SetValue(LegendPositionProperty, value); - } - - /// - public TooltipPosition TooltipPosition - { - get => (TooltipPosition)GetValue(TooltipPositionProperty); - set => SetValue(TooltipPositionProperty, value); - } - - /// - public IPaint? TooltipBackgroundPaint - { - get => (IPaint?)GetValue(TooltipBackgroundPaintProperty); - set => SetValue(TooltipBackgroundPaintProperty, value); - } - - /// - public IPaint? TooltipTextPaint - { - get => (IPaint?)GetValue(TooltipTextPaintProperty); - set => SetValue(TooltipTextPaintProperty, value); - } - - /// - public double? TooltipTextSize - { - get => (double?)GetValue(TooltipTextSizeProperty); - set => SetValue(TooltipTextSizeProperty, value); - } - - /// - public IChartTooltip? Tooltip { get; set; } = new SKDefaultTooltip(); - - /// - public IPaint? LegendBackgroundPaint - { - get => (IPaint?)GetValue(LegendBackgroundPaintProperty); - set => SetValue(LegendBackgroundPaintProperty, value); - } - - /// - public IPaint? LegendTextPaint - { - get => (IPaint?)GetValue(LegendTextPaintProperty); - set => SetValue(LegendTextPaintProperty, value); - } - - /// - public double? LegendTextSize - { - get => (double?)GetValue(LegendTextSizeProperty); - set => SetValue(LegendTextSizeProperty, value); - } - - /// - public IChartLegend? Legend { get; set; } = new SKDefaultLegend(); - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - public TimeSpan UpdaterThrottler { get; set; } = LiveCharts.DefaultSettings.UpdateThrottlingTimeout; - - /// - /// Gets or sets a command to execute when the chart update started. - /// - public ICommand? UpdateStartedCommand - { - get => (ICommand?)GetValue(UpdateStartedCommandProperty); - set => SetValue(UpdateStartedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer is pressed on the chart. - /// - public ICommand? PointerPressedCommand - { - get => (ICommand?)GetValue(PointerPressedCommandProperty); - set => SetValue(PointerPressedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer is released on the chart. - /// - public ICommand? PointerReleasedCommand - { - get => (ICommand?)GetValue(PointerReleasedCommandProperty); - set => SetValue(PointerReleasedCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer moves over the chart. - /// - public ICommand? PointerMoveCommand - { - get => (ICommand?)GetValue(PointerMoveCommandProperty); - set => SetValue(PointerMoveCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a data or data points. - /// - public ICommand DataPointerDownCommand - { - get => (ICommand)GetValue(DataPointerDownCommandProperty); - set => SetValue(DataPointerDownCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a data or data points. - /// - public ICommand ChartPointPointerDownCommand - { - get => (ICommand)GetValue(ChartPointPointerDownCommandProperty); - set => SetValue(ChartPointPointerDownCommandProperty, value); - } - - /// - /// Gets or sets a command to execute when the pointer goes down on a chart point. - /// - public ICommand? VisualElementsPointerDownCommand - { - get => (ICommand?)GetValue(VisualElementsPointerDownCommandProperty); - set => SetValue(VisualElementsPointerDownCommandProperty, value); - } - - #endregion - - /// - public LvcPointD ScalePixelsToData(LvcPointD point, int angleAxisIndex = 0, int radiusAxisIndex = 0) - { - if (_core is not PolarChart cc) throw new Exception("core not found"); - - var scaler = new PolarScaler( - cc.DrawMarginLocation, cc.DrawMarginSize, cc.AngleAxes[angleAxisIndex], cc.RadiusAxes[radiusAxisIndex], - cc.InnerRadius, cc.InitialRotation, cc.TotalAnge); - - return scaler.ToChartValues(point.X, point.Y); - } - - /// - public LvcPointD ScaleDataToPixels(LvcPointD point, int angleAxisIndex = 0, int radiusAxisIndex = 0) - { - if (_core is not PolarChart cc) throw new Exception("core not found"); - - var scaler = new PolarScaler( - cc.DrawMarginLocation, cc.DrawMarginSize, cc.AngleAxes[angleAxisIndex], cc.RadiusAxes[radiusAxisIndex], - cc.InnerRadius, cc.InitialRotation, cc.TotalAnge); - - var r = scaler.ToPixels(point.X, point.Y); - - return new LvcPointD { X = (float)r.X, Y = (float)r.Y }; - } - - /// - public IEnumerable GetPointsAt(LvcPoint point, TooltipFindingStrategy strategy = TooltipFindingStrategy.Automatic) - { - if (_core is not PolarChart cc) throw new Exception("core not found"); - - if (strategy == TooltipFindingStrategy.Automatic) - strategy = cc.Series.GetTooltipFindingStrategy(); - - return cc.Series.SelectMany(series => series.FindHitPoints(cc, point, strategy)); - } - - /// - public IEnumerable> GetVisualsAt(LvcPoint point) - { - return _core is not PolarChart cc - ? throw new Exception("core not found") - : cc.VisualElements.SelectMany(visual => ((VisualElement)visual).IsHitBy(_core, point)); - } - - void IChartView.InvokeOnUIThread(Action action) - { - UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); - } - - private void OnLoaded(object sender, RoutedEventArgs e) - { - var canvas = (MotionCanvas)FindName("motionCanvas"); - _canvas = canvas; - - if (_core is null) - { - _core = new PolarChart(this, config => config.UseDefaults(), canvas.CanvasCore); - - if (SyncContext != null) - _canvas.CanvasCore.Sync = SyncContext; - - if (_core == null) throw new Exception("Core not found!"); - _core.Measuring += OnCoreMeasuring; - _core.UpdateStarted += OnCoreUpdateStarted; - _core.UpdateFinished += OnCoreUpdateFinished; - - PointerWheelChanged += OnWheelChanged; - PointerPressed += OnPointerPressed; - PointerReleased += OnPointerReleased; - SizeChanged += OnSizeChanged; - PointerMoved += OnPointerMoved; - PointerExited += OnPointerExited; - } - - _core.Load(); - _core.Update(); - } - - private void OnDeepCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - _core?.Update(); - } - - private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - _core?.Update(); - } - - private void OnSizeChanged(object? sender, SizeChangedEventArgs e) - { - if (_core == null) throw new Exception("Core not found!"); - _core.Update(); - } - - private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(motionCanvas); - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - } - - private void OnCoreUpdateFinished(IChartView chart) - { - UpdateFinished?.Invoke(this); - } - - private void OnCoreUpdateStarted(IChartView chart) - { - if (UpdateStartedCommand is not null) - { - var args = new ChartCommandArgs(this); - if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); - } - - UpdateStarted?.Invoke(this); - } - - private void OnCoreMeasuring(IChartView chart) - { - Measuring?.Invoke(this); - } - - private void OnPointerExited(object sender, PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - - private void OnPointerReleased(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } - - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); - } - - private void OnPointerPressed(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - - if (PointerPressedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); - } - - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); - } - - private void OnWheelChanged(object sender, PointerRoutedEventArgs e) - { - //if (_core == null) throw new Exception("core not found"); - //var c = (PolarChart)_core; - //var p = e.GetCurrentPoint(this); - - //c.Zoom( - // new System.Drawing.PointF( - // (float)p.Position.X, (float)p.Position.Y), - // p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); - } - - private void OnUnloaded(object sender, RoutedEventArgs e) - { - _core?.Unload(); - } - - private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) - { - var chart = (PolarChart)o; - if (chart._core == null) return; - - chart._core.Update(); - } - - void IChartView.OnDataPointerDown(IEnumerable points, LvcPoint pointer) - { - DataPointerDown?.Invoke(this, points); - if (DataPointerDownCommand is not null && DataPointerDownCommand.CanExecute(points)) DataPointerDownCommand.Execute(points); - - var closest = points.FindClosestTo(pointer); - ChartPointPointerDown?.Invoke(this, closest); - if (ChartPointPointerDownCommand is not null && ChartPointPointerDownCommand.CanExecute(closest)) - ChartPointPointerDownCommand.Execute(closest); - } - - void IChartView.OnVisualElementPointerDown( - IEnumerable> visualElements, LvcPoint pointer) - { - var args = new VisualElementsEventArgs(CoreChart, visualElements, pointer); - - VisualElementsPointerDown?.Invoke(this, args); - if (VisualElementsPointerDownCommand is not null && VisualElementsPointerDownCommand.CanExecute(args)) - VisualElementsPointerDownCommand.Execute(args); - } - - void IChartView.Invalidate() - { - CoreCanvas.Invalidate(); - } -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/images/icon.png b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/images/icon.png deleted file mode 100644 index d0c1c566005cbef8d7c17888043cabb90abe923c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7880 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 Date: Mon, 4 Sep 2023 16:51:58 -0600 Subject: [PATCH 06/78] add old uno proj --- samples/UnoPlatformSample/.vscode/launch.json | 53 + .../UnoPlatformSample/.vscode/settings.json | 7 + samples/UnoPlatformSample/.vscode/tasks.json | 53 + samples/UnoPlatformSample/.vsconfig | 38 + .../UnoPlatformSample/Directory.Build.props | 55 + .../UnoPlatformSample/Directory.Build.targets | 6 + .../Directory.Packages.props | 56 ++ .../UnoPlatformSample.Base/AppHead.xaml | 17 + .../UnoPlatformSample.Base/AppHead.xaml.cs | 49 + .../Icons/appconfig.svg | 137 +++ .../UnoPlatformSample.Base/Icons/iconapp.svg | 42 + .../Splash/splash_screen.svg | 137 +++ .../UnoPlatformSample.Base/base.props | 26 + .../Serialization/WeatherForecastContext.cs | 45 + .../UnoPlatformSample.DataContracts.csproj | 6 + .../WeatherForecast.cs | 37 + .../Android/AndroidManifest.xml | 4 + .../Android/Assets/AboutAssets.txt | 22 + .../Android/Main.Android.cs | 64 ++ .../Android/MainActivity.Android.cs | 37 + .../Android/Resources/AboutResources.txt | 47 + .../Android/Resources/values/Strings.xml | 5 + .../Android/Resources/values/Styles.xml | 22 + .../Android/environment.conf | 2 + .../MacCatalyst/Entitlements.plist | 6 + .../MacCatalyst/Info.plist | 26 + .../MacCatalyst/Main.maccatalyst.cs | 35 + .../LaunchImages.launchimage/Contents.json | 58 ++ .../UnoPlatformSample.Mobile.csproj | 89 ++ .../iOS/Entitlements.plist | 6 + .../UnoPlatformSample.Mobile/iOS/Info.plist | 43 + .../UnoPlatformSample.Mobile/iOS/Main.iOS.cs | 35 + .../LaunchImages.launchimage/Contents.json | 58 ++ .../Apis/WeatherForecastApi.cs | 69 ++ .../UnoPlatformSample.Server/GlobalUsings.cs | 25 + .../UnoPlatformSample.Server/Program.cs | 80 ++ .../Properties/launchSettings.json | 33 + .../UnoPlatformSample.Server.csproj | 18 + .../appsettings.Development.json | 8 + .../UnoPlatformSample.Server/appsettings.json | 9 + .../Package.appxmanifest | 43 + .../UnoPlatformSample.Skia.Gtk/Program.cs | 42 + .../UnoPlatformSample.Skia.Gtk.csproj | 41 + .../UnoPlatformSample.Skia.Gtk/app.manifest | 77 ++ .../UnoPlatformSample.Tests/AppInfoTests.cs | 40 + .../UnoPlatformSample.Tests/GlobalUsings.cs | 25 + .../UnoPlatformSample.Tests.csproj | 19 + .../UnoPlatformSample.UITests/Constants.cs | 33 + .../Given_MainPage.cs | 47 + .../UnoPlatformSample.UITests/GlobalUsings.cs | 27 + .../UnoPlatformSample.UITests/TestBase.cs | 102 ++ .../UnoPlatformSample.UITests.csproj | 16 + .../UnoPlatformSample.Wasm/LinkerConfig.xml | 11 + .../UnoPlatformSample.Wasm/Program.cs | 35 + .../Properties/launchSettings.json | 30 + .../UnoPlatformSample.Wasm.csproj | 91 ++ .../UnoPlatformSample.Wasm/WasmCSS/Fonts.css | 28 + .../WasmScripts/AppManifest.js | 3 + .../manifest.webmanifest | 10 + .../wwwroot/staticwebapp.config.json | 30 + .../UnoPlatformSample.Wasm/wwwroot/web.config | 78 ++ .../Package.appxmanifest | 43 + .../Properties/launchsettings.json | 10 + .../Resources.lang-en-us.resw | 123 +++ .../UnoPlatformSample.Windows.csproj | 91 ++ .../UnoPlatformSample.Windows/app.manifest | 25 + .../UnoPlatformSample/UnoPlatformSample.sln | 302 ++++++ .../UnoPlatformSample/App.cs | 129 +++ .../UnoPlatformSample/AppResources.xaml | 14 + .../UnoPlatformSample/Assets/Icons/back.svg | 3 + .../UnoPlatformSample/Assets/SharedAssets.md | 34 + .../Business/Models/AppConfig.cs | 28 + .../Business/Models/Entity.cs | 25 + .../UnoPlatformSample/GlobalUsings.cs | 54 + .../Infrastructure/DebugHandler.cs | 63 ++ .../Axes/ColorsAndPosition/View.xaml | 31 + .../Axes/ColorsAndPosition/View.xaml.cs | 11 + .../Axes/Crosshairs/View.xaml | 22 + .../Axes/Crosshairs/View.xaml.cs | 11 + .../Axes/CustomSeparatorsInterval/View.xaml | 16 + .../CustomSeparatorsInterval/View.xaml.cs | 11 + .../Axes/DateTimeScaled/View.xaml | 16 + .../Axes/DateTimeScaled/View.xaml.cs | 11 + .../Axes/LabelsFormat/View.xaml | 17 + .../Axes/LabelsFormat/View.xaml.cs | 11 + .../Axes/LabelsFormat2/View.xaml | 17 + .../Axes/LabelsFormat2/View.xaml.cs | 11 + .../Axes/LabelsRotation/View.xaml | 39 + .../Axes/LabelsRotation/View.xaml.cs | 11 + .../Axes/Logarithmic/View.xaml | 16 + .../Axes/Logarithmic/View.xaml.cs | 11 + .../LiveChartsSamples/Axes/Multiple/View.xaml | 20 + .../Axes/Multiple/View.xaml.cs | 11 + .../Axes/NamedLabels/View.xaml | 29 + .../Axes/NamedLabels/View.xaml.cs | 11 + .../LiveChartsSamples/Axes/Paging/View.xaml | 30 + .../Axes/Paging/View.xaml.cs | 11 + .../LiveChartsSamples/Axes/Shared/View.xaml | 36 + .../Axes/Shared/View.xaml.cs | 11 + .../LiveChartsSamples/Axes/Style/View.xaml | 24 + .../LiveChartsSamples/Axes/Style/View.xaml.cs | 11 + .../Axes/TimeSpanScaled/View.xaml | 16 + .../Axes/TimeSpanScaled/View.xaml.cs | 11 + .../Bars/AutoUpdate/View.xaml | 30 + .../Bars/AutoUpdate/View.xaml.cs | 29 + .../LiveChartsSamples/Bars/Basic/View.xaml | 17 + .../LiveChartsSamples/Bars/Basic/View.xaml.cs | 11 + .../LiveChartsSamples/Bars/Custom/View.xaml | 18 + .../Bars/Custom/View.xaml.cs | 11 + .../Bars/DelayedAnimation/View.xaml | 18 + .../Bars/DelayedAnimation/View.xaml.cs | 11 + .../LiveChartsSamples/Bars/Layered/View.xaml | 18 + .../Bars/Layered/View.xaml.cs | 11 + .../LiveChartsSamples/Bars/Race/View.xaml | 26 + .../LiveChartsSamples/Bars/Race/View.xaml.cs | 13 + .../Bars/RowsWithLabels/View.xaml | 18 + .../Bars/RowsWithLabels/View.xaml.cs | 11 + .../LiveChartsSamples/Bars/Spacing/View.xaml | 18 + .../Bars/Spacing/View.xaml.cs | 11 + .../Bars/WithBackground/View.xaml | 18 + .../Bars/WithBackground/View.xaml.cs | 11 + .../LiveChartsSamples/Box/Basic/View.xaml | 17 + .../LiveChartsSamples/Box/Basic/View.xaml.cs | 11 + .../Design/LinearGradients/View.xaml | 18 + .../Design/LinearGradients/View.xaml.cs | 11 + .../Design/RadialGradients/View.xaml | 18 + .../Design/RadialGradients/View.xaml.cs | 11 + .../Design/StrokeDashArray/View.xaml | 18 + .../Design/StrokeDashArray/View.xaml.cs | 11 + .../LiveChartsSamples/Error/Basic/View.xaml | 35 + .../Error/Basic/View.xaml.cs | 11 + .../Events/AddPointOnClick/View.xaml | 20 + .../Events/AddPointOnClick/View.xaml.cs | 14 + .../Events/Cartesian/View.xaml | 21 + .../Events/Cartesian/View.xaml.cs | 11 + .../LiveChartsSamples/Events/Pie/View.xaml | 22 + .../LiveChartsSamples/Events/Pie/View.xaml.cs | 45 + .../LiveChartsSamples/Events/Polar/View.xaml | 21 + .../Events/Polar/View.xaml.cs | 45 + .../Financial/BasicCandlesticks/View.xaml | 21 + .../Financial/BasicCandlesticks/View.xaml.cs | 11 + .../General/Animations/View.xaml | 39 + .../General/Animations/View.xaml.cs | 11 + .../General/ChartToImage/View.xaml | 40 + .../General/ChartToImage/View.xaml.cs | 47 + .../General/ConditionalDraw/View.xaml | 17 + .../General/ConditionalDraw/View.xaml.cs | 11 + .../General/Legends/View.xaml | 32 + .../General/Legends/View.xaml.cs | 11 + .../General/MapPoints/View.xaml | 17 + .../General/MapPoints/View.xaml.cs | 11 + .../General/MultiThreading/View.xaml | 21 + .../General/MultiThreading/View.xaml.cs | 11 + .../General/MultiThreading2/View.xaml | 15 + .../General/MultiThreading2/View.xaml.cs | 28 + .../General/NullPoints/View.xaml | 18 + .../General/NullPoints/View.xaml.cs | 11 + .../General/RealTime/View.xaml | 18 + .../General/RealTime/View.xaml.cs | 11 + .../General/Scrollable/View.xaml | 45 + .../General/Scrollable/View.xaml.cs | 9 + .../General/Sections/View.xaml | 24 + .../General/Sections/View.xaml.cs | 11 + .../General/Sections2/View.xaml | 18 + .../General/Sections2/View.xaml.cs | 11 + .../General/TemplatedLegends/View.xaml | 23 + .../General/TemplatedLegends/View.xaml.cs | 11 + .../General/TemplatedTooltips/View.xaml | 23 + .../General/TemplatedTooltips/View.xaml.cs | 11 + .../General/Tooltips/View.xaml | 27 + .../General/Tooltips/View.xaml.cs | 11 + .../General/UserDefinedTypes/View.xaml | 18 + .../General/UserDefinedTypes/View.xaml.cs | 11 + .../General/Visibility/View.xaml | 27 + .../General/Visibility/View.xaml.cs | 11 + .../General/VisualElements/View.xaml | 23 + .../General/VisualElements/View.xaml.cs | 11 + .../LiveChartsSamples/Heat/Basic/View.xaml | 22 + .../LiveChartsSamples/Heat/Basic/View.xaml.cs | 11 + .../LiveChartsSamples/Lines/Area/View.xaml | 16 + .../LiveChartsSamples/Lines/Area/View.xaml.cs | 11 + .../Lines/AutoUpdate/View.xaml | 30 + .../Lines/AutoUpdate/View.xaml.cs | 29 + .../LiveChartsSamples/Lines/Basic/View.xaml | 14 + .../Lines/Basic/View.xaml.cs | 11 + .../LiveChartsSamples/Lines/Custom/View.xaml | 13 + .../Lines/Custom/View.xaml.cs | 11 + .../LiveChartsSamples/Lines/Padding/View.xaml | 21 + .../Lines/Padding/View.xaml.cs | 11 + .../Lines/Properties/View.xaml | 34 + .../Lines/Properties/View.xaml.cs | 11 + .../Lines/Straight/View.xaml | 13 + .../Lines/Straight/View.xaml.cs | 11 + .../LiveChartsSamples/Lines/XY/View.xaml | 14 + .../LiveChartsSamples/Lines/XY/View.xaml.cs | 11 + .../LiveChartsSamples/Lines/Zoom/View.xaml | 18 + .../LiveChartsSamples/Lines/Zoom/View.xaml.cs | 11 + .../LiveChartsSamples/Maps/World/View.xaml | 13 + .../LiveChartsSamples/Maps/World/View.xaml.cs | 11 + .../Pies/AngularGauge/View.xaml | 30 + .../Pies/AngularGauge/View.xaml.cs | 11 + .../Pies/AutoUpdate/View.xaml | 28 + .../Pies/AutoUpdate/View.xaml.cs | 29 + .../LiveChartsSamples/Pies/Basic/View.xaml | 16 + .../LiveChartsSamples/Pies/Basic/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Custom/View.xaml | 13 + .../Pies/Custom/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Doughnut/View.xaml | 20 + .../Pies/Doughnut/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Gauge/View.xaml | 46 + .../LiveChartsSamples/Pies/Gauge/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Gauge1/View.xaml | 18 + .../Pies/Gauge1/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Gauge2/View.xaml | 19 + .../Pies/Gauge2/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Gauge3/View.xaml | 19 + .../Pies/Gauge3/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Gauge4/View.xaml | 18 + .../Pies/Gauge4/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Gauge5/View.xaml | 30 + .../Pies/Gauge5/View.xaml.cs | 11 + .../LiveChartsSamples/Pies/Gauges/View.xaml | 125 +++ .../Pies/Gauges/View.xaml.cs | 11 + .../Pies/NightingaleRose/View.xaml | 18 + .../Pies/NightingaleRose/View.xaml.cs | 11 + .../Pies/Processing/View.xaml | 51 + .../Pies/Processing/View.xaml.cs | 35 + .../LiveChartsSamples/Pies/Pushout/View.xaml | 18 + .../Pies/Pushout/View.xaml.cs | 11 + .../LiveChartsSamples/Polar/Basic/View.xaml | 22 + .../Polar/Basic/View.xaml.cs | 11 + .../Polar/Coordinates/View.xaml | 13 + .../Polar/Coordinates/View.xaml.cs | 11 + .../Polar/RadialArea/View.xaml | 13 + .../Polar/RadialArea/View.xaml.cs | 11 + .../Scatter/AutoUpdate/View.xaml | 30 + .../Scatter/AutoUpdate/View.xaml.cs | 29 + .../LiveChartsSamples/Scatter/Basic/View.xaml | 18 + .../Scatter/Basic/View.xaml.cs | 11 + .../Scatter/Bubbles/View.xaml | 18 + .../Scatter/Bubbles/View.xaml.cs | 11 + .../Scatter/Custom/View.xaml | 18 + .../Scatter/Custom/View.xaml.cs | 11 + .../StackedArea/Basic/View.xaml | 18 + .../StackedArea/Basic/View.xaml.cs | 11 + .../StackedArea/StepArea/View.xaml | 18 + .../StackedArea/StepArea/View.xaml.cs | 11 + .../StackedBars/Basic/View.xaml | 18 + .../StackedBars/Basic/View.xaml.cs | 11 + .../StackedBars/Groups/View.xaml | 13 + .../StackedBars/Groups/View.xaml.cs | 11 + .../StepLines/Area/View.xaml | 17 + .../StepLines/Area/View.xaml.cs | 11 + .../StepLines/AutoUpdate/View.xaml | 30 + .../StepLines/AutoUpdate/View.xaml.cs | 29 + .../StepLines/Basic/View.xaml | 18 + .../StepLines/Basic/View.xaml.cs | 11 + .../StepLines/Custom/View.xaml | 18 + .../StepLines/Custom/View.xaml.cs | 11 + .../StepLines/Properties/View.xaml | 34 + .../StepLines/Properties/View.xaml.cs | 11 + .../StepLines/Zoom/View.xaml | 23 + .../StepLines/Zoom/View.xaml.cs | 11 + .../Test/Dispose/UserControl1.xaml | 28 + .../Test/Dispose/UserControl1.xaml.cs | 11 + .../LiveChartsSamples/Test/Dispose/View.xaml | 37 + .../Test/Dispose/View.xaml.cs | 20 + .../VisualTest/DataTemplate/View.xaml | 24 + .../VisualTest/DataTemplate/View.xaml.cs | 11 + .../VisualTest/ReattachVisual/View.xaml | 55 + .../VisualTest/ReattachVisual/View.xaml.cs | 30 + .../VisualTest/Tabs/View.xaml | 23 + .../VisualTest/Tabs/View.xaml.cs | 11 + .../VisualTest/TwoChartsOneSeries/View.xaml | 32 + .../TwoChartsOneSeries/View.xaml.cs | 11 + .../Presentation/MainModel.cs | 28 + .../Presentation/MainPage.xaml | 88 ++ .../Presentation/MainPage.xaml.cs | 32 + .../Presentation/SecondModel.cs | 27 + .../Presentation/SecondPage.xaml | 35 + .../Presentation/SecondPage.xaml.cs | 32 + .../UnoPlatformSample/Presentation/Shell.xaml | 36 + .../Presentation/Shell.xaml.cs | 32 + .../Presentation/ShellModel.cs | 40 + .../Services/Caching/IWeatherCache.cs | 28 + .../Services/Caching/WeatherCache.cs | 97 ++ .../Services/Endpoints/IApiClient.cs | 30 + .../Strings/en/Resources.resw | 123 +++ .../Strings/es/Resources.resw | 123 +++ .../Strings/fr/Resources.resw | 123 +++ .../Strings/pt-BR/Resources.resw | 123 +++ .../Styles/ColorPaletteOverride.xaml | 65 ++ .../Styles/ColorPaletteOverride.zip | Bin 0 -> 5848 bytes .../Styles/MaterialFontsOverride.xaml | 8 + .../UnoPlatformSample.csproj | 77 ++ .../appsettings.development.json | 9 + .../UnoPlatformSample/appsettings.json | 16 + .../AssemblyInfo.cs | 32 + .../CartesianChart.xaml | 14 + .../CartesianChart.xaml.cs | 947 ++++++++++++++++++ .../GeoMap.xaml | 14 + .../GeoMap.xaml.cs | 279 ++++++ .../Helpers/LiveChartsPinchEventArgs.cs | 32 + .../Helpers/UnoPlatformHelpers.cs | 62 ++ ...eChartsCore.SkiaSharpView.Uno.WinUI.csproj | 67 ++ .../MotionCanvas.xaml | 14 + .../MotionCanvas.xaml.cs | 283 ++++++ .../PieChart.xaml | 14 + .../PieChart.xaml.cs | 762 ++++++++++++++ .../PolarChart.xaml | 14 + .../PolarChart.xaml.cs | 859 ++++++++++++++++ 311 files changed, 11649 insertions(+) create mode 100644 samples/UnoPlatformSample/.vscode/launch.json create mode 100644 samples/UnoPlatformSample/.vscode/settings.json create mode 100644 samples/UnoPlatformSample/.vscode/tasks.json create mode 100644 samples/UnoPlatformSample/.vsconfig create mode 100644 samples/UnoPlatformSample/Directory.Build.props create mode 100644 samples/UnoPlatformSample/Directory.Build.targets create mode 100644 samples/UnoPlatformSample/Directory.Packages.props create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/appconfig.svg create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/iconapp.svg create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/Splash/splash_screen.svg create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Base/base.props create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.DataContracts/Serialization/WeatherForecastContext.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.DataContracts/UnoPlatformSample.DataContracts.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.DataContracts/WeatherForecast.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/AndroidManifest.xml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Assets/AboutAssets.txt create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Main.Android.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/MainActivity.Android.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/AboutResources.txt create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Strings.xml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Styles.xml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/environment.conf create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Entitlements.plist create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Info.plist create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Main.maccatalyst.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/UnoPlatformSample.Mobile.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Entitlements.plist create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Info.plist create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Main.iOS.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/Apis/WeatherForecastApi.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/GlobalUsings.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/Program.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/Properties/launchSettings.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/UnoPlatformSample.Server.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.Development.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Package.appxmanifest create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Program.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/app.manifest create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Tests/AppInfoTests.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Tests/GlobalUsings.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Tests/UnoPlatformSample.Tests.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/Constants.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/Given_MainPage.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/GlobalUsings.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/TestBase.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.UITests/UnoPlatformSample.UITests.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/LinkerConfig.xml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/Program.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/Properties/launchSettings.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmCSS/Fonts.css create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmScripts/AppManifest.js create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/manifest.webmanifest create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/staticwebapp.config.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/web.config create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/Package.appxmanifest create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/Properties/launchsettings.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/Resources.lang-en-us.resw create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/UnoPlatformSample.Windows.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.Windows/app.manifest create mode 100644 samples/UnoPlatformSample/UnoPlatformSample.sln create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/App.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/AppResources.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Assets/Icons/back.svg create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Assets/SharedAssets.md create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Business/Models/AppConfig.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Business/Models/Entity.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/GlobalUsings.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Infrastructure/DebugHandler.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainModel.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondModel.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Presentation/ShellModel.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/IWeatherCache.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/WeatherCache.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Services/Endpoints/IApiClient.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Strings/en/Resources.resw create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Strings/es/Resources.resw create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Strings/fr/Resources.resw create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Strings/pt-BR/Resources.resw create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.zip create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/Styles/MaterialFontsOverride.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/appsettings.development.json create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/appsettings.json create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/AssemblyInfo.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/LiveChartsPinchEventArgs.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/UnoPlatformHelpers.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs diff --git a/samples/UnoPlatformSample/.vscode/launch.json b/samples/UnoPlatformSample/.vscode/launch.json new file mode 100644 index 000000000..d6af66c57 --- /dev/null +++ b/samples/UnoPlatformSample/.vscode/launch.json @@ -0,0 +1,53 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": "Debug (Chrome, WebAssembly)", + "type": "chrome", + "request": "launch", + "url": "http://localhost:5000", + "webRoot": "${workspaceFolder}/UnoPlatformSample.Wasm", + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "timeout": 30000, + "server": { + "runtimeExecutable": "dotnet", + "program": "run", + "outputCapture": "std", + "timeout": 30000, + "cwd": "${workspaceFolder}/UnoPlatformSample.Wasm" + } + }, + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": "Skia.GTK (Debug)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build-skia-gtk", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/UnoPlatformSample.Skia.Gtk/bin/Debug/net7.0/UnoPlatformSample.Skia.Gtk.dll", + "args": [], + "env": { + "DOTNET_MODIFIABLE_ASSEMBLIES": "debug" + }, + "cwd": "${workspaceFolder}/UnoPlatformSample.Skia.Gtk", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": "Uno Platform Mobile", + "type": "Uno", + "request": "launch", + // any Uno* task will do, this is simply to satisfy vscode requirement when a launch.json is present + "preLaunchTask": "Uno: android | Debug | android-x64" + }, + ] +} diff --git a/samples/UnoPlatformSample/.vscode/settings.json b/samples/UnoPlatformSample/.vscode/settings.json new file mode 100644 index 000000000..23133fc7c --- /dev/null +++ b/samples/UnoPlatformSample/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.expand": false, + "explorer.fileNesting.patterns": { + "*.xaml": "$(capture).xaml.cs" + } +} diff --git a/samples/UnoPlatformSample/.vscode/tasks.json b/samples/UnoPlatformSample/.vscode/tasks.json new file mode 100644 index 000000000..32f202f6d --- /dev/null +++ b/samples/UnoPlatformSample/.vscode/tasks.json @@ -0,0 +1,53 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build-wasm", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish-wasm", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "build-skia-gtk", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish-skia-gtk", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} diff --git a/samples/UnoPlatformSample/.vsconfig b/samples/UnoPlatformSample/.vsconfig new file mode 100644 index 000000000..1c9c22808 --- /dev/null +++ b/samples/UnoPlatformSample/.vsconfig @@ -0,0 +1,38 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.NetCore.Component.SDK", + "Microsoft.NetCore.Component.DevelopmentTools", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions", + "Microsoft.NetCore.Component.Web", + "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.VisualStudio.Component.IISExpress", + "Component.Microsoft.Web.LibraryManager", + "Microsoft.VisualStudio.ComponentGroup.Web", + "Microsoft.VisualStudio.Component.Web", + "Microsoft.VisualStudio.ComponentGroup.Web.Client", + "Microsoft.VisualStudio.Workload.NetWeb", + "Microsoft.VisualStudio.ComponentGroup.Azure.Prerequisites", + "Microsoft.VisualStudio.Workload.Azure", + "Microsoft.VisualStudio.Component.Windows10SDK.19041", + "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Microsoft.Component.NetFX.Native", + "Microsoft.VisualStudio.Component.Graphics", + "Component.OpenJDK", + "Microsoft.VisualStudio.Component.MonoDebugger", + "Microsoft.VisualStudio.Component.Merq", + "Component.Xamarin.RemotedSimulator", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.TemplateEngine", + "Component.Xamarin", + "Component.Android.SDK32", + "Microsoft.VisualStudio.Workload.NetCrossPlat", + "Microsoft.VisualStudio.Workload.NetCoreTools", + "Microsoft.VisualStudio.ComponentGroup.Maui.All" + ] +} diff --git a/samples/UnoPlatformSample/Directory.Build.props b/samples/UnoPlatformSample/Directory.Build.props new file mode 100644 index 000000000..8c8dc7544 --- /dev/null +++ b/samples/UnoPlatformSample/Directory.Build.props @@ -0,0 +1,55 @@ + + + enable + enable + + portable + True + + true + + $(NoWarn);CA1416;NU1507 + + en + + false + false + false + false + false + + + + + + true + 21.0 + + + + + true + 14.2 + + + + + true + 10.14 + + + + + true + 14.0 + + + + + true + 10.0.18362.0 + 10.0.18362.0 + + + + diff --git a/samples/UnoPlatformSample/Directory.Build.targets b/samples/UnoPlatformSample/Directory.Build.targets new file mode 100644 index 000000000..30332cf7d --- /dev/null +++ b/samples/UnoPlatformSample/Directory.Build.targets @@ -0,0 +1,6 @@ + + + + + + diff --git a/samples/UnoPlatformSample/Directory.Packages.props b/samples/UnoPlatformSample/Directory.Packages.props new file mode 100644 index 000000000..b3b9a4186 --- /dev/null +++ b/samples/UnoPlatformSample/Directory.Packages.props @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml b/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml new file mode 100644 index 000000000..4edcdc464 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml.cs new file mode 100644 index 000000000..9a97712e4 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Base/AppHead.xaml.cs @@ -0,0 +1,49 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using Microsoft.UI.Xaml; +using Uno.Resizetizer; + +namespace UnoPlatformSample; +public sealed partial class AppHead : App +{ + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public AppHead() + { + this.InitializeComponent(); + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs args) + { + base.OnLaunched(args); + + MainWindow.SetWindowIcon(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/appconfig.svg b/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/appconfig.svg new file mode 100644 index 000000000..3106b1a8b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/appconfig.svg @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/iconapp.svg b/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/iconapp.svg new file mode 100644 index 000000000..f621ea597 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Base/Icons/iconapp.svg @@ -0,0 +1,42 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/Splash/splash_screen.svg b/samples/UnoPlatformSample/UnoPlatformSample.Base/Splash/splash_screen.svg new file mode 100644 index 000000000..3106b1a8b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Base/Splash/splash_screen.svg @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Base/base.props b/samples/UnoPlatformSample/UnoPlatformSample.Base/base.props new file mode 100644 index 000000000..6c37f9c20 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Base/base.props @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/Serialization/WeatherForecastContext.cs b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/Serialization/WeatherForecastContext.cs new file mode 100644 index 000000000..240177a1e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/Serialization/WeatherForecastContext.cs @@ -0,0 +1,45 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System.Collections.Immutable; +using System.Text.Json.Serialization; + +namespace UnoPlatformSample.DataContracts.Serialization; +/// +/// Generated class for System.Text.Json Serialization +/// +/// +/// When using the JsonSerializerContext you must add the JsonSerializableAttribute +/// for each type that you may need to serialize / deserialize including both the +/// concrete type and any interface that the concrete type implements. +/// For more information on the JsonSerializerContext see: +/// https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation?WT.mc_id=DT-MVP-5002924 +/// +[JsonSerializable(typeof(WeatherForecast))] +[JsonSerializable(typeof(WeatherForecast[]))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IImmutableList))] +[JsonSerializable(typeof(ImmutableList))] +[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] +public partial class WeatherForecastContext : JsonSerializerContext +{ +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/UnoPlatformSample.DataContracts.csproj b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/UnoPlatformSample.DataContracts.csproj new file mode 100644 index 000000000..47df750e1 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/UnoPlatformSample.DataContracts.csproj @@ -0,0 +1,6 @@ + + + net7.0 + true + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/WeatherForecast.cs b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/WeatherForecast.cs new file mode 100644 index 000000000..ff7bc5598 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.DataContracts/WeatherForecast.cs @@ -0,0 +1,37 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.DataContracts; + +/// +/// A Weather Forecast for a specific date +/// +/// Gets the Date of the Forecast. +/// Gets the Forecast Temperature in Celsius. +/// Get a description of how the weather will feel. +public record WeatherForecast(DateOnly Date, double TemperatureC, string? Summary) +{ + /// + /// Gets the Forecast Temperature in Fahrenheit + /// + public double TemperatureF => 32 + (TemperatureC * 9 / 5); +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/AndroidManifest.xml b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/AndroidManifest.xml new file mode 100644 index 000000000..95ae07533 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Assets/AboutAssets.txt b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Assets/AboutAssets.txt new file mode 100644 index 000000000..210a93b80 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Assets/AboutAssets.txt @@ -0,0 +1,22 @@ +To add cross-platform image assets for your Uno Platform app, use the Assets folder +in the shared project instead. Assets in this folder are Android-only assets. + +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with you package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Main.Android.cs b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Main.Android.cs new file mode 100644 index 000000000..dde1359a7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Main.Android.cs @@ -0,0 +1,64 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Android.App; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Com.Nostra13.Universalimageloader.Core; +using Microsoft.UI.Xaml.Media; + +namespace UnoPlatformSample.Droid; +[global::Android.App.ApplicationAttribute( + Label = "@string/ApplicationName", + Icon = "@mipmap/iconapp", + LargeHeap = true, + HardwareAccelerated = true, + Theme = "@style/AppTheme" +)] +public class Application : Microsoft.UI.Xaml.NativeApplication +{ + public Application(IntPtr javaReference, JniHandleOwnership transfer) + : base(() => new AppHead(), javaReference, transfer) + { + ConfigureUniversalImageLoader(); + } + + private static void ConfigureUniversalImageLoader() + { + // Create global configuration and initialize ImageLoader with this config + ImageLoaderConfiguration config = new ImageLoaderConfiguration + .Builder(Context) + .Build(); + + ImageLoader.Instance.Init(config); + + ImageSource.DefaultImageLoader = ImageLoader.Instance.LoadImageAsync; + } +} + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/MainActivity.Android.cs b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/MainActivity.Android.cs new file mode 100644 index 000000000..346cf8462 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/MainActivity.Android.cs @@ -0,0 +1,37 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using Android.App; +using Android.Content.PM; +using Android.OS; +using Android.Views; +using Android.Widget; + +namespace UnoPlatformSample.Droid; +[Activity( + MainLauncher = true, + ConfigurationChanges = global::Uno.UI.ActivityHelper.AllConfigChanges, + WindowSoftInputMode = SoftInput.AdjustNothing | SoftInput.StateHidden +)] +public class MainActivity : Microsoft.UI.Xaml.ApplicationActivity +{ +} \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/AboutResources.txt b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/AboutResources.txt new file mode 100644 index 000000000..17e3b1333 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/AboutResources.txt @@ -0,0 +1,47 @@ +To add cross-platform image assets for your Uno Platform app, use the Assets folder +in the shared project instead. Resources in this folder are Android-only. + +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Strings.xml b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Strings.xml new file mode 100644 index 000000000..302d078a6 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Strings.xml @@ -0,0 +1,5 @@ + + + Hello World, Click Me! + UnoPlatformSample + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Styles.xml b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Styles.xml new file mode 100644 index 000000000..7e1f95c8d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/Resources/values/Styles.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/environment.conf b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/environment.conf new file mode 100644 index 000000000..fa6c2e32b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/Android/environment.conf @@ -0,0 +1,2 @@ +# See this for more details: http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/ +MONO_GC_PARAMS=bridge-implementation=tarjan,nursery-size=32m,soft-heap-limit=256m \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Entitlements.plist b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Entitlements.plist new file mode 100644 index 000000000..24c310368 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Info.plist b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Info.plist new file mode 100644 index 000000000..5a4053db4 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Info.plist @@ -0,0 +1,26 @@ + + + + + UIDeviceFamily + + 2 + + LSApplicationCategoryType + public.app-category.utilities + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/iconapp.appiconset + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Main.maccatalyst.cs b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Main.maccatalyst.cs new file mode 100644 index 000000000..b1f31e7b7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Main.maccatalyst.cs @@ -0,0 +1,35 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using UIKit; + +namespace UnoPlatformSample.MacCatalyst; +public class EntryPoint +{ + // This is the main entry point of the application. + public static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppHead)); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json new file mode 100644 index 000000000..69555e440 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/MacCatalyst/Media.xcassets/LaunchImages.launchimage/Contents.json @@ -0,0 +1,58 @@ +{ + "images": [ + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "640x960", + "idiom": "iphone" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "subtype": "retina4", + "scale": "2x", + "size": "640x1136", + "idiom": "iphone" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "1x", + "size": "768x1024", + "idiom": "ipad" + }, + { + "orientation": "landscape", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "1x", + "size": "1024x768", + "idiom": "ipad" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "1536x2048", + "idiom": "ipad" + }, + { + "orientation": "landscape", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "2048x1536", + "idiom": "ipad" + } + ], + "properties": {}, + "info": { + "version": 1, + "author": "" + } +} \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/UnoPlatformSample.Mobile.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/UnoPlatformSample.Mobile.csproj new file mode 100644 index 000000000..6433c7c59 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/UnoPlatformSample.Mobile.csproj @@ -0,0 +1,89 @@ + + + net7.0-ios;net7.0-android;net7.0-maccatalyst + true + Exe + + UnoPlatformSample + + com.companyname.UnoPlatformSample + 6A5D2EB4-48BB-4C7D-A232-1FB6EA4B61BA + + 1.0 + 1 + + Android\AndroidManifest.xml + + + + + True + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(MtouchExtraArgs) --setenv=MONO_GC_PARAMS=soft-heap-limit=512m,nursery-size=64m,evacuation-threshold=66,major=marksweep,concurrent-sweep + + $(MtouchExtraArgs) --registrar:static + iossimulator-x64 + + + + $(MtouchExtraArgs) --marshal-objectivec-exceptions:disable + + + + + + $(MtouchExtraArgs) --setenv=MONO_GC_PARAMS=soft-heap-limit=512m,nursery-size=64m,evacuation-threshold=66,major=marksweep,concurrent-sweep + + $(MtouchExtraArgs) --registrar:static + + false + maccatalyst-x64 + + + + $(MtouchExtraArgs) --marshal-objectivec-exceptions:disable + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Entitlements.plist b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Entitlements.plist new file mode 100644 index 000000000..24c310368 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Info.plist b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Info.plist new file mode 100644 index 000000000..981d8e728 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Info.plist @@ -0,0 +1,43 @@ + + + + + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + XSAppIconAssets + Assets.xcassets/iconapp.appiconset + UIApplicationSupportsIndirectInputEvents + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Main.iOS.cs b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Main.iOS.cs new file mode 100644 index 000000000..6549466b2 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Main.iOS.cs @@ -0,0 +1,35 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using UIKit; + +namespace UnoPlatformSample.iOS; +public class EntryPoint +{ + // This is the main entry point of the application. + public static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppHead)); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json new file mode 100644 index 000000000..69555e440 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Mobile/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json @@ -0,0 +1,58 @@ +{ + "images": [ + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "640x960", + "idiom": "iphone" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "subtype": "retina4", + "scale": "2x", + "size": "640x1136", + "idiom": "iphone" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "1x", + "size": "768x1024", + "idiom": "ipad" + }, + { + "orientation": "landscape", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "1x", + "size": "1024x768", + "idiom": "ipad" + }, + { + "orientation": "portrait", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "1536x2048", + "idiom": "ipad" + }, + { + "orientation": "landscape", + "extent": "full-screen", + "minimum-system-version": "7.0", + "scale": "2x", + "size": "2048x1536", + "idiom": "ipad" + } + ], + "properties": {}, + "info": { + "version": 1, + "author": "" + } +} \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/Apis/WeatherForecastApi.cs b/samples/UnoPlatformSample/UnoPlatformSample.Server/Apis/WeatherForecastApi.cs new file mode 100644 index 000000000..b27297308 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Server/Apis/WeatherForecastApi.cs @@ -0,0 +1,69 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Server.Apis; + +internal static class WeatherForecastApi +{ + private const string Tag = "Weather"; + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + internal static WebApplication MapWeatherApi(this WebApplication app) + { + app.MapGet("/api/weatherforecast", GetForecast) + .WithTags(Tag) + .WithName(nameof(GetForecast)); + return app; + } + + /// + /// Creates a make believe weather forecast for the next 5 days. + /// + /// + /// A fake 5 day forecast + /// A 5 Day Forecast + /// Weather Forecast returned + [Produces("application/json")] + [ProducesResponseType(typeof(IEnumerable), 200)] + private static IEnumerable GetForecast(ILoggerFactory loggerFactory) + { + var logger = loggerFactory.CreateLogger(nameof(WeatherForecastApi)); + logger.LogDebug("Getting Weather Forecast."); + + return Enumerable.Range(1, 5).Select(index => + new WeatherForecast( + DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + Random.Shared.Next(-20, 55), + Summaries[Random.Shared.Next(Summaries.Length)] + ) + ) + .Select(x => + { + logger.LogInformation("Weather forecast for {Date} is a {Summary} {TemperatureC}°C", x.Date, x.Summary, x.TemperatureC); + return x; + }) + .ToArray(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/GlobalUsings.cs b/samples/UnoPlatformSample/UnoPlatformSample.Server/GlobalUsings.cs new file mode 100644 index 000000000..e57e9b3a4 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Server/GlobalUsings.cs @@ -0,0 +1,25 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +global using Microsoft.AspNetCore.Mvc; +global using UnoPlatformSample.DataContracts; +global using UnoPlatformSample.Server.Apis; diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/Program.cs b/samples/UnoPlatformSample/UnoPlatformSample.Server/Program.cs new file mode 100644 index 000000000..50bffc72c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Server/Program.cs @@ -0,0 +1,80 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using Uno.Wasm.Bootstrap.Server; +using UnoPlatformSample.DataContracts.Serialization; + +try +{ + var builder = WebApplication.CreateBuilder(args); + + // Configure the JsonOptions to use the generated WeatherForecastContext + builder.Services.Configure(options => + options.JsonSerializerOptions.AddContext()); + // Configure the RouteOptions to use lowercase URLs + builder.Services.Configure(options => + options.LowercaseUrls = true); + + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddSwaggerGen(c => + { + // Include XML comments for all included assemblies + Directory.EnumerateFiles(AppContext.BaseDirectory, "*.xml") + .Where(x => x.Contains("UnoPlatformSample") + && File.Exists(Path.Combine( + AppContext.BaseDirectory, + $"{Path.GetFileNameWithoutExtension(x)}.dll"))) + .ToList() + .ForEach(path => c.IncludeXmlComments(path)); + }); + + var app = builder.Build(); + + // Configure the HTTP request pipeline. + if (app.Environment.IsDevelopment()) + { + app.UseSwagger(); + app.UseSwaggerUI(); + } + + app.UseHttpsRedirection(); + + app.UseUnoFrameworkFiles(); + app.MapFallbackToFile("index.html"); + + app.MapWeatherApi(); + app.UseStaticFiles(); + + await app.RunAsync(); +} +catch (Exception ex) +{ + Console.Error.WriteLine("Application terminated unexpectedly"); + Console.Error.WriteLine(ex); +#if DEBUG + if (System.Diagnostics.Debugger.IsAttached) + { + System.Diagnostics.Debugger.Break(); + } +#endif +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/Properties/launchSettings.json b/samples/UnoPlatformSample/UnoPlatformSample.Server/Properties/launchSettings.json new file mode 100644 index 000000000..935d7a031 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Server/Properties/launchSettings.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:5000", + "sslPort": 5001 + } + }, + "profiles": { + "UnoPlatformSample.Server": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "", + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "https://localhost:5000;http://localhost:5001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "", + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/UnoPlatformSample.Server.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Server/UnoPlatformSample.Server.csproj new file mode 100644 index 000000000..ceae9e1ee --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Server/UnoPlatformSample.Server.csproj @@ -0,0 +1,18 @@ + + + + net7.0 + true + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.Development.json b/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.Development.json new file mode 100644 index 000000000..0c208ae91 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.json b/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.json new file mode 100644 index 000000000..10f68b8c8 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Server/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Package.appxmanifest b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Package.appxmanifest new file mode 100644 index 000000000..8eaafe69a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Package.appxmanifest @@ -0,0 +1,43 @@ + + + + + + + + UnoPlatformSample + UnoPlatformSample + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Program.cs b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Program.cs new file mode 100644 index 000000000..6a527fc20 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/Program.cs @@ -0,0 +1,42 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using GLib; +using Uno.UI.Runtime.Skia; + +namespace UnoPlatformSample.Skia.Gtk; +public class Program +{ + public static void Main(string[] args) + { + ExceptionManager.UnhandledException += delegate (UnhandledExceptionArgs expArgs) + { + Console.WriteLine("GLIB UNHANDLED EXCEPTION" + expArgs.ExceptionObject.ToString()); + expArgs.ExitApplication = true; + }; + + var host = new GtkHost(() => new AppHead(), args); + + host.Run(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj new file mode 100644 index 000000000..402055bf7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/UnoPlatformSample.Skia.Gtk.csproj @@ -0,0 +1,41 @@ + + + WinExe + Exe + net7.0 + app.manifest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/app.manifest b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/app.manifest new file mode 100644 index 000000000..90955ac3a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Skia.Gtk/app.manifest @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Tests/AppInfoTests.cs b/samples/UnoPlatformSample/UnoPlatformSample.Tests/AppInfoTests.cs new file mode 100644 index 000000000..fbc37ab36 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Tests/AppInfoTests.cs @@ -0,0 +1,40 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Tests; + +public class AppInfoTests +{ + [SetUp] + public void Setup() + { + } + + [Test] + public void AppInfoCreation() + { + var appInfo = new AppConfig { Environment = "Test" }; + + appInfo.Should().NotBeNull(); + appInfo.Environment.Should().Be("Test"); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Tests/GlobalUsings.cs b/samples/UnoPlatformSample/UnoPlatformSample.Tests/GlobalUsings.cs new file mode 100644 index 000000000..dcb9f8b4d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Tests/GlobalUsings.cs @@ -0,0 +1,25 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +global using FluentAssertions; +global using NUnit.Framework; +global using UnoPlatformSample.Business.Models; diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Tests/UnoPlatformSample.Tests.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Tests/UnoPlatformSample.Tests.csproj new file mode 100644 index 000000000..7e9224e78 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Tests/UnoPlatformSample.Tests.csproj @@ -0,0 +1,19 @@ + + + + net7.0 + false + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/Constants.cs b/samples/UnoPlatformSample/UnoPlatformSample.UITests/Constants.cs new file mode 100644 index 000000000..1eacfc437 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.UITests/Constants.cs @@ -0,0 +1,33 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.UITests; + +public class Constants +{ + public readonly static string WebAssemblyDefaultUri = "http://localhost:5000/"; + public readonly static string iOSAppName = "com.companyname.UnoPlatformSample"; + public readonly static string AndroidAppName = "com.companyname.UnoPlatformSample"; + public readonly static string iOSDeviceNameOrId = "iPad Pro (12.9-inch) (3rd generation)"; + + public readonly static Platform CurrentPlatform = Platform.Browser; +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/Given_MainPage.cs b/samples/UnoPlatformSample/UnoPlatformSample.UITests/Given_MainPage.cs new file mode 100644 index 000000000..b5f9c57c7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.UITests/Given_MainPage.cs @@ -0,0 +1,47 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.UITests; + +public class Given_MainPage : TestBase +{ + [Test] + public async Task When_SmokeTest() + { + // NOTICE + // To run UITests, Run the WASM target without debugger. Note + // the port that is being used and update the Constants.cs file + // in the UITests project with the correct port number. + + // Add delay to allow for the splash screen to disappear + await Task.Delay(5000); + + + // Query for the SecondPageButton and then tap it + Query xamlButton = q => q.All().Marked("SecondPageButton"); + App.WaitForElement(xamlButton); + App.Tap(xamlButton); + + // Take a screenshot and add it to the test results + TakeScreenshot("After tapped"); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/GlobalUsings.cs b/samples/UnoPlatformSample/UnoPlatformSample.UITests/GlobalUsings.cs new file mode 100644 index 000000000..5c7c2a93a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.UITests/GlobalUsings.cs @@ -0,0 +1,27 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +global using NUnit.Framework; +global using Uno.UITest; +global using Uno.UITest.Helpers.Queries; +global using Uno.UITests.Helpers; +global using Query = System.Func; diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/TestBase.cs b/samples/UnoPlatformSample/UnoPlatformSample.UITests/TestBase.cs new file mode 100644 index 000000000..e5dbe3270 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.UITests/TestBase.cs @@ -0,0 +1,102 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.UITests; + +public class TestBase +{ + private IApp? _app; + + static TestBase() + { + AppInitializer.TestEnvironment.AndroidAppName = Constants.AndroidAppName; + AppInitializer.TestEnvironment.WebAssemblyDefaultUri = Constants.WebAssemblyDefaultUri; + AppInitializer.TestEnvironment.iOSAppName = Constants.iOSAppName; + AppInitializer.TestEnvironment.AndroidAppName = Constants.AndroidAppName; + AppInitializer.TestEnvironment.iOSDeviceNameOrId = Constants.iOSDeviceNameOrId; + AppInitializer.TestEnvironment.CurrentPlatform = Constants.CurrentPlatform; + +#if DEBUG + AppInitializer.TestEnvironment.WebAssemblyHeadless = false; +#endif + + // Start the app only once, so the tests runs don't restart it + // and gain some time for the tests. + AppInitializer.ColdStartApp(); + } + + protected IApp App + { + get => _app!; + private set + { + _app = value; + Uno.UITest.Helpers.Queries.Helpers.App = value; + } + } + + [SetUp] + public void SetUpTest() + { + App = AppInitializer.AttachToApp(); + } + + [TearDown] + public void TearDownTest() + { + TakeScreenshot("teardown"); + } + + public FileInfo TakeScreenshot(string stepName) + { + var title = $"{TestContext.CurrentContext.Test.Name}_{stepName}" + .Replace(" ", "_") + .Replace(".", "_"); + + var fileInfo = App.Screenshot(title); + + var fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileInfo.Name); + if (fileNameWithoutExt != title && fileInfo.DirectoryName != null) + { + var destFileName = Path + .Combine(fileInfo.DirectoryName, title + Path.GetExtension(fileInfo.Name)); + + if (File.Exists(destFileName)) + { + File.Delete(destFileName); + } + + File.Move(fileInfo.FullName, destFileName); + + TestContext.AddTestAttachment(destFileName, stepName); + + fileInfo = new FileInfo(destFileName); + } + else + { + TestContext.AddTestAttachment(fileInfo.FullName, stepName); + } + + return fileInfo; + } + +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.UITests/UnoPlatformSample.UITests.csproj b/samples/UnoPlatformSample/UnoPlatformSample.UITests/UnoPlatformSample.UITests.csproj new file mode 100644 index 000000000..6ad4a57a2 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.UITests/UnoPlatformSample.UITests.csproj @@ -0,0 +1,16 @@ + + + + net7.0 + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/LinkerConfig.xml b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/LinkerConfig.xml new file mode 100644 index 000000000..df91b15b8 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/LinkerConfig.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Program.cs b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Program.cs new file mode 100644 index 000000000..b99a57482 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Program.cs @@ -0,0 +1,35 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Wasm; + +public class Program +{ + private static App? _app; + + public static int Main(string[] args) + { + Microsoft.UI.Xaml.Application.Start(_ => _app = new AppHead()); + + return 0; + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Properties/launchSettings.json b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Properties/launchSettings.json new file mode 100644 index 000000000..68ffba9ec --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/Properties/launchSettings.json @@ -0,0 +1,30 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:8080", + "sslPort": 0 + } + }, + "profiles": { + "UnoPlatformSample.Wasm": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5000", + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj new file mode 100644 index 000000000..d0fa69fb0 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/UnoPlatformSample.Wasm.csproj @@ -0,0 +1,91 @@ + + + Exe + net7.0 + $(NoWarn);NU1504;NU1505;NU1701 + + disable + manifest.webmanifest + Properties + + / + + + true + $(DefineConstants);TRACE;DEBUG + portable + true + + false + + + + + + + + + + + True + $(DefineConstants);USE_UITESTS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmCSS/Fonts.css b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmCSS/Fonts.css new file mode 100644 index 000000000..4fdd60555 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmCSS/Fonts.css @@ -0,0 +1,28 @@ +/** + When adding fonts here, make sure to add them using a base64 data uri, otherwise + fonts loading are delayed, and text may get displayed incorrectly. +*/ + +/* https://github.com/unoplatform/uno/issues/3954 */ +@font-face { + font-family: 'Segoe UI'; + src: local('Segoe UI'), local('-apple-system'), local('BlinkMacSystemFont'), local('Inter'), local('Cantarell'), local('Ubuntu'), local('Roboto'), local('Open Sans'), local('Noto Sans'), local('Helvetica Neue'), local('sans-serif'); +} + +@font-face { + font-family: 'Roboto'; + src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Light.ttf) format('truetype'); + font-weight: 300; +} + +@font-face { + font-family: 'Roboto'; + src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Regular.ttf) format('truetype'); + font-weight: 400; +} + +@font-face { + font-family: 'Roboto'; + src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Medium.ttf) format('truetype'); + font-weight: 500; +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmScripts/AppManifest.js b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmScripts/AppManifest.js new file mode 100644 index 000000000..df845f84a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/WasmScripts/AppManifest.js @@ -0,0 +1,3 @@ +var UnoAppManifest = { + displayName: "UnoPlatformSample" +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/manifest.webmanifest b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/manifest.webmanifest new file mode 100644 index 000000000..d6f24a1ac --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/manifest.webmanifest @@ -0,0 +1,10 @@ +{ + "background_color": "#ffffff", + "description": "UnoPlatformSample", + "display": "standalone", + "name": "UnoPlatformSample", + "short_name": "UnoPlatformSample", + "start_url": "/index.html", + "theme_color": "#ffffff", + "scope": "/" +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/staticwebapp.config.json b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/staticwebapp.config.json new file mode 100644 index 000000000..79c1b17c4 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/staticwebapp.config.json @@ -0,0 +1,30 @@ +{ + "navigationFallback": { + "rewrite": "/index.html", + "exclude": [ + "*.{css,js}", + "*.{png}", + "*.{c,h,wasm,clr,pdb,dat,txt}" + ] + }, + "routes": [ + { + "route": "/package_*", + "headers": { + "cache-control": "public, immutable, max-age=31536000" + } + }, + { + "route": "/*.ttf", + "headers": { + "cache-control": "public, immutable, max-age=31536000" + } + }, + { + "route": "/*", + "headers": { + "cache-control": "must-revalidate, max-age=3600" + } + } + ] +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/web.config b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/web.config new file mode 100644 index 000000000..8f5a860f5 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Wasm/wwwroot/web.config @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Package.appxmanifest b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Package.appxmanifest new file mode 100644 index 000000000..8eaafe69a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Package.appxmanifest @@ -0,0 +1,43 @@ + + + + + + + + UnoPlatformSample + UnoPlatformSample + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Properties/launchsettings.json b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Properties/launchsettings.json new file mode 100644 index 000000000..edd66b1e1 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Properties/launchsettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "UnoPlatformSample.Windows (Package)": { + "commandName": "MsixPackage" + }, + "UnoPlatformSample.Windows (Unpackaged)": { + "commandName": "Project" + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/Resources.lang-en-us.resw b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Resources.lang-en-us.resw new file mode 100644 index 000000000..fad04be56 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Windows/Resources.lang-en-us.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Hello World! + + \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/UnoPlatformSample.Windows.csproj b/samples/UnoPlatformSample/UnoPlatformSample.Windows/UnoPlatformSample.Windows.csproj new file mode 100644 index 000000000..0da388803 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Windows/UnoPlatformSample.Windows.csproj @@ -0,0 +1,91 @@ + + + WinExe + net7.0-windows10.0.19041.0 + 10.0.18362.0 + UnoPlatformSample.Windows + app.manifest + x86;x64;arm64 + win10-x86;win10-x64;win10-arm64 + win10-$(Platform).pubxml + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.Windows/app.manifest b/samples/UnoPlatformSample/UnoPlatformSample.Windows/app.manifest new file mode 100644 index 000000000..bf8c29ac0 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.Windows/app.manifest @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample.sln b/samples/UnoPlatformSample/UnoPlatformSample.sln new file mode 100644 index 000000000..e4d7a0e53 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample.sln @@ -0,0 +1,302 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34024.191 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{B9B91410-6F69-4DB0-A917-646B729F2467}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backend", "Backend", "{F075631F-6FB6-476C-8007-491F72A70B15}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{9852BF4B-DB31-4279-94C1-95343B48AD74}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{E58CD4B4-2B35-4D47-9AAD-34016C194D3F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.DataContracts", "UnoPlatformSample.DataContracts\UnoPlatformSample.DataContracts.csproj", "{B6C4869B-599D-441C-8AE2-83AA0BFB2107}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample", "UnoPlatformSample\UnoPlatformSample.csproj", "{5C5CC19E-F676-4440-82E3-B95B2761AFCF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Tests", "UnoPlatformSample.Tests\UnoPlatformSample.Tests.csproj", "{02579EDA-3AF9-42FE-9074-A8F45C51B1D4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.UITests", "UnoPlatformSample.UITests\UnoPlatformSample.UITests.csproj", "{CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Mobile", "UnoPlatformSample.Mobile\UnoPlatformSample.Mobile.csproj", "{84726BD4-BB63-476E-9BD5-8FEC6F773DF5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Windows", "UnoPlatformSample.Windows\UnoPlatformSample.Windows.csproj", "{0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Wasm", "UnoPlatformSample.Wasm\UnoPlatformSample.Wasm.csproj", "{8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Skia.Gtk", "UnoPlatformSample.Skia.Gtk\UnoPlatformSample.Skia.Gtk.csproj", "{420D448C-C768-4844-BD49-485B9CD3116D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.Server", "UnoPlatformSample.Server\UnoPlatformSample.Server.csproj", "{0DDD817E-0368-4477-AEA0-7760F8B22C70}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LiveChartsSource", "LiveChartsSource", "{98754DD8-C793-49EF-A506-F120FEBA666A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore", "..\..\src\LiveChartsCore\LiveChartsCore.csproj", "{BB328359-ECAC-4B7F-A2FE-972CC2C4944F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView", "..\..\src\skiasharp\LiveChartsCore.SkiaSharp\LiveChartsCore.SkiaSharpView.csproj", "{C3C321D8-3CA3-4714-AFF3-B71A3B819E08}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "..\..\src\skiasharp\LiveChartsCore.SkiaSharpView.UnoWinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewModelsSamples", "..\ViewModelsSamples\ViewModelsSamples.csproj", "{EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|arm64 = Debug|arm64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|arm64 = Release|arm64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Debug|arm64.ActiveCfg = Debug|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Debug|arm64.Build.0 = Debug|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Debug|x64.ActiveCfg = Debug|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Debug|x64.Build.0 = Debug|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Debug|x86.ActiveCfg = Debug|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Debug|x86.Build.0 = Debug|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Release|Any CPU.Build.0 = Release|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Release|arm64.ActiveCfg = Release|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Release|arm64.Build.0 = Release|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Release|x64.ActiveCfg = Release|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Release|x64.Build.0 = Release|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Release|x86.ActiveCfg = Release|Any CPU + {B6C4869B-599D-441C-8AE2-83AA0BFB2107}.Release|x86.Build.0 = Release|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Debug|arm64.ActiveCfg = Debug|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Debug|arm64.Build.0 = Debug|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Debug|x64.ActiveCfg = Debug|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Debug|x64.Build.0 = Debug|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Debug|x86.ActiveCfg = Debug|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Debug|x86.Build.0 = Debug|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Release|Any CPU.Build.0 = Release|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Release|arm64.ActiveCfg = Release|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Release|arm64.Build.0 = Release|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Release|x64.ActiveCfg = Release|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Release|x64.Build.0 = Release|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Release|x86.ActiveCfg = Release|Any CPU + {5C5CC19E-F676-4440-82E3-B95B2761AFCF}.Release|x86.Build.0 = Release|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Debug|arm64.ActiveCfg = Debug|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Debug|arm64.Build.0 = Debug|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Debug|x64.ActiveCfg = Debug|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Debug|x64.Build.0 = Debug|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Debug|x86.ActiveCfg = Debug|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Debug|x86.Build.0 = Debug|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Release|Any CPU.Build.0 = Release|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Release|arm64.ActiveCfg = Release|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Release|arm64.Build.0 = Release|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Release|x64.ActiveCfg = Release|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Release|x64.Build.0 = Release|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Release|x86.ActiveCfg = Release|Any CPU + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4}.Release|x86.Build.0 = Release|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Debug|arm64.ActiveCfg = Debug|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Debug|arm64.Build.0 = Debug|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Debug|x64.ActiveCfg = Debug|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Debug|x64.Build.0 = Debug|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Debug|x86.ActiveCfg = Debug|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Debug|x86.Build.0 = Debug|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Release|Any CPU.Build.0 = Release|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Release|arm64.ActiveCfg = Release|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Release|arm64.Build.0 = Release|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Release|x64.ActiveCfg = Release|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Release|x64.Build.0 = Release|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Release|x86.ActiveCfg = Release|Any CPU + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028}.Release|x86.Build.0 = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|arm64.ActiveCfg = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|arm64.Build.0 = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|arm64.Deploy.0 = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|x64.ActiveCfg = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|x64.Build.0 = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|x64.Deploy.0 = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|x86.ActiveCfg = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|x86.Build.0 = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Debug|x86.Deploy.0 = Debug|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|Any CPU.Build.0 = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|Any CPU.Deploy.0 = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|arm64.ActiveCfg = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|arm64.Build.0 = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|arm64.Deploy.0 = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|x64.ActiveCfg = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|x64.Build.0 = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|x64.Deploy.0 = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|x86.ActiveCfg = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|x86.Build.0 = Release|Any CPU + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5}.Release|x86.Deploy.0 = Release|Any CPU + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|Any CPU.ActiveCfg = Debug|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|Any CPU.Build.0 = Debug|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|Any CPU.Deploy.0 = Debug|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|arm64.ActiveCfg = Debug|arm64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|arm64.Build.0 = Debug|arm64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|arm64.Deploy.0 = Debug|arm64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|x64.ActiveCfg = Debug|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|x64.Build.0 = Debug|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|x64.Deploy.0 = Debug|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|x86.ActiveCfg = Debug|x86 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|x86.Build.0 = Debug|x86 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Debug|x86.Deploy.0 = Debug|x86 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|Any CPU.ActiveCfg = Release|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|Any CPU.Build.0 = Release|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|Any CPU.Deploy.0 = Release|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|arm64.ActiveCfg = Release|arm64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|arm64.Build.0 = Release|arm64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|arm64.Deploy.0 = Release|arm64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|x64.ActiveCfg = Release|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|x64.Build.0 = Release|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|x64.Deploy.0 = Release|x64 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|x86.ActiveCfg = Release|x86 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|x86.Build.0 = Release|x86 + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA}.Release|x86.Deploy.0 = Release|x86 + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Debug|arm64.ActiveCfg = Debug|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Debug|arm64.Build.0 = Debug|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Debug|x64.ActiveCfg = Debug|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Debug|x64.Build.0 = Debug|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Debug|x86.ActiveCfg = Debug|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Debug|x86.Build.0 = Debug|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Release|Any CPU.Build.0 = Release|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Release|arm64.ActiveCfg = Release|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Release|arm64.Build.0 = Release|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Release|x64.ActiveCfg = Release|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Release|x64.Build.0 = Release|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Release|x86.ActiveCfg = Release|Any CPU + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64}.Release|x86.Build.0 = Release|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Debug|arm64.ActiveCfg = Debug|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Debug|arm64.Build.0 = Debug|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Debug|x64.ActiveCfg = Debug|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Debug|x64.Build.0 = Debug|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Debug|x86.ActiveCfg = Debug|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Debug|x86.Build.0 = Debug|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Release|Any CPU.Build.0 = Release|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Release|arm64.ActiveCfg = Release|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Release|arm64.Build.0 = Release|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Release|x64.ActiveCfg = Release|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Release|x64.Build.0 = Release|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Release|x86.ActiveCfg = Release|Any CPU + {420D448C-C768-4844-BD49-485B9CD3116D}.Release|x86.Build.0 = Release|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Debug|arm64.ActiveCfg = Debug|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Debug|arm64.Build.0 = Debug|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Debug|x64.ActiveCfg = Debug|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Debug|x64.Build.0 = Debug|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Debug|x86.ActiveCfg = Debug|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Debug|x86.Build.0 = Debug|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Release|Any CPU.Build.0 = Release|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Release|arm64.ActiveCfg = Release|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Release|arm64.Build.0 = Release|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Release|x64.ActiveCfg = Release|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Release|x64.Build.0 = Release|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Release|x86.ActiveCfg = Release|Any CPU + {0DDD817E-0368-4477-AEA0-7760F8B22C70}.Release|x86.Build.0 = Release|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Debug|arm64.ActiveCfg = Debug|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Debug|arm64.Build.0 = Debug|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Debug|x64.ActiveCfg = Debug|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Debug|x64.Build.0 = Debug|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Debug|x86.ActiveCfg = Debug|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Debug|x86.Build.0 = Debug|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Release|Any CPU.Build.0 = Release|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Release|arm64.ActiveCfg = Release|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Release|arm64.Build.0 = Release|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Release|x64.ActiveCfg = Release|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Release|x64.Build.0 = Release|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Release|x86.ActiveCfg = Release|Any CPU + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F}.Release|x86.Build.0 = Release|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Debug|arm64.ActiveCfg = Debug|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Debug|arm64.Build.0 = Debug|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Debug|x64.ActiveCfg = Debug|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Debug|x64.Build.0 = Debug|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Debug|x86.ActiveCfg = Debug|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Debug|x86.Build.0 = Debug|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|Any CPU.Build.0 = Release|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|arm64.ActiveCfg = Release|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|arm64.Build.0 = Release|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|x64.ActiveCfg = Release|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|x64.Build.0 = Release|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|x86.ActiveCfg = Release|Any CPU + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|x86.Build.0 = Release|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|arm64.ActiveCfg = Debug|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|arm64.Build.0 = Debug|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|x64.ActiveCfg = Debug|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|x64.Build.0 = Debug|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|x86.ActiveCfg = Debug|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|x86.Build.0 = Debug|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|Any CPU.Build.0 = Release|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|arm64.ActiveCfg = Release|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|arm64.Build.0 = Release|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|x64.ActiveCfg = Release|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|x64.Build.0 = Release|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|x86.ActiveCfg = Release|Any CPU + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|x86.Build.0 = Release|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|arm64.ActiveCfg = Debug|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|arm64.Build.0 = Debug|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|x64.ActiveCfg = Debug|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|x64.Build.0 = Debug|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|x86.ActiveCfg = Debug|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|x86.Build.0 = Debug|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|Any CPU.Build.0 = Release|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|arm64.ActiveCfg = Release|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|arm64.Build.0 = Release|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|x64.ActiveCfg = Release|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|x64.Build.0 = Release|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|x86.ActiveCfg = Release|Any CPU + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F075631F-6FB6-476C-8007-491F72A70B15} = {B9B91410-6F69-4DB0-A917-646B729F2467} + {9852BF4B-DB31-4279-94C1-95343B48AD74} = {B9B91410-6F69-4DB0-A917-646B729F2467} + {B6C4869B-599D-441C-8AE2-83AA0BFB2107} = {B9B91410-6F69-4DB0-A917-646B729F2467} + {5C5CC19E-F676-4440-82E3-B95B2761AFCF} = {B9B91410-6F69-4DB0-A917-646B729F2467} + {02579EDA-3AF9-42FE-9074-A8F45C51B1D4} = {E58CD4B4-2B35-4D47-9AAD-34016C194D3F} + {CD652080-C1B8-4A5F-B97B-7E8C6B9D5028} = {E58CD4B4-2B35-4D47-9AAD-34016C194D3F} + {84726BD4-BB63-476E-9BD5-8FEC6F773DF5} = {9852BF4B-DB31-4279-94C1-95343B48AD74} + {0DDEDE21-68A8-4DE4-A001-68AB730EF7EA} = {9852BF4B-DB31-4279-94C1-95343B48AD74} + {8DF1ECC6-36DC-45FE-8A5E-10A9E1123F64} = {9852BF4B-DB31-4279-94C1-95343B48AD74} + {420D448C-C768-4844-BD49-485B9CD3116D} = {9852BF4B-DB31-4279-94C1-95343B48AD74} + {0DDD817E-0368-4477-AEA0-7760F8B22C70} = {F075631F-6FB6-476C-8007-491F72A70B15} + {BB328359-ECAC-4B7F-A2FE-972CC2C4944F} = {98754DD8-C793-49EF-A506-F120FEBA666A} + {C3C321D8-3CA3-4714-AFF3-B71A3B819E08} = {98754DD8-C793-49EF-A506-F120FEBA666A} + {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2} = {98754DD8-C793-49EF-A506-F120FEBA666A} + {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669} = {B9B91410-6F69-4DB0-A917-646B729F2467} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4C6F8CF1-CF97-4BED-9F5B-F97F15C166EC} + EndGlobalSection +EndGlobal diff --git a/samples/UnoPlatformSample/UnoPlatformSample/App.cs b/samples/UnoPlatformSample/UnoPlatformSample/App.cs new file mode 100644 index 000000000..086b71978 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/App.cs @@ -0,0 +1,129 @@ +using LiveChartsCore; // mark +using LiveChartsCore.SkiaSharpView; // mark +using SkiaSharp; // mark + +namespace UnoPlatformSample; + +public class App : Application +{ + protected Window? MainWindow { get; private set; } + protected IHost? Host { get; private set; } + public record City(string Name, double Population); + + protected async override void OnLaunched(LaunchActivatedEventArgs args) + { + LiveCharts.Configure(config => // mark + config // mark + // you can override the theme + // .AddDarkTheme() // mark + + // In case you need a non-Latin based font, you must register a typeface for SkiaSharp + //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('汉')) // <- Chinese // mark + //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('あ')) // <- Japanese // mark + //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('헬')) // <- Korean // mark + //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('Ж')) // <- Russian // mark + + //.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('أ')) // <- Arabic // mark + //.UseRightToLeftSettings() // Enables right to left tooltips // mark + + // finally register your own mappers + // you can learn more about mappers at: + // https://livecharts.dev/docs/{{ platform }}/{{ version }}/Overview.Mappers + .HasMap((city, point) => // mark + { // mark + // here we use the index as X, and the population as Y // mark + point.Coordinate = new(point.Index, city.Population); // mark + }) // mark + // .HasMap( .... ) // mark + // .HasMap( .... ) // mark + ); // mark + + + var builder = this.CreateBuilder(args) + // Add navigation support for toolkit controls such as TabBar and NavigationView + .UseToolkitNavigation() + .Configure(host => host +#if DEBUG + // Switch to Development environment when running in DEBUG + .UseEnvironment(Environments.Development) +#endif + .UseLogging(configure: (context, logBuilder) => + { + // Configure log levels for different categories of logging + logBuilder + .SetMinimumLevel( + context.HostingEnvironment.IsDevelopment() ? + LogLevel.Information : + LogLevel.Warning) + + // Default filters for core Uno Platform namespaces + .CoreLogLevel(LogLevel.Warning); + + // Uno Platform namespace filter groups + // Uncomment individual methods to see more detailed logging + //// Generic Xaml events + //logBuilder.XamlLogLevel(LogLevel.Debug); + //// Layouter specific messages + //logBuilder.XamlLayoutLogLevel(LogLevel.Debug); + //// Storage messages + //logBuilder.StorageLogLevel(LogLevel.Debug); + //// Binding related messages + //logBuilder.XamlBindingLogLevel(LogLevel.Debug); + //// Binder memory references tracking + //logBuilder.BinderMemoryReferenceLogLevel(LogLevel.Debug); + //// RemoteControl and HotReload related + //logBuilder.HotReloadCoreLogLevel(LogLevel.Information); + //// Debug JS interop + //logBuilder.WebAssemblyLogLevel(LogLevel.Debug); + + }, enableUnoLogging: true) + .UseConfiguration(configure: configBuilder => + configBuilder + .EmbeddedSource() + .Section() + ) + // Enable localization (see appsettings.json for supported languages) + .UseLocalization() + // Register Json serializers (ISerializer and ISerializer) + .UseSerialization((context, services) => services + .AddContentSerializer(context) + .AddJsonTypeInfo(WeatherForecastContext.Default.IImmutableListWeatherForecast)) + .UseHttp((context, services) => services + // Register HttpClient +#if DEBUG + // DelegatingHandler will be automatically injected into Refit Client + .AddTransient() +#endif + .AddSingleton() + .AddRefitClient(context)) + .ConfigureServices((context, services) => + { + // TODO: Register your services + //services.AddSingleton(); + }) + .UseNavigation(ReactiveViewModelMappings.ViewModelMappings, RegisterRoutes) + ); + MainWindow = builder.Window; + + Host = await builder.NavigateAsync(); + } + + private static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes) + { + views.Register( + new ViewMap(ViewModel: typeof(ShellModel)), + new ViewMap(), + new DataViewMap() + ); + + routes.Register( + new RouteMap("", View: views.FindByViewModel(), + Nested: new RouteMap[] + { + new RouteMap("Main", View: views.FindByViewModel()), + new RouteMap("Second", View: views.FindByViewModel()), + } + ) + ); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/AppResources.xaml b/samples/UnoPlatformSample/UnoPlatformSample/AppResources.xaml new file mode 100644 index 000000000..4e8f2bad1 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/AppResources.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Assets/Icons/back.svg b/samples/UnoPlatformSample/UnoPlatformSample/Assets/Icons/back.svg new file mode 100644 index 000000000..bcd7851b9 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Assets/Icons/back.svg @@ -0,0 +1,3 @@ + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Assets/SharedAssets.md b/samples/UnoPlatformSample/UnoPlatformSample/Assets/SharedAssets.md new file mode 100644 index 000000000..6d84997f1 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Assets/SharedAssets.md @@ -0,0 +1,34 @@ +See documentation about assets here : https://github.com/unoplatform/uno/blob/master/doc/articles/features/working-with-assets.md + +# Here is a cheat sheet: + +1. Add the image file to the `Assets` directory of a shared project. +2. Set the build action to `Content`. +3. (Recommended) Provide an asset for various scales/dpi + +## Examples + +``` +\Assets\Images\logo.scale-100.png +\Assets\Images\logo.scale-200.png +\Assets\Images\logo.scale-400.png + +\Assets\Images\scale-100\logo.png +\Assets\Images\scale-200\logo.png +\Assets\Images\scale-400\logo.png +``` + +## Table of scales + +| Scale | UWP | iOS | Android | +|-------|:-----------:|:--------:|:-------:| +| `100` | scale-100 | @1x | mdpi | +| `125` | scale-125 | N/A | N/A | +| `150` | scale-150 | N/A | hdpi | +| `200` | scale-200 | @2x | xhdpi | +| `300` | scale-300 | @3x | xxhdpi | +| `400` | scale-400 | N/A | xxxhdpi | + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/AppConfig.cs b/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/AppConfig.cs new file mode 100644 index 000000000..2106e7560 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/AppConfig.cs @@ -0,0 +1,28 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Business.Models; + +public record AppConfig +{ + public string? Environment { get; init; } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/Entity.cs b/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/Entity.cs new file mode 100644 index 000000000..661c4f5ae --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Business/Models/Entity.cs @@ -0,0 +1,25 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Business.Models; + +public record Entity(string Name); diff --git a/samples/UnoPlatformSample/UnoPlatformSample/GlobalUsings.cs b/samples/UnoPlatformSample/UnoPlatformSample/GlobalUsings.cs new file mode 100644 index 000000000..457ebaade --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/GlobalUsings.cs @@ -0,0 +1,54 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +global using System.Collections.Immutable; +global using System.Windows.Input; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Localization; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using Microsoft.UI.Xaml; +global using Microsoft.UI.Xaml.Controls; +global using Microsoft.UI.Xaml.Media; +global using Microsoft.UI.Xaml.Navigation; +global using Refit; +global using Uno.Extensions; +global using Uno.Extensions.Configuration; +global using Uno.Extensions.Hosting; +global using Uno.Extensions.Http; +global using Uno.Extensions.Localization; +global using Uno.Extensions.Logging; +global using Uno.Extensions.Navigation; +global using Uno.Extensions.Reactive; +global using Uno.Extensions.Serialization; +global using UnoPlatformSample.Business.Models; +global using UnoPlatformSample.DataContracts; +global using UnoPlatformSample.DataContracts.Serialization; +global using UnoPlatformSample.Infrastructure; +global using UnoPlatformSample.Presentation; +global using UnoPlatformSample.Services.Caching; +global using UnoPlatformSample.Services.Endpoints; +global using Windows.ApplicationModel; +global using Windows.Networking.Connectivity; +global using Windows.Storage; +global using ApplicationExecutionState = Windows.ApplicationModel.Activation.ApplicationExecutionState; diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Infrastructure/DebugHandler.cs b/samples/UnoPlatformSample/UnoPlatformSample/Infrastructure/DebugHandler.cs new file mode 100644 index 000000000..1cd7130f1 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Infrastructure/DebugHandler.cs @@ -0,0 +1,63 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Infrastructure; + +internal class DebugHttpHandler : DelegatingHandler +{ + private readonly ILogger _logger; + + public DebugHttpHandler(ILogger logger, HttpMessageHandler? innerHandler = null) + : base(innerHandler ?? new HttpClientHandler()) + { + _logger = logger; + } + + protected async override Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + { + var response = await base.SendAsync(request, cancellationToken); +#if DEBUG + if(!response.IsSuccessStatusCode) + { + _logger.LogDebugMessage("Unsuccessful API Call"); + if(request.RequestUri is not null) + _logger.LogDebugMessage($"{request.RequestUri} ({request.Method})"); + foreach((var key, var values) in request.Headers.ToDictionary(x => x.Key, x => string.Join(", ", x.Value))) + { + _logger.LogDebugMessage($"{key}: {values}"); + } + + var content = request.Content is not null ? await request.Content.ReadAsStringAsync() : null; + if(!string.IsNullOrEmpty(content)) + { + _logger.LogDebugMessage(content); + } + + // Uncomment to automatically break when an API call fails while debugging + // System.Diagnostics.Debugger.Break(); + } +#endif + return response; + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml new file mode 100644 index 000000000..3a5bf2843 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml.cs new file mode 100644 index 000000000..2585ad11a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/ColorsAndPosition/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.ColorsAndPosition; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml new file mode 100644 index 000000000..50740a29e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml.cs new file mode 100644 index 000000000..382f6287c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Crosshairs/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.Crosshairs; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml new file mode 100644 index 000000000..de2c8c0fb --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml.cs new file mode 100644 index 000000000..9dcfdf2bd --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/CustomSeparatorsInterval/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.CustomSeparatorsInterval; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml new file mode 100644 index 000000000..cd2820427 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml.cs new file mode 100644 index 000000000..aa27bc19b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/DateTimeScaled/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.DateTimeScaled; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml new file mode 100644 index 000000000..0386813ba --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml.cs new file mode 100644 index 000000000..a534423db --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.LabelsFormat; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml new file mode 100644 index 000000000..a8e50d907 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml.cs new file mode 100644 index 000000000..9f544f827 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsFormat2/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.LabelsFormat2; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml new file mode 100644 index 000000000..ae2efe8c5 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml.cs new file mode 100644 index 000000000..9709b4f8b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/LabelsRotation/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.LabelsRotation; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml new file mode 100644 index 000000000..d95e9cb7c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml.cs new file mode 100644 index 000000000..47912b900 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Logarithmic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.Logarithmic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml new file mode 100644 index 000000000..cdb504641 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml.cs new file mode 100644 index 000000000..f6b9b2806 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Multiple/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.Multiple; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml new file mode 100644 index 000000000..014b06401 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml.cs new file mode 100644 index 000000000..72d9a2e45 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/NamedLabels/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.NamedLabels; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml new file mode 100644 index 000000000..a90e90180 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml.cs new file mode 100644 index 000000000..996d8fb51 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Paging/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.Paging; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml new file mode 100644 index 000000000..7f5030cef --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml.cs new file mode 100644 index 000000000..dd75d46ac --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Shared/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.Shared; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml new file mode 100644 index 000000000..a07527a77 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml.cs new file mode 100644 index 000000000..83e4fad4d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/Style/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.Style; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml new file mode 100644 index 000000000..98fdba24c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml.cs new file mode 100644 index 000000000..76238c8a2 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Axes/TimeSpanScaled/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Axes.TimeSpanScaled; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml new file mode 100644 index 000000000..0c18fafae --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml.cs new file mode 100644 index 000000000..130129262 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/AutoUpdate/View.xaml.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using ViewModelsSamples.Bars.AutoUpdate; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +namespace UnoWinUISample.Bars.AutoUpdate; + +public sealed partial class View : UserControl +{ + private bool? _isStreaming = false; + + public View() + { + InitializeComponent(); + } + + private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) + { + var vm = (ViewModel)DataContext; + _isStreaming = _isStreaming is null ? true : !_isStreaming; + + while (_isStreaming.Value) + { + vm.RemoveItem(); + vm.AddItem(); + await Task.Delay(1000); + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml new file mode 100644 index 000000000..a60aeab48 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml.cs new file mode 100644 index 000000000..9814f8f92 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Bars.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml new file mode 100644 index 000000000..ca6e7d101 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml.cs new file mode 100644 index 000000000..6888aee9d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Custom/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Bars.Custom; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml new file mode 100644 index 000000000..ad7fecf0d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml.cs new file mode 100644 index 000000000..4b624be0b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/DelayedAnimation/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Bars.DelayedAnimation; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml new file mode 100644 index 000000000..6b9c4031e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml.cs new file mode 100644 index 000000000..453c9e62f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Layered/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Bars.Layered; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml new file mode 100644 index 000000000..3357be175 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml.cs new file mode 100644 index 000000000..bd81a4a60 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Race/View.xaml.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using ViewModelsSamples.Bars.Race; +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Bars.Race; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml new file mode 100644 index 000000000..8b6d8291f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml.cs new file mode 100644 index 000000000..f80d92559 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/RowsWithLabels/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Bars.RowsWithLabels; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml new file mode 100644 index 000000000..49049ed7b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml.cs new file mode 100644 index 000000000..e9fb41343 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/Spacing/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Bars.Spacing; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml new file mode 100644 index 000000000..70c639b25 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml.cs new file mode 100644 index 000000000..4aa121455 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Bars/WithBackground/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Bars.WithBackground; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml new file mode 100644 index 000000000..0dedab919 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml.cs new file mode 100644 index 000000000..995e859d6 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Box/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Box.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml new file mode 100644 index 000000000..10c989a13 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml.cs new file mode 100644 index 000000000..fd33321a9 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/LinearGradients/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Design.LinearGradients; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml new file mode 100644 index 000000000..210d8ddc7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml.cs new file mode 100644 index 000000000..a0e4c0132 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/RadialGradients/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Design.RadialGradients; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml new file mode 100644 index 000000000..cff20ab25 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml.cs new file mode 100644 index 000000000..475957f9f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Design/StrokeDashArray/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Design.StrokeDashArray; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml new file mode 100644 index 000000000..e56953ced --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml.cs new file mode 100644 index 000000000..77f197bd0 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Error/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Error.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml new file mode 100644 index 000000000..4ed1ac64b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml.cs new file mode 100644 index 000000000..10e774723 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/AddPointOnClick/View.xaml.cs @@ -0,0 +1,14 @@ +using LiveChartsCore.Defaults; +using LiveChartsCore.Drawing; +using ViewModelsSamples.Events.AddPointOnClick; +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Events.AddPointOnClick; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml new file mode 100644 index 000000000..ef5a12eb8 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml.cs new file mode 100644 index 000000000..202da84a5 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Cartesian/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Events.Cartesian; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml new file mode 100644 index 000000000..dab2c85c5 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml.cs new file mode 100644 index 000000000..66473207e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Pie/View.xaml.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Diagnostics; +using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; +using ViewModelsSamples.Events.Pie; +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Events.Pie; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } + + private void Chart_DataPointerDown( + IChartView chart, + IEnumerable points) + { + // notice in the chart event we are not able to use strongly typed points + // but we can cast the point.Context.DataSource to the actual type. + + foreach (var point in points) + { + if (point.Context.DataSource is City city) + { + Trace.WriteLine($"[chart.dataPointerDownEvent] clicked on {city.Name}"); + continue; + } + + if (point.Context.DataSource is int integer) + { + Trace.WriteLine($"[chart.dataPointerDownEvent] clicked on number {integer}"); + continue; + } + + // handle more possible types here... + // if (point.Context.DataSource is Foo foo) + // { + // ... + // } + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml new file mode 100644 index 000000000..f4b4b11f9 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml.cs new file mode 100644 index 000000000..07fc232c9 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Events/Polar/View.xaml.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Diagnostics; +using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; +using ViewModelsSamples.Events.Polar; +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Events.Polar; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } + + private void Chart_DataPointerDown( + IChartView chart, + IEnumerable points) + { + // notice in the chart event we are not able to use strongly typed points + // but we can cast the point.Context.DataSource to the actual type. + + foreach (var point in points) + { + if (point.Context.DataSource is City city) + { + Trace.WriteLine($"[chart.dataPointerDownEvent] clicked on {city.Name}"); + continue; + } + + if (point.Context.DataSource is int integer) + { + Trace.WriteLine($"[chart.dataPointerDownEvent] clicked on number {integer}"); + continue; + } + + // handle more possible types here... + // if (point.Context.DataSource is Foo foo) + // { + // ... + // } + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml new file mode 100644 index 000000000..cd532f5b7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml.cs new file mode 100644 index 000000000..02d3a1db7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Financial/BasicCandlesticks/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Financial.BasicCandlesticks; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml new file mode 100644 index 000000000..402e6b815 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml.cs new file mode 100644 index 000000000..0eee21d83 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Animations/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.Animations; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml new file mode 100644 index 000000000..a3df71a7f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml.cs new file mode 100644 index 000000000..cedc0af70 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ChartToImage/View.xaml.cs @@ -0,0 +1,47 @@ +using LiveChartsCore.SkiaSharpView.SKCharts; +using LiveChartsCore.SkiaSharpView.WinUI; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml; + +namespace UnoWinUISample.General.ChartToImage; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + + // in this case, when the view is loaded // mark + // we render our chart controls as images // mark + Loaded += View_Loaded; + } + + private void View_Loaded(object? sender, RoutedEventArgs e) + { + CreateImageFromCartesianControl(); + CreateImageFromPieControl(); + CreateImageFromGeoControl(); + } + + private void CreateImageFromCartesianControl() + { + // you can take any chart in the UI, and build an image from it // mark + var chartControl = (CartesianChart)FindName("cartesianChart"); + var skChart = new SKCartesianChart(chartControl) { Width = 900, Height = 600, }; + skChart.SaveImage("CartesianImageFromControl.png"); + } + + private void CreateImageFromPieControl() + { + var chartControl = (PieChart)FindName("pieChart"); + var skChart = new SKPieChart(chartControl) { Width = 900, Height = 600, }; + skChart.SaveImage("PieImageFromControl.png"); + } + + private void CreateImageFromGeoControl() + { + var chartControl = (GeoMap)FindName("geoChart"); + var skChart = new SKGeoMap(chartControl) { Width = 900, Height = 600, }; + skChart.SaveImage("MapImageFromControl.png"); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml new file mode 100644 index 000000000..44750fe66 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml.cs new file mode 100644 index 000000000..72c778e46 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/ConditionalDraw/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.ConditionalDraw; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml new file mode 100644 index 000000000..dd4704f63 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml.cs new file mode 100644 index 000000000..100bec92e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Legends/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.Legends; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml new file mode 100644 index 000000000..b800ce314 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml.cs new file mode 100644 index 000000000..74f447e96 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MapPoints/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.MapPoints; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml new file mode 100644 index 000000000..63e6c7ae3 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml.cs new file mode 100644 index 000000000..8a33b1903 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.MultiThreading; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml new file mode 100644 index 000000000..63dd5bb17 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml.cs new file mode 100644 index 000000000..c951bc0f0 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/MultiThreading2/View.xaml.cs @@ -0,0 +1,28 @@ +using System; +using Microsoft.UI.Xaml.Controls; +using ViewModelsSamples.General.MultiThreading2; + +namespace UnoWinUISample.General.MultiThreading2; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + + var vm = new ViewModel(InvokeOnUIThread); + DataContext = vm; + } + + // this method takes another function as an argument. + // the idea is that we are invoking the passed action in the UI thread + // but the UI framework will let the view model how to do this. + // we will pass the InvokeOnUIThread method to our view model so the view model knows how + // to invoke an action in the UI thred. + private void InvokeOnUIThread(Action action) + { + // the InvokeOnUIThread method provided by livecharts is a simple helper class + // that handles the invoke in the multiple platforms Uno supports. + LiveChartsCore.SkiaSharpView.WinUI.Helpers.UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml new file mode 100644 index 000000000..6e3999d8a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml.cs new file mode 100644 index 000000000..7f743809e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/NullPoints/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.NullPoints; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml new file mode 100644 index 000000000..81292eef7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml.cs new file mode 100644 index 000000000..812b3032c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/RealTime/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.RealTime; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml new file mode 100644 index 000000000..cfcdb7802 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml.cs new file mode 100644 index 000000000..49c12bf2a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Scrollable/View.xaml.cs @@ -0,0 +1,9 @@ +namespace UnoWinUISample.General.Scrollable; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml new file mode 100644 index 000000000..654dbbdd8 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml.cs new file mode 100644 index 000000000..72d4f3d2f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.Sections; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml new file mode 100644 index 000000000..ead9a91ee --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml.cs new file mode 100644 index 000000000..8c86ab55c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Sections2/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.Sections2; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml new file mode 100644 index 000000000..6c4faf2db --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml.cs new file mode 100644 index 000000000..23e27e5be --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedLegends/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.TemplatedLegends; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml new file mode 100644 index 000000000..6fd79eb8f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml.cs new file mode 100644 index 000000000..be1fa82ec --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/TemplatedTooltips/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.TemplatedTooltips; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml new file mode 100644 index 000000000..23750d091 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml.cs new file mode 100644 index 000000000..da0cee428 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Tooltips/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.Tooltips; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml new file mode 100644 index 000000000..96dc3bada --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml.cs new file mode 100644 index 000000000..5846c6a95 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/UserDefinedTypes/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.UserDefinedTypes; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml new file mode 100644 index 000000000..4f205423e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml.cs new file mode 100644 index 000000000..091505e2f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/Visibility/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.Visibility; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml new file mode 100644 index 000000000..b14e2a269 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml.cs new file mode 100644 index 000000000..70fbc4805 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/General/VisualElements/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.General.VisualElements; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml new file mode 100644 index 000000000..ccf290044 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml.cs new file mode 100644 index 000000000..f65ca9c22 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Heat/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Heat.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml new file mode 100644 index 000000000..4f1b434e7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml.cs new file mode 100644 index 000000000..204558cdf --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Area/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Lines.Area; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml new file mode 100644 index 000000000..5e97d3ad2 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml.cs new file mode 100644 index 000000000..4ab4830b9 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/AutoUpdate/View.xaml.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using ViewModelsSamples.Lines.AutoUpdate; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +namespace UnoWinUISample.Lines.AutoUpdate; + +public sealed partial class View : UserControl +{ + private bool? _isStreaming = false; + + public View() + { + InitializeComponent(); + } + + private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) + { + var vm = (ViewModel)DataContext; + _isStreaming = _isStreaming is null ? true : !_isStreaming; + + while (_isStreaming.Value) + { + vm.RemoveItem(); + vm.AddItem(); + await Task.Delay(1000); + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml new file mode 100644 index 000000000..336ac534e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml.cs new file mode 100644 index 000000000..e60788268 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Lines.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml new file mode 100644 index 000000000..04102680d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml.cs new file mode 100644 index 000000000..a706c4b1e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Custom/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Lines.Custom; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml new file mode 100644 index 000000000..716afc5d7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml.cs new file mode 100644 index 000000000..57e15db64 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Padding/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Lines.Padding; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml new file mode 100644 index 000000000..0004eb1fb --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml.cs new file mode 100644 index 000000000..76c3b305e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Properties/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Lines.Properties; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml new file mode 100644 index 000000000..a34fbfe01 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml.cs new file mode 100644 index 000000000..644e25c34 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Straight/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Lines.Straight; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml new file mode 100644 index 000000000..4e49c0153 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml.cs new file mode 100644 index 000000000..43ae2ae10 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/XY/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Lines.XY; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml new file mode 100644 index 000000000..beca3d2e8 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml.cs new file mode 100644 index 000000000..a7c447fed --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Lines/Zoom/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Lines.Zoom; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml new file mode 100644 index 000000000..2d01358c1 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml.cs new file mode 100644 index 000000000..f73ab2343 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Maps/World/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Maps.World; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml new file mode 100644 index 000000000..bd9b9fc16 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml.cs new file mode 100644 index 000000000..63f36b09a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AngularGauge/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.AngularGauge; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml new file mode 100644 index 000000000..616779106 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml.cs new file mode 100644 index 000000000..3dd01163f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/AutoUpdate/View.xaml.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using ViewModelsSamples.Pies.AutoUpdate; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +namespace UnoWinUISample.Pies.AutoUpdate; + +public sealed partial class View : UserControl +{ + private bool? _isStreaming = false; + + public View() + { + InitializeComponent(); + } + + private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) + { + var vm = (ViewModel)DataContext; + _isStreaming = _isStreaming is null ? true : !_isStreaming; + + while (_isStreaming.Value) + { + vm.RemoveSeries(); + vm.AddSeries(); + await Task.Delay(1000); + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml new file mode 100644 index 000000000..be0b554cb --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml.cs new file mode 100644 index 000000000..957fb5c4c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml new file mode 100644 index 000000000..c8a511287 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml.cs new file mode 100644 index 000000000..ca7b6cd68 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Custom/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Custom; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml new file mode 100644 index 000000000..e6c8b6dd2 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml.cs new file mode 100644 index 000000000..73b80aaca --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Doughnut/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Doughnut; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml new file mode 100644 index 000000000..7f6eca655 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml.cs new file mode 100644 index 000000000..7fb79cd4c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Gauge; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml new file mode 100644 index 000000000..2f974973f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml.cs new file mode 100644 index 000000000..a83518db2 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge1/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Gauge1; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml new file mode 100644 index 000000000..206a9416f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml.cs new file mode 100644 index 000000000..4db271ddf --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge2/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Gauge2; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml new file mode 100644 index 000000000..e96131aaf --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml.cs new file mode 100644 index 000000000..fa14dbf57 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge3/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Gauge3; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml new file mode 100644 index 000000000..0fb248dd3 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml.cs new file mode 100644 index 000000000..a3747cdf3 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge4/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Gauge4; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml new file mode 100644 index 000000000..2cfaed47f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml.cs new file mode 100644 index 000000000..4931fdb55 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauge5/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Gauge5; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml new file mode 100644 index 000000000..e2a0cf0c6 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml.cs new file mode 100644 index 000000000..c411740b3 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Gauges/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Gauges; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml new file mode 100644 index 000000000..320397055 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml.cs new file mode 100644 index 000000000..4663131a7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/NightingaleRose/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.NightingaleRose; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml new file mode 100644 index 000000000..56a3318a4 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml.cs new file mode 100644 index 000000000..49072dcf6 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Processing/View.xaml.cs @@ -0,0 +1,35 @@ +using System; +using LiveChartsCore.SkiaSharpView.Painting; +using Windows.UI; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Media; + +namespace UnoWinUISample.Pies.Processing; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} + +public class PaintTaskToBrushConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, string language) + { + var solidColor = (SolidColorPaint)value; + return new SolidColorBrush( + Color.FromArgb( + solidColor.Color.Alpha, + solidColor.Color.Red, + solidColor.Color.Green, + solidColor.Color.Blue)); + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml new file mode 100644 index 000000000..6092b802a --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml.cs new file mode 100644 index 000000000..1622dd189 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/Pushout/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.Pushout; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml new file mode 100644 index 000000000..649f54cd6 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml.cs new file mode 100644 index 000000000..5dea8731c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Polar.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml new file mode 100644 index 000000000..f2ddbc6a5 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml.cs new file mode 100644 index 000000000..3a34b930c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/Coordinates/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Polar.Coordinates; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml new file mode 100644 index 000000000..49cdc1464 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml.cs new file mode 100644 index 000000000..0dcffd9c3 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Polar/RadialArea/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Polar.RadialArea; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml new file mode 100644 index 000000000..9ea73c216 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml.cs new file mode 100644 index 000000000..19e8d55e5 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/AutoUpdate/View.xaml.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using ViewModelsSamples.Scatter.AutoUpdate; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +namespace UnoWinUISample.Scatter.AutoUpdate; + +public sealed partial class View : UserControl +{ + private bool? _isStreaming = false; + + public View() + { + InitializeComponent(); + } + + private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) + { + var vm = (ViewModel)DataContext; + _isStreaming = _isStreaming is null ? true : !_isStreaming; + + while (_isStreaming.Value) + { + vm.RemoveItem(); + vm.AddItem(); + await Task.Delay(1000); + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml new file mode 100644 index 000000000..202047df5 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml.cs new file mode 100644 index 000000000..8b6154f1b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Scatter.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml new file mode 100644 index 000000000..6fe5b96cc --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml.cs new file mode 100644 index 000000000..26b6685d7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Bubbles/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Scatter.Bubbles; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml new file mode 100644 index 000000000..56115d380 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml.cs new file mode 100644 index 000000000..f3b209098 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Scatter/Custom/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Scatter.Custom; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml new file mode 100644 index 000000000..e58dbac74 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml.cs new file mode 100644 index 000000000..ad8eeb104 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StackedArea.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml new file mode 100644 index 000000000..d23e9113b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml.cs new file mode 100644 index 000000000..254e2dca4 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedArea/StepArea/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StackedArea.StepArea; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml new file mode 100644 index 000000000..8f4a82e34 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml.cs new file mode 100644 index 000000000..59d6480e5 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StackedBars.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml new file mode 100644 index 000000000..962a535f0 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml.cs new file mode 100644 index 000000000..bf5bf2b96 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StackedBars/Groups/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StackedBars.Groups; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml new file mode 100644 index 000000000..8aefb074d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml.cs new file mode 100644 index 000000000..0fc725ad0 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Area/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StepLines.Area; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml new file mode 100644 index 000000000..85f01518c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml.cs new file mode 100644 index 000000000..b986705d4 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/AutoUpdate/View.xaml.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using ViewModelsSamples.StepLines.AutoUpdate; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +namespace UnoWinUISample.StepLines.AutoUpdate; + +public sealed partial class View : UserControl +{ + private bool? _isStreaming = false; + + public View() + { + InitializeComponent(); + } + + private async void Button_PointerPressed(object sender, PointerRoutedEventArgs e) + { + var vm = (ViewModel)DataContext; + _isStreaming = _isStreaming is null ? true : !_isStreaming; + + while (_isStreaming.Value) + { + vm.RemoveItem(); + vm.AddItem(); + await Task.Delay(1000); + } + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml new file mode 100644 index 000000000..17a07e6b0 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml.cs new file mode 100644 index 000000000..fa410e0ea --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Basic/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StepLines.Basic; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml new file mode 100644 index 000000000..404a264c8 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml.cs new file mode 100644 index 000000000..97c9c0af3 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Custom/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StepLines.Custom; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml new file mode 100644 index 000000000..7df82c379 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml.cs new file mode 100644 index 000000000..1b1a47669 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Properties/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StepLines.Properties; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml new file mode 100644 index 000000000..db1ed013b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml.cs new file mode 100644 index 000000000..1992367e9 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/StepLines/Zoom/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.StepLines.Zoom; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml new file mode 100644 index 000000000..97002bb1f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml.cs new file mode 100644 index 000000000..6d66bd20c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/UserControl1.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Test.Dispose; + +public sealed partial class UserControl1 : UserControl +{ + public UserControl1() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml new file mode 100644 index 000000000..9538c14db --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml.cs new file mode 100644 index 000000000..fa732a267 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Test/Dispose/View.xaml.cs @@ -0,0 +1,20 @@ +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +namespace UnoWinUISample.Test.Dispose; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + + // the event is not attached using xaml? + button.AddHandler(PointerPressedEvent, new PointerEventHandler(Button_PointerPressed2), true); + } + + private void Button_PointerPressed2(object sender, PointerRoutedEventArgs e) + { + content.Content = new UserControl1(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml new file mode 100644 index 000000000..9eb50de17 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml.cs new file mode 100644 index 000000000..512b032bc --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/DataTemplate/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.VisualTest.DataTemplate; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml new file mode 100644 index 000000000..01d47ca71 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml.cs new file mode 100644 index 000000000..22d994098 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/ReattachVisual/View.xaml.cs @@ -0,0 +1,30 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.VisualTest.ReattachVisual; + +public sealed partial class View : UserControl +{ + private bool _isInVisualTree = true; + + public View() + { + InitializeComponent(); + } + + private void Button_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) + { + if (_isInVisualTree) + { + _ = parent.Children.Remove(chart); + _ = parent.Children.Remove(pieChart); + _ = parent.Children.Remove(polarChart); + _isInVisualTree = false; + return; + } + + parent.Children.Add(chart); + parent.Children.Add(pieChart); + parent.Children.Add(polarChart); + _isInVisualTree = true; + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml new file mode 100644 index 000000000..86f62d929 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml.cs new file mode 100644 index 000000000..58f4dda9b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/Tabs/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.VisualTest.Tabs; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml new file mode 100644 index 000000000..7efad4b39 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml.cs new file mode 100644 index 000000000..b58e98f3d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/VisualTest/TwoChartsOneSeries/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.VisualTest.TwoChartsOneSeries; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainModel.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainModel.cs new file mode 100644 index 000000000..6faf3fcdd --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainModel.cs @@ -0,0 +1,28 @@ +using LiveChartsCore; +using LiveChartsCore.SkiaSharpView; +using Uno.Extensions.Reactive; + +namespace UnoPlatformSample.Presentation; +public partial record MainModel +{ + public string? Title { get; } + + public IState Name { get; } + + public MainModel( + INavigator navigator, + IStringLocalizer localizer) + { + _navigator = navigator; + Title = $"Main - {localizer["ApplicationName"]}"; + Name = State.Value(this, () => string.Empty); + } + + public async Task GoToSecond() + { + var name = await Name; + await _navigator.NavigateViewModelAsync(this, data: new Entity(name!)); + } + + private INavigator _navigator; +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml new file mode 100644 index 000000000..79c601576 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs new file mode 100644 index 000000000..91a8d4d8b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs @@ -0,0 +1,32 @@ +using Microsoft.UI.Xaml.Input; + +namespace UnoPlatformSample.Presentation; + +public sealed partial class MainPage : Page +{ + public MainPage() + { + this.InitializeComponent(); + + Samples = ViewModelsSamples.Index.Samples; + grid.DataContext = this; + + LoadSample("Design/LinearGradients"); + + } + + public string[] Samples { get; set; } + + private void Border_PointerPressed(object sender, PointerRoutedEventArgs e) + { + var ctx = (string)((FrameworkElement)sender).DataContext; + LoadSample(ctx); + } + + private void LoadSample(string route) + { + route = route.Replace('/', '.'); + var t = Type.GetType($"UnoWinUISample.{route}.View") ?? throw new FileNotFoundException($"{route} not found!"); + content.Content = Activator.CreateInstance(t); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondModel.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondModel.cs new file mode 100644 index 000000000..4c7be2989 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondModel.cs @@ -0,0 +1,27 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Presentation; + +public partial record SecondModel(Entity Entity) +{ +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml new file mode 100644 index 000000000..6ef332e50 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml.cs new file mode 100644 index 000000000..8200ed04b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/SecondPage.xaml.cs @@ -0,0 +1,32 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Presentation; + +public sealed partial class SecondPage : Page +{ + public SecondPage() + { + this.InitializeComponent(); + } +} + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml new file mode 100644 index 000000000..78781677c --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml.cs new file mode 100644 index 000000000..55b273f4f --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/Shell.xaml.cs @@ -0,0 +1,32 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Presentation; + +public sealed partial class Shell : UserControl, IContentControlProvider +{ + public Shell() + { + this.InitializeComponent(); + } + public ContentControl ContentControl => Splash; +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/ShellModel.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/ShellModel.cs new file mode 100644 index 000000000..cd7b73dec --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/ShellModel.cs @@ -0,0 +1,40 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Presentation; + +public class ShellModel +{ + private readonly INavigator _navigator; + + public ShellModel( + INavigator navigator) + { + _navigator = navigator; + _ = Start(); + } + + public async Task Start() + { + await _navigator.NavigateViewModelAsync(this); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/IWeatherCache.cs b/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/IWeatherCache.cs new file mode 100644 index 000000000..5ea584067 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/IWeatherCache.cs @@ -0,0 +1,28 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Services.Caching; + +public interface IWeatherCache +{ + ValueTask> GetForecast(CancellationToken token); +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/WeatherCache.cs b/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/WeatherCache.cs new file mode 100644 index 000000000..f3f1d9eb9 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Services/Caching/WeatherCache.cs @@ -0,0 +1,97 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Services.Caching; + +public sealed class WeatherCache : IWeatherCache +{ + private readonly IApiClient _api; + private readonly ISerializer _serializer; + private readonly ILogger _logger; + + public WeatherCache(IApiClient api, ISerializer serializer, ILogger logger) + { + _api = api; + _serializer = serializer; + _logger = logger; + } + + private bool IsConnected => NetworkInformation.GetInternetConnectionProfile().GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess; + + public async ValueTask> GetForecast(CancellationToken token) + { + var weatherText = await GetCachedWeather(); + if (!string.IsNullOrWhiteSpace(weatherText)) + { + return _serializer.FromString>(weatherText); + } + + if (!IsConnected) + { + _logger.LogWarning("App is offline and cannot connect to the API."); + throw new Exception("No internet connection"); + } + + var response = await _api.GetWeather(token); + + if (response.IsSuccessStatusCode && response.Content is not null) + { + var weather = response.Content; + await Save(weather, token); + return weather; + } + else if (response.Error is not null) + { + _logger.LogError(response.Error, "An error occurred while retrieving the latest Forecast."); + throw response.Error; + } + else + { + return ImmutableArray.Empty; + } + } + + private async ValueTask GetFile(CreationCollisionOption option) => + await ApplicationData.Current.TemporaryFolder.CreateFileAsync("weather.json", option); + + private async ValueTask GetCachedWeather() + { + var file = await GetFile(CreationCollisionOption.OpenIfExists); + var properties = await file.GetBasicPropertiesAsync(); + + // Reuse latest cache file if offline + // or if the file is less than 5 minutes old + if (IsConnected || DateTimeOffset.Now.AddMinutes(-5) > properties.DateModified) + { + return null; + } + + return await File.ReadAllTextAsync(file.Path); + } + + private async ValueTask Save(IImmutableList weather, CancellationToken token) + { + var weatherText = _serializer.ToString(weather); + var file = await GetFile(CreationCollisionOption.ReplaceExisting); + await File.WriteAllTextAsync(file.Path, weatherText); + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Services/Endpoints/IApiClient.cs b/samples/UnoPlatformSample/UnoPlatformSample/Services/Endpoints/IApiClient.cs new file mode 100644 index 000000000..85c0ca558 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Services/Endpoints/IApiClient.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace UnoPlatformSample.Services.Endpoints; + +[Headers("Content-Type: application/json")] +public interface IApiClient +{ + [Get("/api/weatherforecast")] + Task>> GetWeather(CancellationToken cancellationToken = default); +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Strings/en/Resources.resw b/samples/UnoPlatformSample/UnoPlatformSample/Strings/en/Resources.resw new file mode 100644 index 000000000..e54534102 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Strings/en/Resources.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + UnoPlatformSample-en + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Strings/es/Resources.resw b/samples/UnoPlatformSample/UnoPlatformSample/Strings/es/Resources.resw new file mode 100644 index 000000000..98c09cd2d --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Strings/es/Resources.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + UnoPlatformSample-es + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Strings/fr/Resources.resw b/samples/UnoPlatformSample/UnoPlatformSample/Strings/fr/Resources.resw new file mode 100644 index 000000000..9d7f9b16b --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Strings/fr/Resources.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + UnoPlatformSample-fr + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Strings/pt-BR/Resources.resw b/samples/UnoPlatformSample/UnoPlatformSample/Strings/pt-BR/Resources.resw new file mode 100644 index 000000000..e1ce2edb1 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Strings/pt-BR/Resources.resw @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + UnoPlatformSample-pt-BR + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.xaml new file mode 100644 index 000000000..2710b2912 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.xaml @@ -0,0 +1,65 @@ + + + + + #5946D2 + #FFFFFF + #E5DEFF + #170065 + #6B4EA2 + #FFFFFF + #EBDDFF + #1F182B + #0061A4 + #FFFFFF + #CFE4FF + #001D36 + #B3261E + #F9DEDC + #FFFFFF + #410E0B + #FCFBFF + #1C1B1F + #FFFFFF + #1C1B1F + #F3EFF5 + #8B8494 + #79747E + #F4EFF4 + #313033 + #C8BFFF + #5946D2 + #C9C5D0 + + + #C7BFFF + #2A009F + #4129BA + #E4DFFF + #CDC2DC + #332D41 + #433C52 + #EBDDFF + #9FCAFF + #003258 + #00497E + #D1E4FF + #FFB4AB + #93000A + #690005 + #FFDAD6 + #1C1B1F + #E5E1E6 + #302D38 + #E6E1E5 + #47464F + #C9C5D0 + #928F99 + #1C1B1F + #E6E1E5 + #2A009F + #544794 + #57545D + + + \ No newline at end of file diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.zip b/samples/UnoPlatformSample/UnoPlatformSample/Styles/ColorPaletteOverride.zip new file mode 100644 index 0000000000000000000000000000000000000000..dfac0a9d85660e9b75825dc27909894e739d47c7 GIT binary patch literal 5848 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 GqyGTNNW$m< literal 0 HcmV?d00001 diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Styles/MaterialFontsOverride.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Styles/MaterialFontsOverride.xaml new file mode 100644 index 000000000..385d65953 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/Styles/MaterialFontsOverride.xaml @@ -0,0 +1,8 @@ + + + ms-appx:///Uno.Fonts.Roboto/Fonts/Roboto-Light.ttf#Roboto + ms-appx:///Uno.Fonts.Roboto/Fonts/Roboto-Medium.ttf#Roboto + ms-appx:///Uno.Fonts.Roboto/Fonts/Roboto-Regular.ttf#Roboto + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj b/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj new file mode 100644 index 000000000..37b2015a7 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj @@ -0,0 +1,77 @@ + + + $(TargetFrameworks);net7.0-windows10.0.19041 + $(TargetFrameworks);net7.0;net7.0-ios;net7.0-android;net7.0-maccatalyst + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %(Filename) + + + + + + + + + + + + + + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/appsettings.development.json b/samples/UnoPlatformSample/UnoPlatformSample/appsettings.development.json new file mode 100644 index 000000000..a692bed41 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/appsettings.development.json @@ -0,0 +1,9 @@ +{ + "AppConfig": { + "Environment": "Development" + }, + "ApiClient": { + "Url": "https://localhost:5001", + "UseNativeHandler": true + } +} diff --git a/samples/UnoPlatformSample/UnoPlatformSample/appsettings.json b/samples/UnoPlatformSample/UnoPlatformSample/appsettings.json new file mode 100644 index 000000000..aa890ef1e --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/appsettings.json @@ -0,0 +1,16 @@ +{ + "AppConfig": { + "Environment": "Production" + }, + "ApiClient": { + "UseNativeHandler": true + }, + "LocalizationConfiguration": { + "Cultures": [ + "es", + "fr", + "pt-BR", + "en" + ] + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/AssemblyInfo.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/AssemblyInfo.cs new file mode 100644 index 000000000..9f5a39c7a --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/AssemblyInfo.cs @@ -0,0 +1,32 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System.Runtime.CompilerServices; +#if !DEBUG +using System.Reflection; + +[assembly: AssemblyKeyFile("./../../../LiveCharts.snk")] +[assembly: InternalsVisibleTo("LiveChartsCore.BackersPackage, PublicKey=0024000004800000940000000602000000240000525341310004000001000100d53791eaa0d98b405ca858f39169be6af36ceb7a1bca3ca76c6905fd22fddf8c5e4ef2778a5d7a77ad12f08da711fecfc44795c7923739a2acac946b3f1719a6dfc238695bc69cf5d959b3fb6bc4d18d57a97ff8ed897e6b22a6b8155401ee368d77431e74178104b4adca73520b058b9be28d4ec129beb54871778167afa5ce")] +#else +[assembly: InternalsVisibleTo("LiveChartsCore.BackersPackage")] +#endif + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml new file mode 100644 index 000000000..41bcfbc4a --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml @@ -0,0 +1,14 @@ + + + + + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs new file mode 100644 index 000000000..f6601147c --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs @@ -0,0 +1,947 @@ + +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Windows.Input; +using LiveChartsCore.Drawing; +using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Events; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Measure; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Drawing; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using LiveChartsCore.SkiaSharpView.WinUI.Helpers; +using LiveChartsCore.SkiaSharpView.Painting; +using Microsoft.UI.Input; +using LiveChartsCore.VisualElements; +using System.Linq; +using LiveChartsCore.SkiaSharpView.SKCharts; + +// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 + +namespace LiveChartsCore.SkiaSharpView.WinUI; + +/// +public sealed partial class CartesianChart : UserControl, ICartesianChartView +{ + #region fields + + private Chart? _core; + private MotionCanvas? _motionCanvas; + private readonly CollectionDeepObserver _seriesObserver; + private readonly CollectionDeepObserver _xObserver; + private readonly CollectionDeepObserver _yObserver; + private readonly CollectionDeepObserver> _sectionsObserver; + private readonly CollectionDeepObserver> _visualsObserver; + private DateTime _panLocketUntil; + + #endregion + + /// + /// Initializes a new instance of the class. + /// + public CartesianChart() + { + LiveCharts.Configure(config => config.UseDefaults()); + + InitializeComponent(); + + _seriesObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + _xObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + _yObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + _sectionsObserver = new CollectionDeepObserver>( + OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + _visualsObserver = new CollectionDeepObserver>( + OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + + Loaded += OnLoaded; + Unloaded += OnUnloaded; + + SetValue(XAxesProperty, new ObservableCollection() + { + LiveCharts.DefaultSettings.GetProvider().GetDefaultCartesianAxis() + }); + SetValue(YAxesProperty, new ObservableCollection() + { + LiveCharts.DefaultSettings.GetProvider().GetDefaultCartesianAxis() + }); + SetValue(SeriesProperty, new ObservableCollection()); + SetValue(SectionsProperty, new ObservableCollection>()); + SetValue(VisualElementsProperty, new ObservableCollection>()); + SetValue(SyncContextProperty, new object()); + } + + #region dependency properties + + /// + /// The title property. + /// + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register( + nameof(Title), typeof(VisualElement), typeof(CartesianChart), new PropertyMetadata(null)); + + /// + /// The series property. + /// + public static readonly DependencyProperty SeriesProperty = + DependencyProperty.Register( + nameof(Series), typeof(IEnumerable), typeof(CartesianChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (CartesianChart)o; + var seriesObserver = chart._seriesObserver; + seriesObserver?.Dispose((IEnumerable)args.OldValue); + seriesObserver?.Initialize((IEnumerable)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The x axes property + /// + public static readonly DependencyProperty XAxesProperty = + DependencyProperty.Register( + nameof(XAxes), typeof(IEnumerable), typeof(CartesianChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (CartesianChart)o; + var observer = chart._xObserver; + observer?.Dispose((IEnumerable)args.OldValue); + observer?.Initialize((IEnumerable)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The y axes property + /// + public static readonly DependencyProperty YAxesProperty = + DependencyProperty.Register( + nameof(YAxes), typeof(IEnumerable), typeof(CartesianChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (CartesianChart)o; + var observer = chart._yObserver; + observer?.Dispose((IEnumerable)args.OldValue); + observer?.Initialize((IEnumerable)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The sections property + /// + public static readonly DependencyProperty SectionsProperty = + DependencyProperty.Register( + nameof(Sections), typeof(IEnumerable>), typeof(CartesianChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (CartesianChart)o; + var observer = chart._sectionsObserver; + observer?.Dispose((IEnumerable>)args.OldValue); + observer?.Initialize((IEnumerable>)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The visual elements property + /// + public static readonly DependencyProperty VisualElementsProperty = + DependencyProperty.Register( + nameof(VisualElements), typeof(IEnumerable>), typeof(CartesianChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (CartesianChart)o; + var observer = chart._visualsObserver; + observer?.Dispose((IEnumerable>)args.OldValue); + observer?.Initialize((IEnumerable>)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The sync context property + /// + public static readonly DependencyProperty SyncContextProperty = + DependencyProperty.Register( + nameof(SyncContext), typeof(object), typeof(CartesianChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (CartesianChart)o; + if (chart._motionCanvas != null) chart.CoreCanvas.Sync = args.NewValue; + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The zoom mode property + /// + public static readonly DependencyProperty DrawMarginFrameProperty = + DependencyProperty.Register( + nameof(DrawMarginFrame), typeof(DrawMarginFrame), typeof(CartesianChart), new PropertyMetadata(null)); + + /// + /// The zoom mode property + /// + public static readonly DependencyProperty ZoomModeProperty = + DependencyProperty.Register( + nameof(ZoomMode), typeof(ZoomAndPanMode), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.ZoomMode)); + + /// + /// The zooming speed property + /// + public static readonly DependencyProperty ZoomingSpeedProperty = + DependencyProperty.Register( + nameof(ZoomingSpeed), typeof(double), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.ZoomSpeed)); + + /// + /// The tool tip finding strategy property + /// + public static readonly DependencyProperty TooltipFindingStrategyProperty = + DependencyProperty.Register( + nameof(TooltipFindingStrategy), typeof(TooltipFindingStrategy), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipFindingStrategy, OnDependencyPropertyChanged)); + + /// + /// The draw margin property + /// + public static readonly DependencyProperty DrawMarginProperty = + DependencyProperty.Register( + nameof(DrawMargin), typeof(Margin), typeof(CartesianChart), new PropertyMetadata(null, OnDependencyPropertyChanged)); + + /// + /// The animations speed property + /// + public static readonly DependencyProperty AnimationsSpeedProperty = + DependencyProperty.Register( + nameof(AnimationsSpeed), typeof(TimeSpan), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.AnimationsSpeed, OnDependencyPropertyChanged)); + + /// + /// The easing function property + /// + public static readonly DependencyProperty EasingFunctionProperty = + DependencyProperty.Register( + nameof(EasingFunction), typeof(Func), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.EasingFunction, OnDependencyPropertyChanged)); + + /// + /// The legend position property + /// + public static readonly DependencyProperty LegendPositionProperty = + DependencyProperty.Register( + nameof(LegendPosition), typeof(LegendPosition), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendPosition, OnDependencyPropertyChanged)); + + /// + /// The legend background paint property + /// + public static readonly DependencyProperty LegendBackgroundPaintProperty = + DependencyProperty.Register( + nameof(LegendBackgroundPaint), typeof(IPaint), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendBackgroundPaint, OnDependencyPropertyChanged)); + + /// + /// The legend text paint property + /// + public static readonly DependencyProperty LegendTextPaintProperty = + DependencyProperty.Register( + nameof(LegendTextPaint), typeof(IPaint), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextPaint, OnDependencyPropertyChanged)); + + /// + /// The legend text size property + /// + public static readonly DependencyProperty LegendTextSizeProperty = + DependencyProperty.Register( + nameof(LegendTextSize), typeof(double?), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextSize, OnDependencyPropertyChanged)); + + /// + /// The tool tip position property + /// + public static readonly DependencyProperty TooltipPositionProperty = + DependencyProperty.Register( + nameof(TooltipPosition), typeof(TooltipPosition), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipPosition, OnDependencyPropertyChanged)); + + /// + /// The tooltip background paint property + /// + public static readonly DependencyProperty TooltipBackgroundPaintProperty = + DependencyProperty.Register( + nameof(TooltipBackgroundPaint), typeof(IPaint), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipBackgroundPaint, OnDependencyPropertyChanged)); + + /// + /// The tooltip text paint property + /// + public static readonly DependencyProperty TooltipTextPaintProperty = + DependencyProperty.Register( + nameof(TooltipTextPaint), typeof(IPaint), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextPaint, OnDependencyPropertyChanged)); + + /// + /// The tooltip text size property + /// + public static readonly DependencyProperty TooltipTextSizeProperty = + DependencyProperty.Register( + nameof(TooltipTextSize), typeof(double?), typeof(CartesianChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextSize, OnDependencyPropertyChanged)); + + /// + /// The update started command. + /// + public static readonly DependencyProperty UpdateStartedCommandProperty = + DependencyProperty.Register( + nameof(UpdateStartedCommand), typeof(ICommand), typeof(CartesianChart), + new PropertyMetadata(null)); + + /// + /// The pointer pressed command. + /// + public static readonly DependencyProperty PointerPressedCommandProperty = + DependencyProperty.Register( + nameof(PointerPressedCommand), typeof(ICommand), typeof(CartesianChart), + new PropertyMetadata(null)); + + /// + /// The pointer released command. + /// + public static readonly DependencyProperty PointerReleasedCommandProperty = + DependencyProperty.Register( + nameof(PointerReleasedCommand), typeof(ICommand), typeof(CartesianChart), + new PropertyMetadata(null)); + + /// + /// The pointer move command. + /// + public static readonly DependencyProperty PointerMoveCommandProperty = + DependencyProperty.Register( + nameof(PointerMoveCommand), typeof(ICommand), typeof(CartesianChart), + new PropertyMetadata(null)); + + /// + /// The data pointer down command property + /// + public static readonly DependencyProperty DataPointerDownCommandProperty = + DependencyProperty.Register( + nameof(DataPointerDownCommand), typeof(ICommand), typeof(CartesianChart), new PropertyMetadata(null)); + + /// + /// The chart point pointer down command property + /// + public static readonly DependencyProperty ChartPointPointerDownCommandProperty = + DependencyProperty.Register( + nameof(ChartPointPointerDownCommand), typeof(ICommand), typeof(CartesianChart), new PropertyMetadata(null)); + + /// + /// The chart point pointer down command property + /// + public static readonly DependencyProperty VisualElementsPointerDownCommandProperty = + DependencyProperty.Register( + nameof(VisualElementsPointerDownCommand), typeof(ICommand), typeof(CartesianChart), new PropertyMetadata(null)); + + #endregion + + #region events + + /// + public event ChartEventHandler? Measuring; + + /// + public event ChartEventHandler? UpdateStarted; + + /// + public event ChartEventHandler? UpdateFinished; + + /// + public event ChartPointsHandler? DataPointerDown; + + /// + public event ChartPointHandler? ChartPointPointerDown; + + /// + public event VisualElementsHandler? VisualElementsPointerDown; + + #endregion + + #region properties + + /// + bool IChartView.DesignerMode => Windows.ApplicationModel.DesignMode.DesignModeEnabled; + + /// + public IChart CoreChart => _core ?? throw new Exception("Core not set yet."); + + /// + public object SyncContext + { + get => GetValue(SyncContextProperty); + set => SetValue(SyncContextProperty, value); + } + + LvcColor IChartView.BackColor + { + get => Background is not SolidColorBrush b + ? new LvcColor() + : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); + set => SetValue(BackgroundProperty, new SolidColorBrush(Windows.UI.Color.FromArgb(value.A, value.R, value.G, value.B))); + } + + /// + public Margin DrawMargin + { + get => (Margin)GetValue(DrawMarginProperty); + set => SetValue(DrawMarginProperty, value); + } + + Margin? IChartView.DrawMargin + { + get => DrawMargin; + set => SetValue(DrawMarginProperty, value); + } + + LvcSize IChartView.ControlSize => _motionCanvas == null + ? throw new Exception("Canvas not found") + : new LvcSize { Width = (float)_motionCanvas.ActualWidth, Height = (float)_motionCanvas.ActualHeight }; + + /// + public MotionCanvas CoreCanvas => _motionCanvas == null ? throw new Exception("Canvas not found") : _motionCanvas.CanvasCore; + + CartesianChart ICartesianChartView.Core => + _core == null ? throw new Exception("core not found") : (CartesianChart)_core; + + /// + public VisualElement? Title + { + get => (VisualElement?)GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + + /// + public IEnumerable Series + { + get => (IEnumerable)GetValue(SeriesProperty); + set => SetValue(SeriesProperty, value); + } + + /// + public IEnumerable XAxes + { + get => (IEnumerable)GetValue(XAxesProperty); + set => SetValue(XAxesProperty, value); + } + + /// + public IEnumerable YAxes + { + get => (IEnumerable)GetValue(YAxesProperty); + set => SetValue(YAxesProperty, value); + } + + /// + public IEnumerable> Sections + { + get => (IEnumerable>)GetValue(SectionsProperty); + set => SetValue(SectionsProperty, value); + } + + /// + public IEnumerable> VisualElements + { + get => (IEnumerable>)GetValue(VisualElementsProperty); + set => SetValue(VisualElementsProperty, value); + } + + /// + public DrawMarginFrame? DrawMarginFrame + { + get => (DrawMarginFrame)GetValue(DrawMarginFrameProperty); + set => SetValue(DrawMarginFrameProperty, value); + } + + /// + public ZoomAndPanMode ZoomMode + { + get => (ZoomAndPanMode)GetValue(ZoomModeProperty); + set => SetValue(ZoomModeProperty, value); + } + + ZoomAndPanMode ICartesianChartView.ZoomMode + { + get => ZoomMode; + set => SetValue(ZoomModeProperty, value); + } + + /// + public double ZoomingSpeed + { + get => (double)GetValue(ZoomingSpeedProperty); + set => SetValue(ZoomingSpeedProperty, value); + } + + double ICartesianChartView.ZoomingSpeed + { + get => ZoomingSpeed; + set => SetValue(ZoomingSpeedProperty, value); + } + + /// + public TooltipFindingStrategy TooltipFindingStrategy + { + get => (TooltipFindingStrategy)GetValue(TooltipFindingStrategyProperty); + set => SetValue(TooltipFindingStrategyProperty, value); + } + + /// + public TimeSpan AnimationsSpeed + { + get => (TimeSpan)GetValue(AnimationsSpeedProperty); + set => SetValue(AnimationsSpeedProperty, value); + } + + TimeSpan IChartView.AnimationsSpeed + { + get => AnimationsSpeed; + set => SetValue(AnimationsSpeedProperty, value); + } + + /// + public Func EasingFunction + { + get => (Func)GetValue(EasingFunctionProperty); + set => SetValue(EasingFunctionProperty, value); + } + + Func? IChartView.EasingFunction + { + get => EasingFunction; + set => SetValue(EasingFunctionProperty, value); + } + + /// + public LegendPosition LegendPosition + { + get => (LegendPosition)GetValue(LegendPositionProperty); + set => SetValue(LegendPositionProperty, value); + } + + LegendPosition IChartView.LegendPosition + { + get => LegendPosition; + set => SetValue(LegendPositionProperty, value); + } + + /// + public TooltipPosition TooltipPosition + { + get => (TooltipPosition)GetValue(TooltipPositionProperty); + set => SetValue(TooltipPositionProperty, value); + } + + /// + public IPaint? TooltipBackgroundPaint + { + get => (IPaint?)GetValue(TooltipBackgroundPaintProperty); + set => SetValue(TooltipBackgroundPaintProperty, value); + } + + /// + public IPaint? TooltipTextPaint + { + get => (IPaint?)GetValue(TooltipTextPaintProperty); + set => SetValue(TooltipTextPaintProperty, value); + } + + /// + public double? TooltipTextSize + { + get => (double?)GetValue(TooltipTextSizeProperty); + set => SetValue(TooltipTextSizeProperty, value); + } + + /// + public IChartTooltip? Tooltip { get; set; } = new SKDefaultTooltip(); + + /// + public IPaint? LegendBackgroundPaint + { + get => (IPaint?)GetValue(LegendBackgroundPaintProperty); + set => SetValue(LegendBackgroundPaintProperty, value); + } + + /// + public IPaint? LegendTextPaint + { + get => (IPaint?)GetValue(LegendTextPaintProperty); + set => SetValue(LegendTextPaintProperty, value); + } + + /// + public double? LegendTextSize + { + get => (double?)GetValue(LegendTextSizeProperty); + set => SetValue(LegendTextSizeProperty, value); + } + + /// + public IChartLegend? Legend { get; set; } = new SKDefaultLegend(); + + /// + public bool AutoUpdateEnabled { get; set; } = true; + + /// + public TimeSpan UpdaterThrottler { get; set; } = LiveCharts.DefaultSettings.UpdateThrottlingTimeout; + + /// + /// Gets or sets a command to execute when the chart update started. + /// + public ICommand? UpdateStartedCommand + { + get => (ICommand?)GetValue(UpdateStartedCommandProperty); + set => SetValue(UpdateStartedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer is pressed on the chart. + /// + public ICommand? PointerPressedCommand + { + get => (ICommand?)GetValue(PointerPressedCommandProperty); + set => SetValue(PointerPressedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer is released on the chart. + /// + public ICommand? PointerReleasedCommand + { + get => (ICommand?)GetValue(PointerReleasedCommandProperty); + set => SetValue(PointerReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer moves over the chart. + /// + public ICommand? PointerMoveCommand + { + get => (ICommand?)GetValue(PointerMoveCommandProperty); + set => SetValue(PointerMoveCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a data or data points. + /// + public ICommand DataPointerDownCommand + { + get => (ICommand)GetValue(DataPointerDownCommandProperty); + set => SetValue(DataPointerDownCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a chart point. + /// + public ICommand ChartPointPointerDownCommand + { + get => (ICommand)GetValue(ChartPointPointerDownCommandProperty); + set => SetValue(ChartPointPointerDownCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a chart point. + /// + public ICommand? VisualElementsPointerDownCommand + { + get => (ICommand?)GetValue(VisualElementsPointerDownCommandProperty); + set => SetValue(VisualElementsPointerDownCommandProperty, value); + } + + #endregion + + /// + public double[] ScaleUIPoint(LvcPoint point, int xAxisIndex = 0, int yAxisIndex = 0) + { + if (_core == null) throw new Exception("core not found"); + var cartesianCore = (CartesianChart)_core; + return cartesianCore.ScaleUIPoint(point, xAxisIndex, yAxisIndex); + } + + /// + public LvcPointD ScalePixelsToData(LvcPointD point, int xAxisIndex = 0, int yAxisIndex = 0) + { + if (_core is not CartesianChart cc) throw new Exception("core not found"); + var xScaler = new Scaler(cc.DrawMarginLocation, cc.DrawMarginSize, cc.XAxes[xAxisIndex]); + var yScaler = new Scaler(cc.DrawMarginLocation, cc.DrawMarginSize, cc.YAxes[yAxisIndex]); + + return new LvcPointD { X = xScaler.ToChartValues(point.X), Y = yScaler.ToChartValues(point.Y) }; + } + + /// + public LvcPointD ScaleDataToPixels(LvcPointD point, int xAxisIndex = 0, int yAxisIndex = 0) + { + if (_core is not CartesianChart cc) throw new Exception("core not found"); + + var xScaler = new Scaler(cc.DrawMarginLocation, cc.DrawMarginSize, cc.XAxes[xAxisIndex]); + var yScaler = new Scaler(cc.DrawMarginLocation, cc.DrawMarginSize, cc.YAxes[yAxisIndex]); + + return new LvcPointD { X = xScaler.ToPixels(point.X), Y = yScaler.ToPixels(point.Y) }; + } + + /// + public IEnumerable GetPointsAt(LvcPoint point, TooltipFindingStrategy strategy = TooltipFindingStrategy.Automatic) + { + if (_core is not CartesianChart cc) throw new Exception("core not found"); + + if (strategy == TooltipFindingStrategy.Automatic) + strategy = cc.Series.GetTooltipFindingStrategy(); + + return cc.Series.SelectMany(series => series.FindHitPoints(cc, point, strategy)); + } + + /// + public IEnumerable> GetVisualsAt(LvcPoint point) + { + return _core is not CartesianChart cc + ? throw new Exception("core not found") + : cc.VisualElements.SelectMany(visual => ((VisualElement)visual).IsHitBy(_core, point)); + } + + void IChartView.InvokeOnUIThread(Action action) + { + UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + var canvas = (MotionCanvas)FindName("motionCanvas"); + + _motionCanvas = canvas; + + if (_core is null) + { + var zoomingSection = new Drawing.Geometries.RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + + _core = new CartesianChart( + this, config => config.UseDefaults(), canvas.CanvasCore, zoomingSection); + + if (SyncContext != null) + _motionCanvas.CanvasCore.Sync = SyncContext; + + if (_core == null) throw new Exception("Core not found!"); + _core.Measuring += OnCoreMeasuring; + _core.UpdateStarted += OnCoreUpdateStarted; + _core.UpdateFinished += OnCoreUpdateFinished; + + PointerPressed += OnPointerPressed; + PointerMoved += OnPointerMoved; + PointerReleased += OnPointerReleased; + PointerWheelChanged += OnWheelChanged; + PointerExited += OnPointerExited; + + SizeChanged += OnSizeChanged; + + _motionCanvas.Pinched += OnCanvasPinched; + } + + _core.Load(); + _core.Update(); + } + + private void OnDeepCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + _core?.Update(); + } + + private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + _core?.Update(); + } + + private void OnSizeChanged(object? sender, SizeChangedEventArgs e) + { + if (_core == null) throw new Exception("Core not found!"); + _core.Update(); + } + + private void OnCoreUpdateFinished(IChartView chart) + { + UpdateFinished?.Invoke(this); + } + + private void OnCoreUpdateStarted(IChartView chart) + { + if (UpdateStartedCommand is not null) + { + var args = new ChartCommandArgs(this); + if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); + } + + UpdateStarted?.Invoke(this); + } + + private void OnCoreMeasuring(IChartView chart) + { + Measuring?.Invoke(this); + } + + private void OnPointerPressed(object? sender, PointerRoutedEventArgs e) + { + if (e.KeyModifiers > 0) return; + _ = CapturePointer(e.Pointer); + var p = e.GetCurrentPoint(this); + + if (PointerPressedCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); + } + + var isRight = false; + if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) + { + var properties = e.GetCurrentPoint(this).Properties; + isRight = properties.IsRightButtonPressed; + } + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); + } + + private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) + { + if (DateTime.Now < _panLocketUntil) return; + + var p = e.GetCurrentPoint(motionCanvas); + + if (PointerMoveCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); + } + + _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + } + + private void OnPointerReleased(object? sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(this); + + if (PointerReleasedCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); + } + + var isRight = false; + if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) + { + var properties = e.GetCurrentPoint(this).Properties; + isRight = properties.IsRightButtonPressed; + } + _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); + ReleasePointerCapture(e.Pointer); + } + + private void OnPointerExited(object? sender, PointerRoutedEventArgs e) + { + _core?.InvokePointerLeft(); + } + + private void OnWheelChanged(object? sender, PointerRoutedEventArgs e) + { + if (_core == null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + var p = e.GetCurrentPoint(this); + + c.Zoom( + new LvcPoint( + (float)p.Position.X, (float)p.Position.Y), + p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnCanvasPinched(object? sender, LiveChartsPinchEventArgs eventArgs) + { + if (_core == null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + + c.Zoom(eventArgs.PinchStart, ZoomDirection.DefinedByScaleFactor, eventArgs.Scale, true); + _panLocketUntil = DateTime.Now.AddMilliseconds(500); + //_lastScale = eventArgs.Scale; + } + + private void OnUnloaded(object? sender, RoutedEventArgs e) + { + _core?.Unload(); + } + + private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + var chart = (CartesianChart)o; + if (chart._core == null) return; + + chart._core.Update(); + } + + void IChartView.OnDataPointerDown(IEnumerable points, LvcPoint pointer) + { + DataPointerDown?.Invoke(this, points); + if (DataPointerDownCommand is not null && DataPointerDownCommand.CanExecute(points)) DataPointerDownCommand.Execute(points); + + var closest = points.FindClosestTo(pointer); + ChartPointPointerDown?.Invoke(this, closest); + if (ChartPointPointerDownCommand is not null && ChartPointPointerDownCommand.CanExecute(closest)) ChartPointPointerDownCommand.Execute(closest); + } + + void IChartView.OnVisualElementPointerDown( + IEnumerable> visualElements, LvcPoint pointer) + { + var args = new VisualElementsEventArgs(CoreChart, visualElements, pointer); + + VisualElementsPointerDown?.Invoke(this, args); + if (VisualElementsPointerDownCommand is not null && VisualElementsPointerDownCommand.CanExecute(args)) + VisualElementsPointerDownCommand.Execute(args); + } + + void IChartView.Invalidate() + { + CoreCanvas.Invalidate(); + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml new file mode 100644 index 000000000..99fa69eac --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml @@ -0,0 +1,14 @@ + + + + + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml.cs new file mode 100644 index 000000000..eb4414f15 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml.cs @@ -0,0 +1,279 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using LiveChartsCore.Drawing; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel; +using LiveChartsCore.Measure; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Painting; +using SkiaSharp; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using LiveChartsCore.SkiaSharpView.WinUI.Helpers; + +namespace LiveChartsCore.SkiaSharpView.WinUI; + +/// +/// Defines a geographic map. +/// +public sealed partial class GeoMap : UserControl, IGeoMapView +{ + private readonly CollectionDeepObserver _seriesObserver; + private readonly GeoMap _core; + + /// + /// Initializes a new instance of the class. + /// + public GeoMap() + { + InitializeComponent(); + LiveCharts.Configure(config => config.UseDefaults()); + _core = new GeoMap(this); + + PointerPressed += OnPointerPressed; + PointerMoved += OnPointerMoved; + PointerReleased += OnPointerReleased; + PointerWheelChanged += OnWheelChanged; + PointerExited += OnPointerExited; + + SizeChanged += GeoMap_SizeChanged; + + _seriesObserver = new CollectionDeepObserver( + (object? sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), + (object? sender, PropertyChangedEventArgs e) => _core.Update(), + true); + + SetValue(SeriesProperty, Enumerable.Empty()); + SetValue(ActiveMapProperty, Maps.GetWorldMap()); + SetValue(SyncContextProperty, new object()); + + Unloaded += GeoMap_Unloaded; + } + + #region dependency props + + /// + /// The active map property + /// + public static readonly DependencyProperty ActiveMapProperty = + DependencyProperty.Register(nameof(ActiveMap), typeof(CoreMap), typeof(GeoMap), + new PropertyMetadata(null, OnDependencyPropertyChanged)); + + /// + /// The sync context property. + /// + public static readonly DependencyProperty SyncContextProperty = + DependencyProperty.Register( + nameof(SyncContext), typeof(object), typeof(GeoMap), new PropertyMetadata(null, OnDependencyPropertyChanged)); + + /// + /// The view command property. + /// + public static readonly DependencyProperty ViewCommandProperty = + DependencyProperty.Register( + nameof(ViewCommand), typeof(object), typeof(GeoMap), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (GeoMap)o; + chart._core.ViewTo(args.NewValue); + })); + + /// + /// The map projection property + /// + public static readonly DependencyProperty MapProjectionProperty = + DependencyProperty.Register(nameof(MapProjection), typeof(MapProjection), typeof(GeoMap), + new PropertyMetadata(MapProjection.Default, OnDependencyPropertyChanged)); + + /// + /// The series property + /// + public static readonly DependencyProperty SeriesProperty = + DependencyProperty.Register(nameof(Series), typeof(IEnumerable), + typeof(GeoMap), new PropertyMetadata(null, (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (GeoMap)o; + var seriesObserver = chart._seriesObserver; + seriesObserver?.Dispose((IEnumerable)args.OldValue); + seriesObserver?.Initialize((IEnumerable)args.NewValue); + chart._core.Update(); + })); + + /// + /// The stroke property + /// + public static readonly DependencyProperty StrokeProperty = + DependencyProperty.Register( + nameof(Stroke), typeof(IPaint), typeof(GeoMap), + new PropertyMetadata(new SolidColorPaint(new SKColor(255, 255, 255, 255)) { IsStroke = true }, OnDependencyPropertyChanged)); + + /// + /// The fill property + /// + public static readonly DependencyProperty FillProperty = + DependencyProperty.Register( + nameof(Fill), typeof(IPaint), typeof(GeoMap), + new PropertyMetadata(new SolidColorPaint(new SKColor(240, 240, 240, 255)) { IsFill = true }, OnDependencyPropertyChanged)); + + #endregion + + #region properties + + /// + public bool AutoUpdateEnabled { get; set; } = true; + + /// + bool IGeoMapView.DesignerMode => Windows.ApplicationModel.DesignMode.DesignModeEnabled; + + /// + public object SyncContext + { + get => GetValue(SyncContextProperty); + set => SetValue(SyncContextProperty, value); + } + + /// + public object? ViewCommand + { + get => GetValue(ViewCommandProperty); + set => SetValue(ViewCommandProperty, value); + } + + /// + public MotionCanvas Canvas => canvas.CanvasCore; + + /// + public CoreMap ActiveMap + { + get => (CoreMap)GetValue(ActiveMapProperty); + set => SetValue(ActiveMapProperty, value); + } + + /// + float IGeoMapView.Width => (float)ActualWidth; + + /// + float IGeoMapView.Height => (float)ActualHeight; + + /// + public MapProjection MapProjection + { + get => (MapProjection)GetValue(MapProjectionProperty); + set => SetValue(MapProjectionProperty, value); + } + + /// + public IPaint? Stroke + { + get => (IPaint)GetValue(StrokeProperty); + set + { + if (value is not null) value.IsStroke = true; + SetValue(StrokeProperty, value); + } + } + + /// + public IPaint? Fill + { + get => (IPaint)GetValue(FillProperty); + set + { + if (value is not null) value.IsFill = true; + SetValue(FillProperty, value); + } + } + + /// + public IEnumerable Series + { + get => (IEnumerable)GetValue(SeriesProperty); + set => SetValue(SeriesProperty, value); + } + + #endregion + + void IGeoMapView.InvokeOnUIThread(Action action) + { + UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); + } + + private void GeoMap_SizeChanged(object sender, SizeChangedEventArgs e) + { + _core.Update(); + } + + private void GeoMap_Unloaded(object sender, RoutedEventArgs e) + { + _core.Unload(); + } + + private void OnPointerPressed(object sender, PointerRoutedEventArgs e) + { + _ = CapturePointer(e.Pointer); + var p = e.GetCurrentPoint(this); + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + } + + private void OnPointerMoved(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(this); + _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + } + + private void OnPointerReleased(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(this); + _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + ReleasePointerCapture(e.Pointer); + } + + private void OnPointerExited(object sender, PointerRoutedEventArgs e) + { + _core?.InvokePointerLeft(); + } + + private void OnWheelChanged(object sender, PointerRoutedEventArgs e) + { + if (_core == null) throw new Exception("core not found"); + var p = e.GetCurrentPoint(this); + + _core.ViewTo( + new ZoomOnPointerView( + new LvcPoint((float)p.Position.X, (float)p.Position.Y), + p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut)); + } + + private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + var chart = (GeoMap)o; + chart._core.Update(); + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/LiveChartsPinchEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/LiveChartsPinchEventArgs.cs new file mode 100644 index 000000000..223a2b6ac --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/LiveChartsPinchEventArgs.cs @@ -0,0 +1,32 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.SkiaSharpView.WinUI.Helpers; + +public class LiveChartsPinchEventArgs +{ + public float Scale { get; set; } + + public LvcPoint PinchStart { get; set; } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/UnoPlatformHelpers.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/UnoPlatformHelpers.cs new file mode 100644 index 000000000..233535643 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/UnoPlatformHelpers.cs @@ -0,0 +1,62 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Runtime.InteropServices; +using Microsoft.UI.Dispatching; + +namespace LiveChartsCore.SkiaSharpView.WinUI.Helpers; + +/// +/// Defines Uno platform helpers. +/// +public static class UnoPlatformHelpers +{ + /// + /// Determines whether the assembly is running in web assembly. + /// + public static bool IsWebAssembly { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")); + + /// + /// Invokes a given acction in the UI thread. + /// + /// The action. + /// The dispatcher queue + public static void InvokeOnUIThread(Action action, DispatcherQueue dispatcherQueue) + { + if (IsWebAssembly) + { + action(); + return; + } + + _ = dispatcherQueue.TryEnqueue( + DispatcherQueuePriority.Normal, () => action()); + } +} + +/// +/// Defines a custom pinch event handler. +/// +/// +/// +public delegate void PinchHandler(object sender, LiveChartsPinchEventArgs eventArgs); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj new file mode 100644 index 000000000..2c24caf35 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj @@ -0,0 +1,67 @@ + + + $(TargetFrameworks);net7.0-windows10.0.19041 + $(TargetFrameworks);net7.0;net7.0-ios;net7.0-maccatalyst;net7.0-android + + true + + enable + 11.0 + 2.0.0-beta.950 + icon.png + Simple, flexible, interactive and powerful data visualization for Uno.WinUI. + MIT + BetoRodriguez + true + snupkg + https://github.com/beto-rodriguez/LiveCharts2 + Properties + LiveChartsCore.SkiaSharpView.WinUI + LiveChartsCore.SkiaSharpView.Uno.WinUI + en-US + bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml + + + + + + + + + + + + + + + + + + + + + + + %(Filename) + + + + + + + + + + + + \ No newline at end of file diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml new file mode 100644 index 000000000..f436fdf64 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml @@ -0,0 +1,14 @@ + + + + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs new file mode 100644 index 000000000..23a695114 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs @@ -0,0 +1,283 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using LiveChartsCore.Drawing; +using LiveChartsCore.Kernel; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Drawing; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using LiveChartsCore.SkiaSharpView.WinUI.Helpers; +using SkiaSharp.Views.Windows; +using Windows.Graphics.Display; + +#if __ANDROID__ +using Android.Views; +#endif + +namespace LiveChartsCore.SkiaSharpView.WinUI; + +/// +public sealed partial class MotionCanvas : UserControl +{ + private readonly SKXamlCanvas _skiaElement; + private bool _isDrawingLoopRunning; + + /// + /// Initializes a new instance of the class. + /// + public MotionCanvas() + { + InitializeComponent(); + Loaded += OnLoaded; + Unloaded += OnUnloaded; + + var canvas = (SKXamlCanvas)FindName("canvas"); + _skiaElement = canvas; + _skiaElement.PaintSurface += OnPaintSurface; + +#if __ANDROID__ + _scaleDetector = new ScaleGestureDetector(Context, new AndroidScaleListener(this)); +#endif + } + + #region properties + + /// + /// The paint tasks property + /// + public static readonly DependencyProperty PaintTasksProperty = + DependencyProperty.Register( + nameof(PaintTasks), typeof(List>), typeof(MotionCanvas), + new PropertyMetadata(new List>(), new PropertyChangedCallback(OnPaintTaskChanged))); + + /// + /// Gets or sets the paint tasks. + /// + /// + /// The paint tasks. + /// + public List> PaintTasks + { + get => (List>)GetValue(PaintTasksProperty); + set => SetValue(PaintTasksProperty, value); + } + + /// + /// Gets or sets the frames per second. + /// + /// + /// The frames per second. + /// + public double MaxFps { get; set; } = 60; + + /// + /// Gets the canvas core. + /// + /// + /// The canvas core. + /// + public MotionCanvas CanvasCore { get; } = new(); + + #endregion + + /// + /// Called when the canvas detects a pinch gesture. + /// + public event PinchHandler? Pinched; + + private void OnLoaded(object sender, RoutedEventArgs e) + { + CanvasCore.Invalidated += OnCanvasCoreInvalidated; + } + + private void OnPaintSurface(object? sender, SKPaintSurfaceEventArgs args) + { +#if HAS_UNO_WINUI + var scale = DisplayInformation.GetForCurrentView().LogicalDpi / 96.0f; + args.Surface.Canvas.Scale((float)scale, (float)scale); + CanvasCore.DrawFrame(new SkiaSharpDrawingContext(CanvasCore, args.Info, args.Surface, args.Surface.Canvas)); +#else + var scaleFactor = XamlRoot.RasterizationScale; + args.Surface.Canvas.Scale((float)scaleFactor, (float)scaleFactor); + CanvasCore.DrawFrame(new SkiaSharpDrawingContext(CanvasCore, args.Info, args.Surface, args.Surface.Canvas)); +#endif + } + + private async void RunDrawingLoop() + { + if (_isDrawingLoopRunning || _skiaElement == null) return; + _isDrawingLoopRunning = true; + + var ts = TimeSpan.FromSeconds(1 / MaxFps); + while (!CanvasCore.IsValid) + { + _skiaElement.Invalidate(); + await Task.Delay(ts); + } + + _isDrawingLoopRunning = false; + } + + private void OnCanvasCoreInvalidated(MotionCanvas sender) + { + RunDrawingLoop(); + } + + private static void OnPaintTaskChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) + { + var motionCanvas = (MotionCanvas)sender; + + var tasks = new HashSet>(); + + foreach (var item in motionCanvas.PaintTasks ?? Enumerable.Empty>()) + { + item.PaintTask.SetGeometries(motionCanvas.CanvasCore, item.Geometries); + _ = tasks.Add(item.PaintTask); + } + + motionCanvas.CanvasCore.SetPaintTasks(tasks); + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + CanvasCore.Invalidated -= OnCanvasCoreInvalidated; + CanvasCore.Dispose(); + } + + #region ANDROID +#if __ANDROID__ + // based on: + //https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/touch/android-touch-walkthrough + + private readonly ScaleGestureDetector _scaleDetector; + + private int _activePointerId = -1; + private float _lastTouchX; + private float _lastTouchY; + private float _posX; + private float _posY; + + private class AndroidScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener + { + private readonly MotionCanvas _canvas; + + public AndroidScaleListener(MotionCanvas canvas) + { + _canvas = canvas; + } + + /// + /// Called on scale gesture. + /// + /// + /// + public override bool OnScale(ScaleGestureDetector? detector) + { + if (detector is null) return false; + + if (detector.ScaleFactor != 1.0f) + { + _canvas.InvokePinch( + new LiveChartsPinchEventArgs + { + PinchStart = new LvcPoint { X = _canvas._lastTouchX, Y = _canvas._lastTouchY }, + Scale = detector.ScaleFactor + }); + } + return true; + } + } + + public override bool OnTouchEvent(MotionEvent? ev) + { + if (ev is null) return false; + + _ = _scaleDetector.OnTouchEvent(ev); + + var action = ev.Action & MotionEventActions.Mask; + int pointerIndex; + + switch (action) + { + case MotionEventActions.Down: + _lastTouchX = ev.GetX(); + _lastTouchY = ev.GetY(); + _activePointerId = ev.GetPointerId(0); + break; + + case MotionEventActions.Move: + pointerIndex = ev.FindPointerIndex(_activePointerId); + var x = ev.GetX(pointerIndex); + var y = ev.GetY(pointerIndex); + if (!_scaleDetector.IsInProgress) + { + // Only move the ScaleGestureDetector isn't already processing a gesture. + var deltaX = x - _lastTouchX; + var deltaY = y - _lastTouchY; + _posX += deltaX; + _posY += deltaY; + } + + _lastTouchX = x; + _lastTouchY = y; + break; + + case MotionEventActions.Up: + case MotionEventActions.Cancel: + // We no longer need to keep track of the active pointer. + _activePointerId = -1; + break; + + case MotionEventActions.PointerUp: + // check to make sure that the pointer that went up is for the gesture we're tracking. + pointerIndex = (int)(ev.Action & MotionEventActions.PointerIndexMask) >> (int)MotionEventActions.PointerIndexShift; + var pointerId = ev.GetPointerId(pointerIndex); + if (pointerId == _activePointerId) + { + // This was our active pointer going up. Choose a new + // action pointer and adjust accordingly + var newPointerIndex = pointerIndex == 0 ? 1 : 0; + _lastTouchX = ev.GetX(newPointerIndex); + _lastTouchY = ev.GetY(newPointerIndex); + _activePointerId = ev.GetPointerId(newPointerIndex); + } + break; + + default: + break; + } + + return true; + } + + private void InvokePinch(LiveChartsPinchEventArgs args) + { + Pinched?.Invoke(this, args); + } +#endif + #endregion +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml new file mode 100644 index 000000000..fa32efc41 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml @@ -0,0 +1,14 @@ + + + + + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs new file mode 100644 index 000000000..c9079aa73 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs @@ -0,0 +1,762 @@ + +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using System.Windows.Input; +using LiveChartsCore.Drawing; +using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Events; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Measure; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.SKCharts; +using LiveChartsCore.SkiaSharpView.WinUI.Helpers; +using LiveChartsCore.VisualElements; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; + +namespace LiveChartsCore.SkiaSharpView.WinUI; + +/// +public sealed partial class PieChart : UserControl, IPieChartView +{ + private Chart? _core; + private MotionCanvas? _canvas; + private readonly CollectionDeepObserver _seriesObserver; + private readonly CollectionDeepObserver> _visualsObserver; + + /// + /// Initializes a new instance of the class. + /// + public PieChart() + { + LiveCharts.Configure(config => config.UseDefaults()); + + InitializeComponent(); + + _seriesObserver = new CollectionDeepObserver( + (object? sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), + (object? sender, PropertyChangedEventArgs e) => _core?.Update()); + _visualsObserver = new CollectionDeepObserver>( + (object? sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), + (object? sender, PropertyChangedEventArgs e) => _core?.Update()); + + Loaded += OnLoaded; + Unloaded += OnUnloaded; + + SetValue(SeriesProperty, new ObservableCollection()); + SetValue(VisualElementsProperty, new ObservableCollection>()); + SetValue(SyncContextProperty, new object()); + } + + #region dependency properties + + /// + /// The title property. + /// + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register( + nameof(Title), typeof(VisualElement), typeof(PieChart), new PropertyMetadata(null)); + + /// + /// The series property + /// + public static readonly DependencyProperty SeriesProperty = + DependencyProperty.Register( + nameof(Series), typeof(IEnumerable), typeof(PieChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (PieChart)o; + var seriesObserver = chart._seriesObserver; + seriesObserver?.Dispose((IEnumerable)args.OldValue); + seriesObserver?.Initialize((IEnumerable)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The visual elements property + /// + public static readonly DependencyProperty VisualElementsProperty = + DependencyProperty.Register( + nameof(VisualElements), typeof(IEnumerable>), typeof(PieChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (PieChart)o; + var observer = chart._visualsObserver; + observer?.Dispose((IEnumerable>)args.OldValue); + observer?.Initialize((IEnumerable>)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The sync context property + /// + public static readonly DependencyProperty SyncContextProperty = + DependencyProperty.Register( + nameof(SyncContext), typeof(object), typeof(PieChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (PieChart)o; + if (chart._canvas != null) chart.CoreCanvas.Sync = args.NewValue; + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The IsClockwise property + /// + public static readonly DependencyProperty IsClockwiseProperty = + DependencyProperty.Register( + nameof(IsClockwise), typeof(bool), typeof(PieChart), new PropertyMetadata(true, OnDependencyPropertyChanged)); + + /// + /// The initial rotation property + /// + public static readonly DependencyProperty InitialRotationProperty = + DependencyProperty.Register( + nameof(InitialRotation), typeof(double), typeof(PieChart), new PropertyMetadata(0d, OnDependencyPropertyChanged)); + + /// + /// The maximum angle property + /// + public static readonly DependencyProperty MaxAngleProperty = + DependencyProperty.Register( + nameof(MaxAngle), typeof(double), typeof(PieChart), new PropertyMetadata(360d, OnDependencyPropertyChanged)); + + /// + /// The total property + /// + public static readonly DependencyProperty MaxValueProperty = + DependencyProperty.Register( + nameof(MaxValue), typeof(double?), typeof(PieChart), new PropertyMetadata(null, OnDependencyPropertyChanged)); + + /// + /// The start property + /// + public static readonly DependencyProperty MinValueProperty = + DependencyProperty.Register( + nameof(MinValue), typeof(double), typeof(PieChart), new PropertyMetadata(0d, OnDependencyPropertyChanged)); + + /// + /// The draw margin property + /// + public static readonly DependencyProperty DrawMarginProperty = + DependencyProperty.Register( + nameof(DrawMargin), typeof(Margin), typeof(PieChart), new PropertyMetadata(null, OnDependencyPropertyChanged)); + + /// + /// The animations speed property + /// + public static readonly DependencyProperty AnimationsSpeedProperty = + DependencyProperty.Register( + nameof(AnimationsSpeed), typeof(TimeSpan), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.AnimationsSpeed, OnDependencyPropertyChanged)); + + /// + /// The easing function property + /// + public static readonly DependencyProperty EasingFunctionProperty = + DependencyProperty.Register( + nameof(EasingFunction), typeof(Func), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.EasingFunction, OnDependencyPropertyChanged)); + + /// + /// The legend position property + /// + public static readonly DependencyProperty LegendPositionProperty = + DependencyProperty.Register( + nameof(LegendPosition), typeof(LegendPosition), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendPosition, OnDependencyPropertyChanged)); + + /// + /// The legend background paint property + /// + public static readonly DependencyProperty LegendBackgroundPaintProperty = + DependencyProperty.Register( + nameof(LegendBackgroundPaint), typeof(IPaint), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendBackgroundPaint, OnDependencyPropertyChanged)); + + /// + /// The legend text paint property + /// + public static readonly DependencyProperty LegendTextPaintProperty = + DependencyProperty.Register( + nameof(LegendTextPaint), typeof(IPaint), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextPaint, OnDependencyPropertyChanged)); + + /// + /// The legend text size property + /// + public static readonly DependencyProperty LegendTextSizeProperty = + DependencyProperty.Register( + nameof(LegendTextSize), typeof(double?), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextSize, OnDependencyPropertyChanged)); + + /// + /// The tool tip position property + /// + public static readonly DependencyProperty TooltipPositionProperty = + DependencyProperty.Register( + nameof(TooltipPosition), typeof(TooltipPosition), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipPosition, OnDependencyPropertyChanged)); + + /// + /// The tooltip background paint property + /// + public static readonly DependencyProperty TooltipBackgroundPaintProperty = + DependencyProperty.Register( + nameof(TooltipBackgroundPaint), typeof(IPaint), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipBackgroundPaint, OnDependencyPropertyChanged)); + + /// + /// The tooltip text paint property + /// + public static readonly DependencyProperty TooltipTextPaintProperty = + DependencyProperty.Register( + nameof(TooltipTextPaint), typeof(IPaint), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextPaint, OnDependencyPropertyChanged)); + + /// + /// The tooltip text size property + /// + public static readonly DependencyProperty TooltipTextSizeProperty = + DependencyProperty.Register( + nameof(TooltipTextSize), typeof(double?), typeof(PieChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextSize, OnDependencyPropertyChanged)); + + /// + /// The update started command. + /// + public static readonly DependencyProperty UpdateStartedCommandProperty = + DependencyProperty.Register( + nameof(UpdateStartedCommand), typeof(ICommand), typeof(PieChart), + new PropertyMetadata(null)); + + /// + /// The pointer pressed command. + /// + public static readonly DependencyProperty PointerPressedCommandProperty = + DependencyProperty.Register( + nameof(PointerPressedCommand), typeof(ICommand), typeof(PieChart), + new PropertyMetadata(null)); + + /// + /// The pointer released command. + /// + public static readonly DependencyProperty PointerReleasedCommandProperty = + DependencyProperty.Register( + nameof(PointerReleasedCommand), typeof(ICommand), typeof(PieChart), + new PropertyMetadata(null)); + + /// + /// The pointer move command. + /// + public static readonly DependencyProperty PointerMoveCommandProperty = + DependencyProperty.Register( + nameof(PointerMoveCommand), typeof(ICommand), typeof(PieChart), + new PropertyMetadata(null)); + + /// + /// The data pointer down command property + /// + public static readonly DependencyProperty DataPointerDownCommandProperty = + DependencyProperty.Register( + nameof(DataPointerDownCommand), typeof(ICommand), typeof(PieChart), new PropertyMetadata(null)); + + /// + /// The data pointer down command property + /// + public static readonly DependencyProperty ChartPointPointerDownCommandProperty = + DependencyProperty.Register( + nameof(ChartPointPointerDownCommand), typeof(ICommand), typeof(PieChart), new PropertyMetadata(null)); + + /// + /// The chart point pointer down command property + /// + public static readonly DependencyProperty VisualElementsPointerDownCommandProperty = + DependencyProperty.Register( + nameof(VisualElementsPointerDownCommand), typeof(ICommand), typeof(PieChart), new PropertyMetadata(null)); + + #endregion + + #region events + + /// + public event ChartEventHandler? Measuring; + + /// + public event ChartEventHandler? UpdateStarted; + + /// + public event ChartEventHandler? UpdateFinished; + + /// + public event ChartPointsHandler? DataPointerDown; + + /// + public event ChartPointHandler? ChartPointPointerDown; + + /// + public event VisualElementsHandler? VisualElementsPointerDown; + + #endregion + + #region properties + + /// + bool IChartView.DesignerMode => Windows.ApplicationModel.DesignMode.DesignModeEnabled; + + /// + public IChart CoreChart => _core ?? throw new Exception("Core not set yet."); + + PieChart IPieChartView.Core + => _core == null ? throw new Exception("core not found") : (PieChart)_core; + + LvcColor IChartView.BackColor + { + get => Background is not SolidColorBrush b + ? new LvcColor() + : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); + set => SetValue(BackgroundProperty, new SolidColorBrush(Windows.UI.Color.FromArgb(value.A, value.R, value.G, value.B))); + } + + /// + public object SyncContext + { + get => GetValue(SyncContextProperty); + set => SetValue(SyncContextProperty, value); + } + + /// + public VisualElement? Title + { + get => (VisualElement?)GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + + /// + public IEnumerable Series + { + get => (IEnumerable)GetValue(SeriesProperty); + set => SetValue(SeriesProperty, value); + } + + /// + public IEnumerable> VisualElements + { + get => (IEnumerable>)GetValue(VisualElementsProperty); + set => SetValue(VisualElementsProperty, value); + } + + /// + public bool IsClockwise + { + get => (bool)GetValue(IsClockwiseProperty); + set => SetValue(IsClockwiseProperty, value); + } + + /// + public double InitialRotation + { + get => (double)GetValue(InitialRotationProperty); + set => SetValue(InitialRotationProperty, value); + } + + /// + public double MaxAngle + { + get => (double)GetValue(MaxAngleProperty); + set => SetValue(MaxAngleProperty, value); + } + + /// + [Obsolete($"Use {nameof(MaxValue)} instead.")] + public double? Total + { + get => (double?)GetValue(MaxValueProperty); + set => SetValue(MaxValueProperty, value); + } + + /// + public double? MaxValue + { + get => (double?)GetValue(MaxValueProperty); + set => SetValue(MaxValueProperty, value); + } + + /// + public double MinValue + { + get => (double)GetValue(MinValueProperty); + set => SetValue(MinValueProperty, value); + } + + /// + public Margin DrawMargin + { + get => (Margin)GetValue(DrawMarginProperty); + set => SetValue(DrawMarginProperty, value); + } + + Margin? IChartView.DrawMargin + { + get => DrawMargin; + set => SetValue(DrawMarginProperty, value); + } + + LvcSize IChartView.ControlSize => _canvas == null + ? throw new Exception("Canvas not found") + : new LvcSize { Width = (float)_canvas.ActualWidth, Height = (float)_canvas.ActualHeight }; + + /// + public MotionCanvas CoreCanvas => _canvas == null ? throw new Exception("Canvas not found") : _canvas.CanvasCore; + + /// + public TimeSpan AnimationsSpeed + { + get => (TimeSpan)GetValue(AnimationsSpeedProperty); + set => SetValue(AnimationsSpeedProperty, value); + } + + TimeSpan IChartView.AnimationsSpeed + { + get => AnimationsSpeed; + set => SetValue(AnimationsSpeedProperty, value); + } + + /// + public Func EasingFunction + { + get => (Func)GetValue(EasingFunctionProperty); + set => SetValue(EasingFunctionProperty, value); + } + + Func? IChartView.EasingFunction + { + get => EasingFunction; + set => SetValue(EasingFunctionProperty, value); + } + + /// + public LegendPosition LegendPosition + { + get => (LegendPosition)GetValue(LegendPositionProperty); + set => SetValue(LegendPositionProperty, value); + } + + /// + public TooltipPosition TooltipPosition + { + get => (TooltipPosition)GetValue(TooltipPositionProperty); + set => SetValue(TooltipPositionProperty, value); + } + + /// + public IPaint? TooltipBackgroundPaint + { + get => (IPaint?)GetValue(TooltipBackgroundPaintProperty); + set => SetValue(TooltipBackgroundPaintProperty, value); + } + + /// + public IPaint? TooltipTextPaint + { + get => (IPaint?)GetValue(TooltipTextPaintProperty); + set => SetValue(TooltipTextPaintProperty, value); + } + + /// + public double? TooltipTextSize + { + get => (double?)GetValue(TooltipTextSizeProperty); + set => SetValue(TooltipTextSizeProperty, value); + } + + /// + public IChartTooltip? Tooltip { get; set; } = new SKDefaultTooltip(); + + /// + public IPaint? LegendBackgroundPaint + { + get => (IPaint?)GetValue(LegendBackgroundPaintProperty); + set => SetValue(LegendBackgroundPaintProperty, value); + } + + /// + public IPaint? LegendTextPaint + { + get => (IPaint?)GetValue(LegendTextPaintProperty); + set => SetValue(LegendTextPaintProperty, value); + } + + /// + public double? LegendTextSize + { + get => (double?)GetValue(LegendTextSizeProperty); + set => SetValue(LegendTextSizeProperty, value); + } + + /// + public IChartLegend? Legend { get; set; } = new SKDefaultLegend(); + + /// + public bool AutoUpdateEnabled { get; set; } = true; + + /// + public TimeSpan UpdaterThrottler { get; set; } = LiveCharts.DefaultSettings.UpdateThrottlingTimeout; + + /// + /// Gets or sets a command to execute when the chart update started. + /// + public ICommand? UpdateStartedCommand + { + get => (ICommand?)GetValue(UpdateStartedCommandProperty); + set => SetValue(UpdateStartedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer is pressed on the chart. + /// + public ICommand? PointerPressedCommand + { + get => (ICommand?)GetValue(PointerPressedCommandProperty); + set => SetValue(PointerPressedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer is released on the chart. + /// + public ICommand? PointerReleasedCommand + { + get => (ICommand?)GetValue(PointerReleasedCommandProperty); + set => SetValue(PointerReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer moves over the chart. + /// + public ICommand? PointerMoveCommand + { + get => (ICommand?)GetValue(PointerMoveCommandProperty); + set => SetValue(PointerMoveCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a data or data points. + /// + public ICommand DataPointerDownCommand + { + get => (ICommand)GetValue(DataPointerDownCommandProperty); + set => SetValue(DataPointerDownCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a chart point. + /// + public ICommand ChartPointPointerDownCommand + { + get => (ICommand)GetValue(ChartPointPointerDownCommandProperty); + set => SetValue(ChartPointPointerDownCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a chart point. + /// + public ICommand? VisualElementsPointerDownCommand + { + get => (ICommand?)GetValue(VisualElementsPointerDownCommandProperty); + set => SetValue(VisualElementsPointerDownCommandProperty, value); + } + + #endregion + + /// + public IEnumerable GetPointsAt(LvcPoint point, TooltipFindingStrategy strategy = TooltipFindingStrategy.Automatic) + { + if (_core is not PieChart cc) throw new Exception("core not found"); + + if (strategy == TooltipFindingStrategy.Automatic) + strategy = cc.Series.GetTooltipFindingStrategy(); + + return cc.Series.SelectMany(series => series.FindHitPoints(cc, point, strategy)); + } + + /// + public IEnumerable> GetVisualsAt(LvcPoint point) + { + return _core is not PieChart cc + ? throw new Exception("core not found") + : cc.VisualElements.SelectMany(visual => ((VisualElement)visual).IsHitBy(_core, point)); + } + + void IChartView.InvokeOnUIThread(Action action) + { + UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + var canvas = (MotionCanvas)FindName("motionCanvas"); + _canvas = canvas; + + if (_core is null) + { + _core = new PieChart(this, config => config.UseDefaults(), canvas.CanvasCore); + + if (SyncContext != null) + _canvas.CanvasCore.Sync = SyncContext; + + if (_core == null) throw new Exception("Core not found!"); + _core.Update(); + + _core.Measuring += OnCoreMeasuring; + _core.UpdateStarted += OnCoreUpdateStarted; + _core.UpdateFinished += OnCoreUpdateFinished; + + PointerPressed += OnPointerPressed; + PointerReleased += PieChart_PointerReleased; + SizeChanged += OnSizeChanged; + PointerMoved += OnPointerMoved; + PointerExited += OnPointerExited; + } + + _core.Load(); + _core.Update(); + } + + private void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + if (_core == null) throw new Exception("Core not found!"); + _core.Update(); + } + + private void OnPointerPressed(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(this); + + if (PointerPressedCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); + } + + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); + } + + private void PieChart_PointerReleased(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(this); + if (PointerReleasedCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); + } + } + + private void OnPointerMoved(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(motionCanvas); + + if (PointerMoveCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); + } + + _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + } + + private void OnCoreUpdateFinished(IChartView chart) + { + UpdateFinished?.Invoke(this); + } + + private void OnCoreUpdateStarted(IChartView chart) + { + if (UpdateStartedCommand is not null) + { + var args = new ChartCommandArgs(this); + if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); + } + + UpdateStarted?.Invoke(this); + } + + private void OnCoreMeasuring(IChartView chart) + { + Measuring?.Invoke(this); + } + + private void OnPointerExited(object sender, PointerRoutedEventArgs e) + { + _core?.InvokePointerLeft(); + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + _core?.Unload(); + } + + private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + var chart = (PieChart)o; + if (chart._core == null) return; + + chart._core.Update(); + } + + void IChartView.OnDataPointerDown(IEnumerable points, LvcPoint pointer) + { + DataPointerDown?.Invoke(this, points); + if (DataPointerDownCommand is not null && DataPointerDownCommand.CanExecute(points)) DataPointerDownCommand.Execute(points); + + var closest = points.FindClosestTo(pointer); + ChartPointPointerDown?.Invoke(this, closest); + if (ChartPointPointerDownCommand is not null && ChartPointPointerDownCommand.CanExecute(closest)) ChartPointPointerDownCommand.Execute(closest); + } + + void IChartView.OnVisualElementPointerDown( + IEnumerable> visualElements, LvcPoint pointer) + { + var args = new VisualElementsEventArgs(CoreChart, visualElements, pointer); + + VisualElementsPointerDown?.Invoke(this, args); + if (VisualElementsPointerDownCommand is not null && VisualElementsPointerDownCommand.CanExecute(args)) + VisualElementsPointerDownCommand.Execute(args); + } + + void IChartView.Invalidate() + { + CoreCanvas.Invalidate(); + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml new file mode 100644 index 000000000..437f2b7de --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml @@ -0,0 +1,14 @@ + + + + + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs new file mode 100644 index 000000000..10ec031ec --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs @@ -0,0 +1,859 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using System.Windows.Input; +using LiveChartsCore.Drawing; +using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Events; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Measure; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.SKCharts; +using LiveChartsCore.SkiaSharpView.WinUI.Helpers; +using LiveChartsCore.VisualElements; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; + +// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 + +namespace LiveChartsCore.SkiaSharpView.WinUI; + +/// +public sealed partial class PolarChart : UserControl, IPolarChartView +{ + #region fields + + private Chart? _core; + private MotionCanvas? _canvas; + private readonly CollectionDeepObserver _seriesObserver; + private readonly CollectionDeepObserver _angleObserver; + private readonly CollectionDeepObserver _radiusObserver; + private readonly CollectionDeepObserver> _visualsObserver; + + #endregion + + /// + /// Initializes a new instance of the class. + /// + public PolarChart() + { + LiveCharts.Configure(config => config.UseDefaults()); + + InitializeComponent(); + + _seriesObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + _angleObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + _radiusObserver = new CollectionDeepObserver(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + _visualsObserver = new CollectionDeepObserver>( + OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true); + + Loaded += OnLoaded; + Unloaded += OnUnloaded; + + SetValue(AngleAxesProperty, new ObservableCollection() + { + LiveCharts.DefaultSettings.GetProvider().GetDefaultPolarAxis() + }); + SetValue(RadiusAxesProperty, new ObservableCollection() + { + LiveCharts.DefaultSettings.GetProvider().GetDefaultPolarAxis() + }); + SetValue(SeriesProperty, new ObservableCollection()); + SetValue(VisualElementsProperty, new ObservableCollection>()); + SetValue(SyncContextProperty, new object()); + } + + #region dependency properties + + /// + /// The fit to bounds property. + /// + public static readonly DependencyProperty FitToBoundsProperty = + DependencyProperty.Register( + nameof(FitToBounds), typeof(bool), typeof(PolarChart), new PropertyMetadata(false, OnDependencyPropertyChanged)); + + /// + /// The inner radius property. + /// + public static readonly DependencyProperty TotalAngleProperty = + DependencyProperty.Register( + nameof(TotalAngle), typeof(double), typeof(PolarChart), new PropertyMetadata(360d, OnDependencyPropertyChanged)); + + /// + /// The inner radius property. + /// + public static readonly DependencyProperty InnerRadiusProperty = + DependencyProperty.Register( + nameof(InnerRadius), typeof(double), typeof(PolarChart), new PropertyMetadata(0d, OnDependencyPropertyChanged)); + + /// + /// The initial rotation property. + /// + public static readonly DependencyProperty InitialRotationProperty = + DependencyProperty.Register( + nameof(InitialRotation), typeof(double), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.PolarInitialRotation, OnDependencyPropertyChanged)); + + /// + /// The title property. + /// + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register( + nameof(Title), typeof(VisualElement), typeof(PolarChart), new PropertyMetadata(null)); + + /// + /// The series property. + /// + public static readonly DependencyProperty SeriesProperty = + DependencyProperty.Register( + nameof(Series), typeof(IEnumerable), typeof(PolarChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (PolarChart)o; + var seriesObserver = chart._seriesObserver; + seriesObserver?.Dispose((IEnumerable)args.OldValue); + seriesObserver?.Initialize((IEnumerable)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The visual elements property + /// + public static readonly DependencyProperty VisualElementsProperty = + DependencyProperty.Register( + nameof(VisualElements), typeof(IEnumerable>), typeof(PolarChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (PolarChart)o; + var observer = chart._visualsObserver; + observer?.Dispose((IEnumerable>)args.OldValue); + observer?.Initialize((IEnumerable>)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The x axes property. + /// + public static readonly DependencyProperty AngleAxesProperty = + DependencyProperty.Register( + nameof(AngleAxes), typeof(IEnumerable), typeof(PolarChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (PolarChart)o; + var observer = chart._angleObserver; + observer?.Dispose((IEnumerable)args.OldValue); + observer?.Initialize((IEnumerable)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The y axes property. + /// + public static readonly DependencyProperty RadiusAxesProperty = + DependencyProperty.Register( + nameof(RadiusAxes), typeof(IEnumerable), typeof(PolarChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (PolarChart)o; + var observer = chart._radiusObserver; + observer?.Dispose((IEnumerable)args.OldValue); + observer?.Initialize((IEnumerable)args.NewValue); + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The sync context property. + /// + public static readonly DependencyProperty SyncContextProperty = + DependencyProperty.Register( + nameof(SyncContext), typeof(object), typeof(PolarChart), new PropertyMetadata(null, + (DependencyObject o, DependencyPropertyChangedEventArgs args) => + { + var chart = (PolarChart)o; + if (chart._canvas != null) chart.CoreCanvas.Sync = args.NewValue; + if (chart._core == null) return; + chart._core.Update(); + })); + + /// + /// The tool tip finding strategy property. + /// + public static readonly DependencyProperty TooltipFindingStrategyProperty = + DependencyProperty.Register( + nameof(TooltipFindingStrategy), typeof(TooltipFindingStrategy), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipFindingStrategy, OnDependencyPropertyChanged)); + + /// + /// The animations speed property. + /// + public static readonly DependencyProperty AnimationsSpeedProperty = + DependencyProperty.Register( + nameof(AnimationsSpeed), typeof(TimeSpan), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.AnimationsSpeed, OnDependencyPropertyChanged)); + + /// + /// The easing function property. + /// + public static readonly DependencyProperty EasingFunctionProperty = + DependencyProperty.Register( + nameof(EasingFunction), typeof(Func), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.EasingFunction, OnDependencyPropertyChanged)); + + /// + /// The legend position property. + /// + public static readonly DependencyProperty LegendPositionProperty = + DependencyProperty.Register( + nameof(LegendPosition), typeof(LegendPosition), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendPosition, OnDependencyPropertyChanged)); + + /// + /// The legend background paint property + /// + public static readonly DependencyProperty LegendBackgroundPaintProperty = + DependencyProperty.Register( + nameof(LegendBackgroundPaint), typeof(IPaint), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendBackgroundPaint, OnDependencyPropertyChanged)); + + /// + /// The legend text paint property + /// + public static readonly DependencyProperty LegendTextPaintProperty = + DependencyProperty.Register( + nameof(LegendTextPaint), typeof(IPaint), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextPaint, OnDependencyPropertyChanged)); + + /// + /// The legend text size property + /// + public static readonly DependencyProperty LegendTextSizeProperty = + DependencyProperty.Register( + nameof(LegendTextSize), typeof(double?), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.LegendTextSize, OnDependencyPropertyChanged)); + + /// + /// The tool tip position property. + /// + public static readonly DependencyProperty TooltipPositionProperty = + DependencyProperty.Register( + nameof(TooltipPosition), typeof(TooltipPosition), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipPosition, OnDependencyPropertyChanged)); + + /// + /// The tooltip background paint property + /// + public static readonly DependencyProperty TooltipBackgroundPaintProperty = + DependencyProperty.Register( + nameof(TooltipBackgroundPaint), typeof(IPaint), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipBackgroundPaint, OnDependencyPropertyChanged)); + + /// + /// The tooltip text paint property + /// + public static readonly DependencyProperty TooltipTextPaintProperty = + DependencyProperty.Register( + nameof(TooltipTextPaint), typeof(IPaint), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextPaint, OnDependencyPropertyChanged)); + + /// + /// The tooltip text size property + /// + public static readonly DependencyProperty TooltipTextSizeProperty = + DependencyProperty.Register( + nameof(TooltipTextSize), typeof(double?), typeof(PolarChart), + new PropertyMetadata(LiveCharts.DefaultSettings.TooltipTextSize, OnDependencyPropertyChanged)); + + /// + /// The update started command. + /// + public static readonly DependencyProperty UpdateStartedCommandProperty = + DependencyProperty.Register( + nameof(UpdateStartedCommand), typeof(ICommand), typeof(PolarChart), + new PropertyMetadata(null)); + + /// + /// The pointer pressed command. + /// + public static readonly DependencyProperty PointerPressedCommandProperty = + DependencyProperty.Register( + nameof(PointerPressedCommand), typeof(ICommand), typeof(PolarChart), + new PropertyMetadata(null)); + + /// + /// The pointer released command. + /// + public static readonly DependencyProperty PointerReleasedCommandProperty = + DependencyProperty.Register( + nameof(PointerReleasedCommand), typeof(ICommand), typeof(PolarChart), + new PropertyMetadata(null)); + + /// + /// The pointer move command. + /// + public static readonly DependencyProperty PointerMoveCommandProperty = + DependencyProperty.Register( + nameof(PointerMoveCommand), typeof(ICommand), typeof(PolarChart), + new PropertyMetadata(null)); + + /// + /// The data pointer down command property + /// + public static readonly DependencyProperty DataPointerDownCommandProperty = + DependencyProperty.Register( + nameof(DataPointerDownCommand), typeof(ICommand), typeof(PolarChart), new PropertyMetadata(null)); + + /// + /// The chart point pointer down command property + /// + public static readonly DependencyProperty ChartPointPointerDownCommandProperty = + DependencyProperty.Register( + nameof(ChartPointPointerDownCommand), typeof(ICommand), typeof(PolarChart), new PropertyMetadata(null)); + + /// + /// The chart point pointer down command property + /// + public static readonly DependencyProperty VisualElementsPointerDownCommandProperty = + DependencyProperty.Register( + nameof(VisualElementsPointerDownCommand), typeof(ICommand), typeof(PolarChart), new PropertyMetadata(null)); + + #endregion + + #region events + + /// + public event ChartEventHandler? Measuring; + + /// + public event ChartEventHandler? UpdateStarted; + + /// + public event ChartEventHandler? UpdateFinished; + + /// + public event ChartPointsHandler? DataPointerDown; + + /// + public event ChartPointHandler? ChartPointPointerDown; + + /// + public event VisualElementsHandler? VisualElementsPointerDown; + + #endregion + + #region properties + + /// + bool IChartView.DesignerMode => Windows.ApplicationModel.DesignMode.DesignModeEnabled; + + /// + public IChart CoreChart => _core ?? throw new Exception("Core not set yet."); + + /// + public object SyncContext + { + get => GetValue(SyncContextProperty); + set => SetValue(SyncContextProperty, value); + } + + LvcColor IChartView.BackColor + { + get => Background is not SolidColorBrush b + ? new LvcColor() + : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); + set => SetValue(BackgroundProperty, new SolidColorBrush(Windows.UI.Color.FromArgb(value.A, value.R, value.G, value.B))); + } + + /// + public Margin? DrawMargin + { + get => null; + set => throw new NotImplementedException(); + } + + Margin? IChartView.DrawMargin + { + get => DrawMargin; + set => throw new NotImplementedException(); + } + + LvcSize IChartView.ControlSize => _canvas == null + ? throw new Exception("Canvas not found") + : new LvcSize { Width = (float)_canvas.ActualWidth, Height = (float)_canvas.ActualHeight }; + + /// + public MotionCanvas CoreCanvas => _canvas == null ? throw new Exception("Canvas not found") : _canvas.CanvasCore; + + PolarChart IPolarChartView.Core => + _core == null ? throw new Exception("core not found") : (PolarChart)_core; + + /// + public bool FitToBounds + { + get => (bool)GetValue(FitToBoundsProperty); + set => SetValue(FitToBoundsProperty, value); + } + + /// + public double TotalAngle + { + get => (double)GetValue(TotalAngleProperty); + set => SetValue(TotalAngleProperty, value); + } + + /// + public double InnerRadius + { + get => (double)GetValue(InnerRadiusProperty); + set => SetValue(InnerRadiusProperty, value); + } + + /// + public double InitialRotation + { + get => (double)GetValue(InitialRotationProperty); + set => SetValue(InitialRotationProperty, value); + } + + /// + public VisualElement? Title + { + get => (VisualElement?)GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + + /// + public IEnumerable Series + { + get => (IEnumerable)GetValue(SeriesProperty); + set => SetValue(SeriesProperty, value); + } + + /// + public IEnumerable AngleAxes + { + get => (IEnumerable)GetValue(AngleAxesProperty); + set => SetValue(AngleAxesProperty, value); + } + + /// + public IEnumerable RadiusAxes + { + get => (IEnumerable)GetValue(RadiusAxesProperty); + set => SetValue(RadiusAxesProperty, value); + } + + /// + public IEnumerable> VisualElements + { + get => (IEnumerable>)GetValue(VisualElementsProperty); + set => SetValue(VisualElementsProperty, value); + } + + /// + public TimeSpan AnimationsSpeed + { + get => (TimeSpan)GetValue(AnimationsSpeedProperty); + set => SetValue(AnimationsSpeedProperty, value); + } + + TimeSpan IChartView.AnimationsSpeed + { + get => AnimationsSpeed; + set => SetValue(AnimationsSpeedProperty, value); + } + + /// + public Func EasingFunction + { + get => (Func)GetValue(EasingFunctionProperty); + set => SetValue(EasingFunctionProperty, value); + } + + Func? IChartView.EasingFunction + { + get => EasingFunction; + set => SetValue(EasingFunctionProperty, value); + } + + /// + public LegendPosition LegendPosition + { + get => (LegendPosition)GetValue(LegendPositionProperty); + set => SetValue(LegendPositionProperty, value); + } + + LegendPosition IChartView.LegendPosition + { + get => LegendPosition; + set => SetValue(LegendPositionProperty, value); + } + + /// + public TooltipPosition TooltipPosition + { + get => (TooltipPosition)GetValue(TooltipPositionProperty); + set => SetValue(TooltipPositionProperty, value); + } + + /// + public IPaint? TooltipBackgroundPaint + { + get => (IPaint?)GetValue(TooltipBackgroundPaintProperty); + set => SetValue(TooltipBackgroundPaintProperty, value); + } + + /// + public IPaint? TooltipTextPaint + { + get => (IPaint?)GetValue(TooltipTextPaintProperty); + set => SetValue(TooltipTextPaintProperty, value); + } + + /// + public double? TooltipTextSize + { + get => (double?)GetValue(TooltipTextSizeProperty); + set => SetValue(TooltipTextSizeProperty, value); + } + + /// + public IChartTooltip? Tooltip { get; set; } = new SKDefaultTooltip(); + + /// + public IPaint? LegendBackgroundPaint + { + get => (IPaint?)GetValue(LegendBackgroundPaintProperty); + set => SetValue(LegendBackgroundPaintProperty, value); + } + + /// + public IPaint? LegendTextPaint + { + get => (IPaint?)GetValue(LegendTextPaintProperty); + set => SetValue(LegendTextPaintProperty, value); + } + + /// + public double? LegendTextSize + { + get => (double?)GetValue(LegendTextSizeProperty); + set => SetValue(LegendTextSizeProperty, value); + } + + /// + public IChartLegend? Legend { get; set; } = new SKDefaultLegend(); + + /// + public bool AutoUpdateEnabled { get; set; } = true; + + /// + public TimeSpan UpdaterThrottler { get; set; } = LiveCharts.DefaultSettings.UpdateThrottlingTimeout; + + /// + /// Gets or sets a command to execute when the chart update started. + /// + public ICommand? UpdateStartedCommand + { + get => (ICommand?)GetValue(UpdateStartedCommandProperty); + set => SetValue(UpdateStartedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer is pressed on the chart. + /// + public ICommand? PointerPressedCommand + { + get => (ICommand?)GetValue(PointerPressedCommandProperty); + set => SetValue(PointerPressedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer is released on the chart. + /// + public ICommand? PointerReleasedCommand + { + get => (ICommand?)GetValue(PointerReleasedCommandProperty); + set => SetValue(PointerReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer moves over the chart. + /// + public ICommand? PointerMoveCommand + { + get => (ICommand?)GetValue(PointerMoveCommandProperty); + set => SetValue(PointerMoveCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a data or data points. + /// + public ICommand DataPointerDownCommand + { + get => (ICommand)GetValue(DataPointerDownCommandProperty); + set => SetValue(DataPointerDownCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a data or data points. + /// + public ICommand ChartPointPointerDownCommand + { + get => (ICommand)GetValue(ChartPointPointerDownCommandProperty); + set => SetValue(ChartPointPointerDownCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer goes down on a chart point. + /// + public ICommand? VisualElementsPointerDownCommand + { + get => (ICommand?)GetValue(VisualElementsPointerDownCommandProperty); + set => SetValue(VisualElementsPointerDownCommandProperty, value); + } + + #endregion + + /// + public LvcPointD ScalePixelsToData(LvcPointD point, int angleAxisIndex = 0, int radiusAxisIndex = 0) + { + if (_core is not PolarChart cc) throw new Exception("core not found"); + + var scaler = new PolarScaler( + cc.DrawMarginLocation, cc.DrawMarginSize, cc.AngleAxes[angleAxisIndex], cc.RadiusAxes[radiusAxisIndex], + cc.InnerRadius, cc.InitialRotation, cc.TotalAnge); + + return scaler.ToChartValues(point.X, point.Y); + } + + /// + public LvcPointD ScaleDataToPixels(LvcPointD point, int angleAxisIndex = 0, int radiusAxisIndex = 0) + { + if (_core is not PolarChart cc) throw new Exception("core not found"); + + var scaler = new PolarScaler( + cc.DrawMarginLocation, cc.DrawMarginSize, cc.AngleAxes[angleAxisIndex], cc.RadiusAxes[radiusAxisIndex], + cc.InnerRadius, cc.InitialRotation, cc.TotalAnge); + + var r = scaler.ToPixels(point.X, point.Y); + + return new LvcPointD { X = (float)r.X, Y = (float)r.Y }; + } + + /// + public IEnumerable GetPointsAt(LvcPoint point, TooltipFindingStrategy strategy = TooltipFindingStrategy.Automatic) + { + if (_core is not PolarChart cc) throw new Exception("core not found"); + + if (strategy == TooltipFindingStrategy.Automatic) + strategy = cc.Series.GetTooltipFindingStrategy(); + + return cc.Series.SelectMany(series => series.FindHitPoints(cc, point, strategy)); + } + + /// + public IEnumerable> GetVisualsAt(LvcPoint point) + { + return _core is not PolarChart cc + ? throw new Exception("core not found") + : cc.VisualElements.SelectMany(visual => ((VisualElement)visual).IsHitBy(_core, point)); + } + + void IChartView.InvokeOnUIThread(Action action) + { + UnoPlatformHelpers.InvokeOnUIThread(action, DispatcherQueue); + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + var canvas = (MotionCanvas)FindName("motionCanvas"); + _canvas = canvas; + + if (_core is null) + { + _core = new PolarChart(this, config => config.UseDefaults(), canvas.CanvasCore); + + if (SyncContext != null) + _canvas.CanvasCore.Sync = SyncContext; + + if (_core == null) throw new Exception("Core not found!"); + _core.Measuring += OnCoreMeasuring; + _core.UpdateStarted += OnCoreUpdateStarted; + _core.UpdateFinished += OnCoreUpdateFinished; + + PointerWheelChanged += OnWheelChanged; + PointerPressed += OnPointerPressed; + PointerReleased += OnPointerReleased; + SizeChanged += OnSizeChanged; + PointerMoved += OnPointerMoved; + PointerExited += OnPointerExited; + } + + _core.Load(); + _core.Update(); + } + + private void OnDeepCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + _core?.Update(); + } + + private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + _core?.Update(); + } + + private void OnSizeChanged(object? sender, SizeChangedEventArgs e) + { + if (_core == null) throw new Exception("Core not found!"); + _core.Update(); + } + + private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(motionCanvas); + + if (PointerMoveCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); + } + + _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + } + + private void OnCoreUpdateFinished(IChartView chart) + { + UpdateFinished?.Invoke(this); + } + + private void OnCoreUpdateStarted(IChartView chart) + { + if (UpdateStartedCommand is not null) + { + var args = new ChartCommandArgs(this); + if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); + } + + UpdateStarted?.Invoke(this); + } + + private void OnCoreMeasuring(IChartView chart) + { + Measuring?.Invoke(this); + } + + private void OnPointerExited(object sender, PointerRoutedEventArgs e) + { + _core?.InvokePointerLeft(); + } + + private void OnPointerReleased(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(this); + + if (PointerReleasedCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); + } + + _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); + } + + private void OnPointerPressed(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(this); + + if (PointerPressedCommand is not null) + { + var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); + if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); + } + + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); + } + + private void OnWheelChanged(object sender, PointerRoutedEventArgs e) + { + //if (_core == null) throw new Exception("core not found"); + //var c = (PolarChart)_core; + //var p = e.GetCurrentPoint(this); + + //c.Zoom( + // new System.Drawing.PointF( + // (float)p.Position.X, (float)p.Position.Y), + // p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + _core?.Unload(); + } + + private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) + { + var chart = (PolarChart)o; + if (chart._core == null) return; + + chart._core.Update(); + } + + void IChartView.OnDataPointerDown(IEnumerable points, LvcPoint pointer) + { + DataPointerDown?.Invoke(this, points); + if (DataPointerDownCommand is not null && DataPointerDownCommand.CanExecute(points)) DataPointerDownCommand.Execute(points); + + var closest = points.FindClosestTo(pointer); + ChartPointPointerDown?.Invoke(this, closest); + if (ChartPointPointerDownCommand is not null && ChartPointPointerDownCommand.CanExecute(closest)) + ChartPointPointerDownCommand.Execute(closest); + } + + void IChartView.OnVisualElementPointerDown( + IEnumerable> visualElements, LvcPoint pointer) + { + var args = new VisualElementsEventArgs(CoreChart, visualElements, pointer); + + VisualElementsPointerDown?.Invoke(this, args); + if (VisualElementsPointerDownCommand is not null && VisualElementsPointerDownCommand.CanExecute(args)) + VisualElementsPointerDownCommand.Execute(args); + } + + void IChartView.Invalidate() + { + CoreCanvas.Invalidate(); + } +} From 3786b292760919c979b333504e8051274afbcc6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 17:12:10 -0600 Subject: [PATCH 07/78] small navigation --- .../Presentation/MainPage.xaml | 86 ++++++------------- .../Presentation/MainPage.xaml.cs | 10 +++ 2 files changed, 37 insertions(+), 59 deletions(-) diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml index 79c601576..13985d31e 100644 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml @@ -10,47 +10,36 @@ NavigationCacheMode="Required" Background="{ThemeResource BackgroundBrush}"> - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -64,25 +53,4 @@ - - diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs index 91a8d4d8b..201a9c9c2 100644 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs @@ -4,6 +4,8 @@ namespace UnoPlatformSample.Presentation; public sealed partial class MainPage : Page { + private bool _isMenuOpen = false; + public MainPage() { this.InitializeComponent(); @@ -19,6 +21,8 @@ public MainPage() private void Border_PointerPressed(object sender, PointerRoutedEventArgs e) { + grid.ColumnDefinitions[0].Width = new GridLength(0); + var ctx = (string)((FrameworkElement)sender).DataContext; LoadSample(ctx); } @@ -29,4 +33,10 @@ private void LoadSample(string route) var t = Type.GetType($"UnoWinUISample.{route}.View") ?? throw new FileNotFoundException($"{route} not found!"); content.Content = Activator.CreateInstance(t); } + + private void Button_Click(object sender, RoutedEventArgs e) + { + grid.ColumnDefinitions[0].Width = _isMenuOpen ? new GridLength(0) : new GridLength(250); + _isMenuOpen = !_isMenuOpen; + } } From b4e6b76e5f90aba5468bcfe03489c5b96f26fc12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 18:02:26 -0600 Subject: [PATCH 08/78] add shared behaviours --- .../ChartBehaviour.Android.cs | 117 ++++++++++++++++++ .../ChartBehaviour.cs | 66 ++++++++++ .../Events/EventArgs.cs | 43 +++++++ .../Events/Handler.cs | 30 +++++ .../Events/PinchEventArgs.cs | 54 ++++++++ .../Events/PinchHandler.cs | 30 +++++ .../Events/PressedEventArgs.cs | 48 +++++++ .../Events/PressedHandler.cs | 30 +++++ .../Events/ScreenEventArgs.cs | 47 +++++++ .../Events/ScreenHandler.cs | 30 +++++ .../Events/ScrollEventArgs.cs | 48 +++++++ .../Events/ScrollHandler.cs | 30 +++++ .../LiveChartsCore.Behaviours.csproj | 14 +++ 13 files changed, 587 insertions(+) create mode 100644 src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs create mode 100644 src/LiveChartsCore.Behaviours/ChartBehaviour.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/EventArgs.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/Handler.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/PinchEventArgs.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/PinchHandler.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/PressedEventArgs.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/PressedHandler.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/ScreenEventArgs.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/ScreenHandler.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/ScrollEventArgs.cs create mode 100644 src/LiveChartsCore.Behaviours/Events/ScrollHandler.cs create mode 100644 src/LiveChartsCore.Behaviours/LiveChartsCore.Behaviours.csproj diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs new file mode 100644 index 000000000..f8cb182d8 --- /dev/null +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs @@ -0,0 +1,117 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if ANDROID + +using Android.Views; +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.Behaviours; + +public abstract partial class ChartBehaviour +{ + private bool _isPinching; + private bool _isDown; + private LvcPoint _lastTouch = new(); + private readonly ScaleGestureDetector _scaleDetector = null!; + + protected void OnAndroidHover(object? sender, View.HoverEventArgs e) + { + if (e.Event is null) return; + + var p = new LvcPoint(e.Event.GetX() / Density, e.Event.GetY() / Density); + Moved!.Invoke(sender, new(p, e.Event)); + } + + protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) + { + if (e.Event is null) return; + + var p = new LvcPoint(e.Event.GetX() / Density, e.Event.GetY() / Density); + var isRightClick = false; // can we detect this? + var isPinch = e.Event.PointerCount > 1; + + _ = _scaleDetector.OnTouchEvent(e.Event); + + switch (e.Event.ActionMasked) + { + case MotionEventActions.ButtonPress: + case MotionEventActions.Pointer1Down: + case MotionEventActions.Pointer2Down: + case MotionEventActions.Pointer3Down: + case MotionEventActions.Down: + _isPinching = isPinch; + _isDown = true; + if (!_isPinching) + Pressed?.Invoke(sender, new(p, isRightClick, e.Event)); + break; + case MotionEventActions.Move: + case MotionEventActions.HoverMove: + // the Moved event is only raised when the pointer is down, + // it is also fired frorm the hover event when the pointer is not down. + if (!_isPinching && _isDown) + Moved?.Invoke(sender, new(p, e.Event)); + break; + case MotionEventActions.ButtonRelease: + case MotionEventActions.Pointer1Up: + case MotionEventActions.Pointer2Up: + case MotionEventActions.Pointer3Up: + case MotionEventActions.Up: + case MotionEventActions.Cancel: + if (!_isPinching && _isDown) + Released?.Invoke(sender, new(p, isRightClick, e.Event)); + else + _isPinching = false; + _isDown = false; + break; + case MotionEventActions.HoverEnter: + case MotionEventActions.HoverExit: + case MotionEventActions.Mask: + case MotionEventActions.Outside: + case MotionEventActions.PointerIdMask: + case MotionEventActions.PointerIdShift: + default: + break; + } + + _lastTouch = p; + } + + private class CustomScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener + { + private readonly Action _onScaled; + + public CustomScaleListener(Action onSacaled) + { + _onScaled = onSacaled; + } + + public override bool OnScale(ScaleGestureDetector? detector) + { + if (detector is null || detector.ScaleFactor == 1) return false; + _onScaled(detector.ScaleFactor); + return true; + } + } +} + +#endif diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.cs new file mode 100644 index 000000000..fb854e50d --- /dev/null +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.cs @@ -0,0 +1,66 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Behaviours.Events; + +namespace LiveChartsCore.Behaviours; + +/// +/// A class that adds platform-specific events to the chart. +/// +public abstract partial class ChartBehaviour +{ + /// + /// Gets or sets the screen density. + /// + public double Density { get; set; } + + /// + /// Called when the pointer/tap is pressed. + /// + public event PressedHandler? Pressed; + + /// + /// Called when the pointer/tap is released. + /// + public event PressedHandler? Released; + + /// + /// Called when the pointer/tap moves. + /// + public event ScreenHandler? Moved; + + /// + /// Called when the pointer exits the control. + /// + public event Handler? Exited; + + /// + /// Called when the control is pinched. + /// + public event PinchHandler? Pinched; + + /// + /// Called when the control is scrolled. + /// + public event ScrollHandler? Scrolled; +} diff --git a/src/LiveChartsCore.Behaviours/Events/EventArgs.cs b/src/LiveChartsCore.Behaviours/Events/EventArgs.cs new file mode 100644 index 000000000..079f81ddf --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/EventArgs.cs @@ -0,0 +1,43 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the screen event args. +/// +public class EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The original event. + public EventArgs(object originalEvent) + { + OriginalEvent = originalEvent; + } + + /// + /// Gets the original event. + /// + public object OriginalEvent { get; } +} diff --git a/src/LiveChartsCore.Behaviours/Events/Handler.cs b/src/LiveChartsCore.Behaviours/Events/Handler.cs new file mode 100644 index 000000000..f78c6ab4d --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/Handler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the pinch event handler. +/// +/// The sender. +/// The args. +public delegate void Handler(object? sender, EventArgs args); diff --git a/src/LiveChartsCore.Behaviours/Events/PinchEventArgs.cs b/src/LiveChartsCore.Behaviours/Events/PinchEventArgs.cs new file mode 100644 index 000000000..d28efe6db --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/PinchEventArgs.cs @@ -0,0 +1,54 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the pinch event args. +/// +public class PinchEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The scale. + /// The start. + /// The original event. + public PinchEventArgs(float scale, LvcPoint pinchStart, object originalEvent) + : base(originalEvent) + { + Scale = scale; + PinchStart = pinchStart; + } + + /// + /// Gets the scale. + /// + public float Scale { get; } + + /// + /// Gets the pinch star location. + /// + public LvcPoint PinchStart { get; set; } +} diff --git a/src/LiveChartsCore.Behaviours/Events/PinchHandler.cs b/src/LiveChartsCore.Behaviours/Events/PinchHandler.cs new file mode 100644 index 000000000..473abc2a4 --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/PinchHandler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the pinch event handler. +/// +/// The sender. +/// The args. +public delegate void PinchHandler(object? sender, PinchEventArgs args); diff --git a/src/LiveChartsCore.Behaviours/Events/PressedEventArgs.cs b/src/LiveChartsCore.Behaviours/Events/PressedEventArgs.cs new file mode 100644 index 000000000..2aca80083 --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/PressedEventArgs.cs @@ -0,0 +1,48 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the pointer event args. +/// +public class PressedEventArgs : ScreenEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The pointer location. + /// Indicates whether the action is secondary. + /// The original event. + public PressedEventArgs(LvcPoint location, bool isSecondaryPress, object originalEvent) + : base(location, originalEvent) + { + IsSecondaryPress = isSecondaryPress; + } + + /// + /// Gets a value indicating whether the action is a secondary press. + /// + public bool IsSecondaryPress { get; } +} diff --git a/src/LiveChartsCore.Behaviours/Events/PressedHandler.cs b/src/LiveChartsCore.Behaviours/Events/PressedHandler.cs new file mode 100644 index 000000000..3a5e7cf03 --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/PressedHandler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the sreen event handler. +/// +/// The sender. +/// The args. +public delegate void PressedHandler(object? sender, PressedEventArgs args); diff --git a/src/LiveChartsCore.Behaviours/Events/ScreenEventArgs.cs b/src/LiveChartsCore.Behaviours/Events/ScreenEventArgs.cs new file mode 100644 index 000000000..de073c169 --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/ScreenEventArgs.cs @@ -0,0 +1,47 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the screen event args. +/// +public class ScreenEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The pointer location. + /// The original event. + public ScreenEventArgs(LvcPoint location, object originalEvent) + : base(originalEvent) + { + Location = location; + } + + /// + /// Gets the pointer location. + /// + public LvcPoint Location { get; } +} diff --git a/src/LiveChartsCore.Behaviours/Events/ScreenHandler.cs b/src/LiveChartsCore.Behaviours/Events/ScreenHandler.cs new file mode 100644 index 000000000..db8d49624 --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/ScreenHandler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the sreen event handler. +/// +/// The sender. +/// The args. +public delegate void ScreenHandler(object? sender, ScreenEventArgs args); diff --git a/src/LiveChartsCore.Behaviours/Events/ScrollEventArgs.cs b/src/LiveChartsCore.Behaviours/Events/ScrollEventArgs.cs new file mode 100644 index 000000000..9c57b57a4 --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/ScrollEventArgs.cs @@ -0,0 +1,48 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the scroll event args. +/// +public class ScrollEventArgs : ScreenEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The pointer location. + /// Indicates the scroll delta. + /// The original event. + public ScrollEventArgs(LvcPoint location, double scrollDelta, object originalEvent) + : base(location, originalEvent) + { + ScrollDelta = scrollDelta; + } + + /// + /// Gets the scroll delta. + /// + public double ScrollDelta { get; } +} diff --git a/src/LiveChartsCore.Behaviours/Events/ScrollHandler.cs b/src/LiveChartsCore.Behaviours/Events/ScrollHandler.cs new file mode 100644 index 000000000..224a936cc --- /dev/null +++ b/src/LiveChartsCore.Behaviours/Events/ScrollHandler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.Behaviours.Events; + +/// +/// Defines the scrroll event handler. +/// +/// The sender. +/// The args. +public delegate void ScrollHandler(object? sender, ScrollEventArgs args); diff --git a/src/LiveChartsCore.Behaviours/LiveChartsCore.Behaviours.csproj b/src/LiveChartsCore.Behaviours/LiveChartsCore.Behaviours.csproj new file mode 100644 index 000000000..07394b205 --- /dev/null +++ b/src/LiveChartsCore.Behaviours/LiveChartsCore.Behaviours.csproj @@ -0,0 +1,14 @@ + + + + net6.0;net6.0-android;net6.0-ios;net6.0-maccatalyst + $(TargetFrameworks);net6.0-windows10.0.19041.0 + enable + enable + + + + + + + From e4f9f7b8e222038010b706836d81b2686ab6d67a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 18:02:48 -0600 Subject: [PATCH 09/78] consume behaviours from maui --- .../ChartBehaviour.cs | 48 +++++++++++++++++++ .../LiveChartsCore.SkiaSharpView.Maui.csproj | 1 + 2 files changed, 49 insertions(+) create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs new file mode 100644 index 000000000..3dff6b0a1 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs @@ -0,0 +1,48 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using Microsoft.Maui.Devices; +using Microsoft.Maui.Platform; + +namespace LiveChartsCore.SkiaSharpView.Maui; + +/// +/// The chart behaviour for Uno Platform. +/// +public class ChartBehaviour : Behaviours.ChartBehaviour +{ + public void On(Microsoft.Maui.Controls.VisualElement element) + { + Density = DeviceDisplay.MainDisplayInfo.Density; + +#if ANDROID + + var contentViewGroup = (ContentViewGroup?)element.Handler?.PlatformView + ?? throw new Exception("Unable to cast to ContentViewGroup"); + + contentViewGroup.Touch += OnAndroidTouched; + contentViewGroup.Hover += OnAndroidHover; + +#endif + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj index bb97f5a64..69384e66a 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj @@ -32,6 +32,7 @@ + From d709717193022dd5c19c295d116faff1ea566460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 18:02:59 -0600 Subject: [PATCH 10/78] consume behaviours from androrid --- .../ChartBehaviour.cs | 43 +++++++++++++++++++ ...eChartsCore.SkiaSharpView.Uno.WinUI.csproj | 1 + 2 files changed, 44 insertions(+) create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs new file mode 100644 index 000000000..007d4575c --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs @@ -0,0 +1,43 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using Microsoft.UI.Xaml; + +namespace LiveChartsCore.SkiaSharpView.WinUI; + +/// +/// The chart behaviour for Uno Platform. +/// +public class ChartBehaviour : Behaviours.ChartBehaviour +{ + public void On(FrameworkElement element) + { + Density = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi / 96.0f; + +#if ANDROID + + element.Touch += OnAndroidTouched; + element.Hover += OnAndroidHover; + +#endif + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj index 2c24caf35..20b70e3e8 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj @@ -62,6 +62,7 @@ + \ No newline at end of file From f869c3cc0c46b63d6d9dd5c5b1fa03d36f935074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 18:03:13 -0600 Subject: [PATCH 11/78] add behaviours to sln --- LiveCharts.sln | 174 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 116 insertions(+), 58 deletions(-) diff --git a/LiveCharts.sln b/LiveCharts.sln index 7598fc19c..4fa7666b9 100644 --- a/LiveCharts.sln +++ b/LiveCharts.sln @@ -80,8 +80,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WinUI", "WinUI", "{39D52D6D EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinUISample", "samples\WinUISample\WinUISample\WinUISample.csproj", "{BACC7B19-20AB-41B1-AF7C-AB0682E64184}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "src\skiasharp\LiveChartsCore.SkiaSharpView.Uno.WinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{E264730C-19FF-4451-B83F-1A0633622F80}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuestPDFSample", "samples\QuestPDFSample\QuestPDFSample.csproj", "{763F1951-D833-4579-A592-1FFD960FD634}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnoPlatform", "UnoPlatform", "{5E27972E-DFEA-4825-8037-D26041333C5B}" @@ -108,6 +106,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpVie EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.DataContracts", "samples\UnoPlatformSample\UnoPlatformSample.DataContracts\UnoPlatformSample.DataContracts.csproj", "{03BDCD7C-5428-450B-A757-531AFD36C37E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.Behaviours", "src\LiveChartsCore.Behaviours\LiveChartsCore.Behaviours.csproj", "{F7B300BA-687D-4420-B658-0D1FA7F981EB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "src\skiasharp\LiveChartsCore.SkiaSharpView.UnoWinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -1590,62 +1592,6 @@ Global {BACC7B19-20AB-41B1-AF7C-AB0682E64184}.Release|x86.ActiveCfg = Release|x86 {BACC7B19-20AB-41B1-AF7C-AB0682E64184}.Release|x86.Build.0 = Release|x86 {BACC7B19-20AB-41B1-AF7C-AB0682E64184}.Release|x86.Deploy.0 = Release|x86 - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|ARM.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|ARM64.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|ARM64.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|iPhone.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|x64.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|x64.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|x86.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.AppStore|x86.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|ARM.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|ARM.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|ARM64.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|iPhone.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|x64.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|x64.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|x86.ActiveCfg = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Debug|x86.Build.0 = Debug|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|Any CPU.Build.0 = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|ARM.ActiveCfg = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|ARM.Build.0 = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|ARM64.ActiveCfg = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|ARM64.Build.0 = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|iPhone.ActiveCfg = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|iPhone.Build.0 = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|x64.ActiveCfg = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|x64.Build.0 = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|x86.ActiveCfg = Release|Any CPU - {E264730C-19FF-4451-B83F-1A0633622F80}.Release|x86.Build.0 = Release|Any CPU {763F1951-D833-4579-A592-1FFD960FD634}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU {763F1951-D833-4579-A592-1FFD960FD634}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU {763F1951-D833-4579-A592-1FFD960FD634}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU @@ -2290,6 +2236,118 @@ Global {03BDCD7C-5428-450B-A757-531AFD36C37E}.Release|x64.Build.0 = Release|Any CPU {03BDCD7C-5428-450B-A757-531AFD36C37E}.Release|x86.ActiveCfg = Release|Any CPU {03BDCD7C-5428-450B-A757-531AFD36C37E}.Release|x86.Build.0 = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|ARM.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|ARM64.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|iPhone.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|x64.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|x64.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|x86.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.AppStore|x86.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|ARM.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|ARM.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|ARM64.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|iPhone.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|x64.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|x64.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|x86.ActiveCfg = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Debug|x86.Build.0 = Debug|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|Any CPU.Build.0 = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|ARM.ActiveCfg = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|ARM.Build.0 = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|ARM64.ActiveCfg = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|ARM64.Build.0 = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|iPhone.ActiveCfg = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|iPhone.Build.0 = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|x64.ActiveCfg = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|x64.Build.0 = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|x86.ActiveCfg = Release|Any CPU + {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|x86.Build.0 = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|ARM.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|ARM64.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|iPhone.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|x64.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|x64.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|x86.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|x86.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|ARM.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|ARM.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|ARM64.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|iPhone.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|x64.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|x64.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|x86.ActiveCfg = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|x86.Build.0 = Debug|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|Any CPU.Build.0 = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|ARM.ActiveCfg = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|ARM.Build.0 = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|ARM64.ActiveCfg = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|ARM64.Build.0 = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|iPhone.ActiveCfg = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|iPhone.Build.0 = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|x64.ActiveCfg = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|x64.Build.0 = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|x86.ActiveCfg = Release|Any CPU + {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From d2013d771225d910dff026224542b457ace1b099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 18:24:30 -0600 Subject: [PATCH 12/78] add maccatalyst events --- .../ChartBehaviour.MacCatalyst.cs | 146 ++++++++++++++++++ .../ChartBehaviour.cs | 32 +++- .../ChartBehaviour.cs | 23 ++- 3 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs new file mode 100644 index 000000000..5a8b3212a --- /dev/null +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs @@ -0,0 +1,146 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if MACCATALYST || IOS + +using System; +using LiveChartsCore.Drawing; +using UIKit; + +namespace LiveChartsCore.Behaviours; + +/// +/// Add some custom events to a given MAUI visual element. +/// +public partial class ChartBehaviour +{ + protected UIHoverGestureRecognizer GetHover(UIView view) + { + return new UIHoverGestureRecognizer((UIHoverGestureRecognizer e) => + { + switch (e.State) + { + case UIGestureRecognizerState.Changed: + var p = e.LocationInView(view); + Moved!.Invoke(view, new(new(p.X, p.Y), e)); + break; + case UIGestureRecognizerState.Cancelled: + case UIGestureRecognizerState.Failed: + case UIGestureRecognizerState.Ended: + Exited?.Invoke(view, new(e)); + break; + case UIGestureRecognizerState.Possible: + case UIGestureRecognizerState.Began: + default: + break; + } + }); + } + + protected UILongPressGestureRecognizer GetLongPress(UIView view) + { + return new UILongPressGestureRecognizer((UILongPressGestureRecognizer e) => + { + var location = e.LocationInView(view); + var p = new LvcPoint((float)location.X, (float)location.Y); + var isRightClick = false; // can we detect this? + var isPinch = e.NumberOfTouches > 1; + + switch (e.State) + { + case UIGestureRecognizerState.Began: + Pressed?.Invoke(view, new(p, isRightClick, e)); + break; + case UIGestureRecognizerState.Changed: + Moved?.Invoke(view, new(p, e)); + break; + case UIGestureRecognizerState.Cancelled: + case UIGestureRecognizerState.Ended: + Released?.Invoke(view, new(p, isRightClick, e)); + break; + case UIGestureRecognizerState.Possible: + case UIGestureRecognizerState.Failed: + default: + break; + } + }) + { + MinimumPressDuration = 0, + ShouldRecognizeSimultaneously = (g1, g2) => true + }; + } + + private float _previousScale = 1; + protected UIPinchGestureRecognizer GetPinch(UIView view) + { + return new UIPinchGestureRecognizer((UIPinchGestureRecognizer e) => + { + var p = e.LocationInView(view); + + switch (e.State) + { + case UIGestureRecognizerState.Began: + _previousScale = 1; + break; + case UIGestureRecognizerState.Changed: + var s = (float)e.Scale; + var delta = _previousScale - s; + Pinched?.Invoke(view, new(1 - delta, new(p.X, p.Y), e)); + _previousScale = s; + break; + case UIGestureRecognizerState.Ended: + case UIGestureRecognizerState.Cancelled: + break; + case UIGestureRecognizerState.Possible: + case UIGestureRecognizerState.Failed: + default: + break; + } + }) + { + ShouldRecognizeSimultaneously = (g1, g2) => true + }; + } + + private CGPoint? _last; + protected UIPanGestureRecognizer GetOnPan(UIView view) + { + return new UIPanGestureRecognizer((UIPanGestureRecognizer e) => + { + var l = e.LocationInView(view); + _last ??= l; + var delta = _last.Value.Y - l.Y; + var isZoom = e.NumberOfTouches == 0; + var tolerance = 10; // just a fator to avoid multiple calls. + + if (e.State == UIGestureRecognizerState.Ended || !isZoom || Math.Abs(delta) < tolerance) return; + Scrolled?.Invoke(view, new(new(l.X, l.Y), delta, e)); + _last = l; + }) + { + AllowedScrollTypesMask = UIScrollTypeMask.Discrete | UIScrollTypeMask.Continuous, + MinimumNumberOfTouches = 0 + }; + } +} + +#endif diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs index 3dff6b0a1..a17a816a4 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs @@ -31,18 +31,40 @@ namespace LiveChartsCore.SkiaSharpView.Maui; /// public class ChartBehaviour : Behaviours.ChartBehaviour { + /// + /// Attaches the native events on the specified element. + /// + /// The element. public void On(Microsoft.Maui.Controls.VisualElement element) { - Density = DeviceDisplay.MainDisplayInfo.Density; + element.HandlerChanged += (sender, e) => + { + Density = DeviceDisplay.MainDisplayInfo.Density; #if ANDROID - var contentViewGroup = (ContentViewGroup?)element.Handler?.PlatformView - ?? throw new Exception("Unable to cast to ContentViewGroup"); + var contentViewGroup = (ContentViewGroup?)element.Handler?.PlatformView + ?? throw new Exception("Unable to cast to ContentViewGroup"); - contentViewGroup.Touch += OnAndroidTouched; - contentViewGroup.Hover += OnAndroidHover; + contentViewGroup.Touch += OnAndroidTouched; + contentViewGroup.Hover += OnAndroidHover; #endif + +#if MACCATALYST || IOS + + var contentView = (ContentView?)element.Handler?.PlatformView + ?? throw new Exception("Unable to cast to ContentView"); + + contentView.UserInteractionEnabled = true; + + contentView.AddGestureRecognizer(GetHover(contentView)); + contentView.AddGestureRecognizer(GetLongPress(contentView)); + contentView.AddGestureRecognizer(GetPinch(contentView)); + contentView.AddGestureRecognizer(GetOnPan(contentView)); + +#endif + + }; } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs index 007d4575c..0772ba88b 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs @@ -29,15 +29,34 @@ namespace LiveChartsCore.SkiaSharpView.WinUI; /// public class ChartBehaviour : Behaviours.ChartBehaviour { + /// + /// Attaches the native events on the specified element. + /// + /// The element. public void On(FrameworkElement element) { Density = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi / 96.0f; + element.Loaded += (sender, e) => + { + #if ANDROID - element.Touch += OnAndroidTouched; - element.Hover += OnAndroidHover; + element.Touch += OnAndroidTouched; + element.Hover += OnAndroidHover; + +#endif + +#if MACCATALYST || IOS + + element.UserInteractionEnabled = true; + element.AddGestureRecognizer(GetHover(element)); + element.AddGestureRecognizer(GetLongPress(element)); + element.AddGestureRecognizer(GetPinch(element)); + element.AddGestureRecognizer(GetOnPan(element)); #endif + + }; } } From 7241cee7f578f30ff8dba5bd923fbed0a645721a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 18:42:40 -0600 Subject: [PATCH 13/78] add windows --- .../ChartBehaviour.Windows.cs | 77 +++++++++++++++++++ .../LiveChartsCore.Behaviours.csproj | 6 ++ .../ChartBehaviour.cs | 18 ++++- .../ChartBehaviour.cs | 10 +++ 4 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src/LiveChartsCore.Behaviours/ChartBehaviour.Windows.cs diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.Windows.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.Windows.cs new file mode 100644 index 000000000..eb0aaf14a --- /dev/null +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.Windows.cs @@ -0,0 +1,77 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if WINDOWS + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Input; + +namespace LiveChartsCore.Behaviours; + +/// +/// A class that adds platform-specific events to the chart. +/// +public partial class ChartBehaviour +{ + protected void OnWindowsPointerPressed(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(sender as UIElement); + if (p is null) return; + + Pressed!.Invoke( + sender, + new(new(p.Position.X, p.Position.Y), p.Properties.IsRightButtonPressed, e)); + } + + protected void OnWindowsPointerMoved(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(sender as UIElement); + if (p is null) return; + + Moved!.Invoke( + sender, + new(new(p.Position.X, p.Position.Y), e)); + } + + protected void OnWindowsPointerReleased(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(sender as UIElement); + if (p is null) return; + + Released!.Invoke( + sender, + new(new(p.Position.X, p.Position.Y), p.Properties.IsRightButtonPressed, e)); + } + + protected void OnWindowsPointerWheelChanged(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(sender as UIElement); + Scrolled!.Invoke(sender, new(new(p.Position.X, p.Position.Y), p.Properties.MouseWheelDelta, e)); + } + + protected void OnWindowsPointerExited(object sender, PointerRoutedEventArgs e) + { + Exited?.Invoke(sender, new(e)); + } +} + +#endif diff --git a/src/LiveChartsCore.Behaviours/LiveChartsCore.Behaviours.csproj b/src/LiveChartsCore.Behaviours/LiveChartsCore.Behaviours.csproj index 07394b205..00e68bb6d 100644 --- a/src/LiveChartsCore.Behaviours/LiveChartsCore.Behaviours.csproj +++ b/src/LiveChartsCore.Behaviours/LiveChartsCore.Behaviours.csproj @@ -7,6 +7,12 @@ enable + + + + + + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs index a17a816a4..931f91762 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs @@ -22,7 +22,6 @@ using System; using Microsoft.Maui.Devices; -using Microsoft.Maui.Platform; namespace LiveChartsCore.SkiaSharpView.Maui; @@ -43,7 +42,7 @@ public void On(Microsoft.Maui.Controls.VisualElement element) #if ANDROID - var contentViewGroup = (ContentViewGroup?)element.Handler?.PlatformView + var contentViewGroup = (Microsoft.Maui.Platform.ContentViewGroup?)element.Handler?.PlatformView ?? throw new Exception("Unable to cast to ContentViewGroup"); contentViewGroup.Touch += OnAndroidTouched; @@ -53,7 +52,7 @@ public void On(Microsoft.Maui.Controls.VisualElement element) #if MACCATALYST || IOS - var contentView = (ContentView?)element.Handler?.PlatformView + var contentView = (Microsoft.Maui.Platform.ContentView?)element.Handler?.PlatformView ?? throw new Exception("Unable to cast to ContentView"); contentView.UserInteractionEnabled = true; @@ -63,6 +62,19 @@ public void On(Microsoft.Maui.Controls.VisualElement element) contentView.AddGestureRecognizer(GetPinch(contentView)); contentView.AddGestureRecognizer(GetOnPan(contentView)); +#endif + +#if WINDOWS + + var contentPanel = (Microsoft.UI.Xaml.UIElement?)element.Handler?.PlatformView + ?? throw new Exception("Unable to cast to ContentPanel"); + + contentPanel.PointerPressed += OnWindowsPointerPressed; + contentPanel.PointerMoved += OnWindowsPointerMoved; + contentPanel.PointerReleased += OnWindowsPointerReleased; + contentPanel.PointerWheelChanged += OnWindowsPointerWheelChanged; + contentPanel.PointerExited += OnWindowsPointerExited; + #endif }; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs index 0772ba88b..43da1178a 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs @@ -55,6 +55,16 @@ public void On(FrameworkElement element) element.AddGestureRecognizer(GetPinch(element)); element.AddGestureRecognizer(GetOnPan(element)); +#endif + +#if WINDOWS + + element.PointerPressed += OnWindowsPointerPressed; + element.PointerMoved += OnWindowsPointerMoved; + element.PointerReleased += OnWindowsPointerReleased; + element.PointerWheelChanged += OnWindowsPointerWheelChanged; + element.PointerExited += OnWindowsPointerExited; + #endif }; From e74704d57258b7cd40f87f42fb91f16f97927889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 18:44:29 -0600 Subject: [PATCH 14/78] rename and docs --- .../ChartBehaviour.Android.cs | 3 +++ .../ChartBehaviour.MacCatalyst.cs | 10 +++++----- .../{ChartBehaviour.cs => ChartBehaviour._shared.cs} | 0 .../ChartBehaviour.cs | 8 ++++---- .../ChartBehaviour.cs | 8 ++++---- 5 files changed, 16 insertions(+), 13 deletions(-) rename src/LiveChartsCore.Behaviours/{ChartBehaviour.cs => ChartBehaviour._shared.cs} (100%) diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs index f8cb182d8..acb417472 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs @@ -27,6 +27,9 @@ namespace LiveChartsCore.Behaviours; +/// +/// A class that adds platform-specific events to the chart. +/// public abstract partial class ChartBehaviour { private bool _isPinching; diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs index 5a8b3212a..dec0a8a00 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs @@ -29,11 +29,11 @@ namespace LiveChartsCore.Behaviours; /// -/// Add some custom events to a given MAUI visual element. +/// A class that adds platform-specific events to the chart. /// public partial class ChartBehaviour { - protected UIHoverGestureRecognizer GetHover(UIView view) + protected UIHoverGestureRecognizer GetMacCatalystHover(UIView view) { return new UIHoverGestureRecognizer((UIHoverGestureRecognizer e) => { @@ -56,7 +56,7 @@ protected UIHoverGestureRecognizer GetHover(UIView view) }); } - protected UILongPressGestureRecognizer GetLongPress(UIView view) + protected UILongPressGestureRecognizer GetMacCatalystLongPress(UIView view) { return new UILongPressGestureRecognizer((UILongPressGestureRecognizer e) => { @@ -90,7 +90,7 @@ protected UILongPressGestureRecognizer GetLongPress(UIView view) } private float _previousScale = 1; - protected UIPinchGestureRecognizer GetPinch(UIView view) + protected UIPinchGestureRecognizer GetMacCatalystPinch(UIView view) { return new UIPinchGestureRecognizer((UIPinchGestureRecognizer e) => { @@ -122,7 +122,7 @@ protected UIPinchGestureRecognizer GetPinch(UIView view) } private CGPoint? _last; - protected UIPanGestureRecognizer GetOnPan(UIView view) + protected UIPanGestureRecognizer GetMacCatalystOnPan(UIView view) { return new UIPanGestureRecognizer((UIPanGestureRecognizer e) => { diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour._shared.cs similarity index 100% rename from src/LiveChartsCore.Behaviours/ChartBehaviour.cs rename to src/LiveChartsCore.Behaviours/ChartBehaviour._shared.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs index 931f91762..8e0cb10e4 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs @@ -57,10 +57,10 @@ public void On(Microsoft.Maui.Controls.VisualElement element) contentView.UserInteractionEnabled = true; - contentView.AddGestureRecognizer(GetHover(contentView)); - contentView.AddGestureRecognizer(GetLongPress(contentView)); - contentView.AddGestureRecognizer(GetPinch(contentView)); - contentView.AddGestureRecognizer(GetOnPan(contentView)); + contentView.AddGestureRecognizer(GetMacCatalystHover(contentView)); + contentView.AddGestureRecognizer(GetMacCatalystLongPress(contentView)); + contentView.AddGestureRecognizer(GetMacCatalystPinch(contentView)); + contentView.AddGestureRecognizer(GetMacCatalystOnPan(contentView)); #endif diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs index 43da1178a..6fac8ebf8 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs @@ -50,10 +50,10 @@ public void On(FrameworkElement element) #if MACCATALYST || IOS element.UserInteractionEnabled = true; - element.AddGestureRecognizer(GetHover(element)); - element.AddGestureRecognizer(GetLongPress(element)); - element.AddGestureRecognizer(GetPinch(element)); - element.AddGestureRecognizer(GetOnPan(element)); + element.AddGestureRecognizer(GetMacCatalystHover(element)); + element.AddGestureRecognizer(GetMacCatalystLongPress(element)); + element.AddGestureRecognizer(GetMacCatalystPinch(element)); + element.AddGestureRecognizer(GetMacCatalystOnPan(element)); #endif From e39906e5cca190c2ee861f7252a6e1de8aab6b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 18:59:30 -0600 Subject: [PATCH 15/78] remove maui geestures --- .../CartesianChart.xaml.cs | 265 ------------------ .../LiveChartsCore.SkiaSharpView.Maui.csproj | 4 +- .../PieChart.xaml | 8 +- .../PieChart.xaml.cs | 43 +-- .../PolarChart.xaml | 8 +- .../PolarChart.xaml.cs | 41 --- 6 files changed, 5 insertions(+), 364 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs index bdceb8efd..26482ea42 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs @@ -37,18 +37,12 @@ using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Drawing; using LiveChartsCore.SkiaSharpView.Drawing.Geometries; -using LiveChartsCore.SkiaSharpView.Painting; using LiveChartsCore.SkiaSharpView.SKCharts; using LiveChartsCore.VisualElements; -using Microsoft.Maui; using Microsoft.Maui.ApplicationModel; using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Xaml; -using Microsoft.Maui.Devices; using Microsoft.Maui.Graphics; -#if MACCATALYST -using UIKit; -#endif namespace LiveChartsCore.SkiaSharpView.Maui; @@ -64,10 +58,6 @@ public partial class CartesianChart : ContentView, ICartesianChartView _yObserver; private readonly CollectionDeepObserver> _sectionsObserver; private readonly CollectionDeepObserver> _visualsObserver; - private double _lastScale = 0; - private DateTime _panLocketUntil; - private double _lastPanX = 0; - private double _lastPanY = 0; private IChartLegend? _legend = new SKDefaultLegend(); private IChartTooltip? _tooltip = new SKDefaultTooltip(); private TimeSpan _tooltipCloseInterval = TimeSpan.FromMilliseconds(3500); @@ -117,34 +107,6 @@ public CartesianChart() _closeTooltipTimer.Interval = TooltipCloseInterval.TotalMilliseconds; _closeTooltipTimer.Elapsed += OnTooltipTimerEllapsed; - -#if __MOBILE__ - - var pinchGesture = new PinchGestureRecognizer(); - var panGesture = new PanGestureRecognizer(); - var tapGesture = new TapGestureRecognizer(); - - pinchGesture.PinchUpdated += OnPinchUpdated; - panGesture.PanUpdated += OnPanUpdated; - tapGesture.Tapped += OnTapped; - - canvas.GestureRecognizers.Add(pinchGesture); - canvas.GestureRecognizers.Add(panGesture); - canvas.GestureRecognizers.Add(tapGesture); - -#endif - -#if WINDOWS - - canvas.HandlerChanged += OnHandlerChanged; - -#endif - -#if MACCATALYST - - canvas.HandlerChanged += OnHandlerChanged; - -#endif } #region bindable properties @@ -801,233 +763,6 @@ private void OnSizeChanged(object? sender, EventArgs e) _core?.Update(); } -#if __MOBILE__ - - private void OnPanUpdated(object? sender, PanUpdatedEventArgs e) - { - if (_core is null) return; - if (e.StatusType is not GestureStatus.Running and not GestureStatus.Completed) return; - if (DateTime.Now < _panLocketUntil) return; - - var c = (CartesianChart)_core; - - if (e.StatusType == GestureStatus.Running) - { - var delta = new LvcPoint( - (float)(e.TotalX - _lastPanX), - (float)(e.TotalY - _lastPanY)); - - var args = new PanGestureEventArgs(delta); - c.InvokePanGestrue(args); - - if (args.Handled) return; - - c.Pan(delta, true); - _lastPanX = e.TotalX; - _lastPanY = e.TotalY; - - return; - } - - // lets just let the core know that the pan finished, - // so the core is able to bounce back the plot in case it exceeded the allowed limits - // this is a dummy request of += 0.01 pixels just in the corresponding direction - c.Pan(new LvcPoint(_lastPanX > 0 ? 0.01f : -0.01f, _lastPanY > 0 ? 0.01f : -0.01f), false); - - _lastPanX = 0; - _lastPanY = 0; - } - - private void OnPinchUpdated(object? sender, PinchGestureUpdatedEventArgs e) - { - if (_core is null) return; - if (e.Status is not GestureStatus.Running and not GestureStatus.Completed) return; - - var c = (CartesianChart)_core; - var p = e.ScaleOrigin; - var s = c.ControlSize; - - var pivot = new LvcPoint((float)(p.X * s.Width), (float)(p.Y * s.Height)); - - if (e.Status == GestureStatus.Running) - { - c.Zoom(pivot, ZoomDirection.DefinedByScaleFactor, e.Scale, true); - _panLocketUntil = DateTime.Now.AddMilliseconds(500); - _lastScale = e.Scale; - return; - } - - // lets just let the core know that the zoom finished, - // so the core is able to bounce back the plot in case it exceeded the allowed limits - // this is a dummy request of += .001 percent just in the corresponding direction - c.Zoom(pivot, ZoomDirection.DefinedByScaleFactor, _lastScale < 1 ? 0.99999 : 1.00001, false); - } - - private void OnTapped(object? sender, TappedEventArgs e) - { - if (_core is null) return; - var p = e.GetPosition(this); - if (p is null) return; - - if (TappedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Value.X, p.Value.Y), e); - if (TappedCommand.CanExecute(args)) TappedCommand.Execute(args); - } - - var location = new LvcPoint(p.Value.X, p.Value.Y); - _core.InvokePointerDown(location, false); - _core.InvokePointerMove(location); - _core.InvokePointerUp(location, false); - - if (DeviceInfo.Platform != DevicePlatform.macOS) - { - _closeTooltipTimer.Stop(); - _closeTooltipTimer.Start(); - } - } - -#endif - -#if WINDOWS - private bool _isZoomingSectionAttached = false; - - private void OnHandlerChanged(object? sender, EventArgs e) - { - var panel = (Microsoft.Maui.Platform.ContentPanel?)canvas.Handler?.PlatformView - ?? throw new Exception("Unable to cast to ContentPanel"); - - panel.PointerWheelChanged += OnPointerWheelChanged; - panel.PointerPressed += OnPointerPressed; - panel.PointerReleased += OnPointerReleased; - panel.PointerMoved += OnPointerMoved; - panel.PointerExited += OnPointerExited; - } - - private void OnPointerMoved(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(sender as Microsoft.Maui.Platform.ContentPanel)?.Position; - if (p is null) return; - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Value.X, p.Value.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Value.X, (float)p.Value.Y)); - } - - private void OnPointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) - { - // not implemented yet? - // https://github.com/dotnet/maui/issues/16202 - //if (Keyboard.Modifiers > 0) return; - - if (!_isZoomingSectionAttached) - { - var zoomingSectionPaint = new SolidColorPaint - { - IsFill = true, - Color = new SkiaSharp.SKColor(33, 150, 243, 50), - ZIndex = int.MaxValue - }; - var zoomingSection = ((CartesianChart)CoreChart)._zoomingSection; - zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); - canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); - _isZoomingSectionAttached = true; - } - - var p = e.GetCurrentPoint(sender as Microsoft.Maui.Platform.ContentPanel); - _core?.InvokePointerDown( - new LvcPoint((float)p.Position.X, (float)p.Position.Y), p.Properties.IsRightButtonPressed); - } - - private void OnPointerReleased(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(sender as Microsoft.Maui.Platform.ContentPanel); - _core?.InvokePointerUp( - new LvcPoint((float)p.Position.X, (float)p.Position.Y), p.Properties.IsRightButtonPressed); - } - - private void OnPointerWheelChanged(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) - { - if (_core is null) throw new Exception("core not found"); - var c = (CartesianChart)_core; - var p = e.GetCurrentPoint(sender as Microsoft.Maui.Platform.ContentPanel); - c.Zoom( - new LvcPoint((float)p.Position.X, (float)p.Position.Y), - p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); - } - - private void OnPointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - -#endif - -#if MACCATALYST - - private void OnHandlerChanged(object? sender, EventArgs e) - { - var view = (Microsoft.Maui.Platform.ContentView?)canvas.Handler?.PlatformView - ?? throw new Exception("Unable to cast to ContentView"); - - view.AddGestureRecognizer(new UIHoverGestureRecognizer(GetOnHover(view))); - view.AddGestureRecognizer(new UIPanGestureRecognizer(GetOnPan(view)) - { - AllowedScrollTypesMask = UIScrollTypeMask.Discrete | UIScrollTypeMask.Continuous, - MinimumNumberOfTouches = 0 - }); - - var pointerGesture = new PointerGestureRecognizer(); - pointerGesture.PointerExited += OnPointerExited; - canvas.GestureRecognizers.Add(pointerGesture); - } - - private Action GetOnHover(UIView view) - { - return (UIHoverGestureRecognizer e) => - { - var p = e.LocationInView(view); - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.X, p.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.X, (float)p.Y)); - }; - } - - private CoreGraphics.CGPoint? _last; - private Action GetOnPan(UIView view) - { - return (UIPanGestureRecognizer e) => - { - var l = e.LocationInView(view); - _last ??= l; - var delta = _last.Value.Y - l.Y; - var isZoom = e.NumberOfTouches == 0; - - if (e.State == UIGestureRecognizerState.Ended || !isZoom || delta == 0) return; - - var c = (CartesianChart)CoreChart; - c.Zoom(new(l.X, l.Y), delta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); - - _last = l; - }; - } - - private void OnPointerExited(object? sender, PointerEventArgs e) - { - _core?.InvokePointerLeft(); - } - -#endif - private void OnTooltipTimerEllapsed(object? sender, ElapsedEventArgs e) { if (_core is null) return; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj index 69384e66a..85da52d91 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj @@ -1,8 +1,8 @@ - net7.0;net7.0-android;net7.0-ios;net7.0-maccatalyst - $(TargetFrameworks);net7.0-windows10.0.19041.0 + net6.0;net6.0-android;net6.0-ios;net6.0-maccatalyst + $(TargetFrameworks);net6.0-windows10.0.19041.0 true true enable diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml index 88a3b92f3..a366d8f8d 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml @@ -4,12 +4,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.Maui"> - - - - - - + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs index 8a8f26bb6..23e518e71 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs @@ -654,29 +654,7 @@ private void OnSizeChanged(object? sender, EventArgs e) _core.Update(); } - private void OnTapped(object sender, TappedEventArgs e) - { - if (_core is null) return; - var p = e.GetPosition(this); - if (p is null) return; - - if (TappedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Value.X, p.Value.Y), e); - if (TappedCommand.CanExecute(args)) TappedCommand.Execute(args); - } - - var location = new LvcPoint(p.Value.X, p.Value.Y); - _core.InvokePointerDown(location, false); - _core.InvokePointerMove(location); - -#if __MOBILE__ - _closeTooltipTimer.Stop(); - _closeTooltipTimer.Start(); -#endif - } - - private void OnTooltipTimerEllapsed(object sender, ElapsedEventArgs e) + private void OnTooltipTimerEllapsed(object? sender, ElapsedEventArgs e) { if (_core is null) return; MainThread.BeginInvokeOnMainThread(() => @@ -687,20 +665,6 @@ private void OnTooltipTimerEllapsed(object sender, ElapsedEventArgs e) }); } - private void OnPointerMoved(object sender, PointerEventArgs e) - { - var p = e.GetPosition(this); - if (p is null) return; - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Value.X, p.Value.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Value.X, (float)p.Value.Y)); - } - private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); @@ -722,11 +686,6 @@ private void OnCoreMeasuring(IChartView chart) Measuring?.Invoke(this); } - private void OnPointerExited(object sender, PointerEventArgs e) - { - _core?.InvokePointerLeft(); - } - void IChartView.OnDataPointerDown(IEnumerable points, LvcPoint pointer) { DataPointerDown?.Invoke(this, points); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml index 0873e1535..c80199267 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml @@ -4,12 +4,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.Maui"> - - - - - - + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs index 547966ff9..3eab2f1c7 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs @@ -746,28 +746,6 @@ private void OnCoreUpdateStarted(IChartView chart) UpdateStarted?.Invoke(this); } - private void OnTapped(object sender, TappedEventArgs e) - { - if (_core is null) return; - var p = e.GetPosition(this); - if (p is null) return; - - if (TappedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Value.X, p.Value.Y), e); - if (TappedCommand.CanExecute(args)) TappedCommand.Execute(args); - } - - var location = new LvcPoint(p.Value.X, p.Value.Y); - _core.InvokePointerDown(location, false); - _core.InvokePointerMove(location); - -#if __MOBILE__ - _closeTooltipTimer.Stop(); - _closeTooltipTimer.Start(); -#endif - } - private void OnTooltipTimerEllapsed(object sender, ElapsedEventArgs e) { if (_core is null) return; @@ -779,30 +757,11 @@ private void OnTooltipTimerEllapsed(object sender, ElapsedEventArgs e) }); } - private void OnPointerMoved(object sender, PointerEventArgs e) - { - var p = e.GetPosition(this); - if (p is null) return; - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Value.X, p.Value.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Value.X, (float)p.Value.Y)); - } - private void OnCoreMeasuring(IChartView chart) { Measuring?.Invoke(this); } - private void OnPointerExited(object sender, PointerEventArgs e) - { - _core?.InvokePointerLeft(); - } - void IChartView.OnDataPointerDown(IEnumerable points, LvcPoint pointer) { DataPointerDown?.Invoke(this, points); From b4969a3cd29407de0438af99eac8aa054e8b8042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 4 Sep 2023 19:05:12 -0600 Subject: [PATCH 16/78] we can now target net6 --- .../LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj index 20b70e3e8..917c395f4 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj @@ -1,7 +1,7 @@ - $(TargetFrameworks);net7.0-windows10.0.19041 - $(TargetFrameworks);net7.0;net7.0-ios;net7.0-maccatalyst;net7.0-android + $(TargetFrameworks);net6.0-windows10.0.19041 + $(TargetFrameworks);net6.0;net6.0-ios;net6.0-maccatalyst;net6.0-android true From 46a74db1e0504093b35e4481d0ff2b26b590e0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 09:52:41 -0600 Subject: [PATCH 17/78] Apply chart behaviour to maui controls --- .../ChartBehaviour.Android.cs | 5 +- .../CartesianChart.xaml.cs | 119 ++++++++++++++++-- .../ChartBehaviour.cs | 9 +- .../PieChart.xaml.cs | 103 +++++++++++++-- .../PolarChart.xaml.cs | 105 ++++++++++++++-- 5 files changed, 304 insertions(+), 37 deletions(-) diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs index acb417472..8b02207c6 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs @@ -34,7 +34,6 @@ public abstract partial class ChartBehaviour { private bool _isPinching; private bool _isDown; - private LvcPoint _lastTouch = new(); private readonly ScaleGestureDetector _scaleDetector = null!; protected void OnAndroidHover(object? sender, View.HoverEventArgs e) @@ -70,7 +69,7 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) case MotionEventActions.Move: case MotionEventActions.HoverMove: // the Moved event is only raised when the pointer is down, - // it is also fired frorm the hover event when the pointer is not down. + // it is also fired from the hover handler when the pointer is not down. if (!_isPinching && _isDown) Moved?.Invoke(sender, new(p, e.Event)); break; @@ -95,8 +94,6 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) default: break; } - - _lastTouch = p; } private class CustomScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs index 26482ea42..40cd6f922 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs @@ -37,6 +37,7 @@ using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Drawing; using LiveChartsCore.SkiaSharpView.Drawing.Geometries; +using LiveChartsCore.SkiaSharpView.Painting; using LiveChartsCore.SkiaSharpView.SKCharts; using LiveChartsCore.VisualElements; using Microsoft.Maui.ApplicationModel; @@ -62,6 +63,7 @@ public partial class CartesianChart : ContentView, ICartesianChartView? _tooltip = new SKDefaultTooltip(); private TimeSpan _tooltipCloseInterval = TimeSpan.FromMilliseconds(3500); private readonly Timer _closeTooltipTimer = new(); + private bool _isZoomingSectionAttached; #endregion @@ -107,6 +109,16 @@ public CartesianChart() _closeTooltipTimer.Interval = TooltipCloseInterval.TotalMilliseconds; _closeTooltipTimer.Elapsed += OnTooltipTimerEllapsed; + + var chartBehaviour = new ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } #region bindable properties @@ -338,18 +350,25 @@ public CartesianChart() nameof(UpdateStartedCommand), typeof(ICommand), typeof(CartesianChart), null); /// - /// The tapped command. + /// The pressed command. + /// + public static readonly BindableProperty PressedCommandProperty = + BindableProperty.Create( + nameof(PressedCommand), typeof(ICommand), typeof(CartesianChart), null); + + /// + /// The released command. /// - public static readonly BindableProperty TappedCommandProperty = + public static readonly BindableProperty ReleasedCommandProperty = BindableProperty.Create( - nameof(TappedCommand), typeof(ICommand), typeof(CartesianChart), null); + nameof(ReleasedCommand), typeof(ICommand), typeof(CartesianChart), null); /// /// The pointer move command. /// - public static readonly BindableProperty PointerMoveCommandProperty = + public static readonly BindableProperty MovedCommandProperty = BindableProperty.Create( - nameof(PointerMoveCommand), typeof(ICommand), typeof(CartesianChart), null); + nameof(MovedCommand), typeof(ICommand), typeof(CartesianChart), null); /// /// The data pointer down command property @@ -599,19 +618,48 @@ public ICommand? UpdateStartedCommand /// /// Gets or sets a command to execute when the users taped the chart. /// + [Obsolete($"Replaced by {nameof(PressedCommand)} and {nameof(ReleasedCommand)}")] public ICommand? TappedCommand { - get => (ICommand?)GetValue(TappedCommandProperty); - set => SetValue(TappedCommandProperty, value); + get => (ICommand?)GetValue(ReleasedCommandProperty); + set => SetValue(ReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the prressed the chart. + /// + public ICommand? PressedCommand + { + get => (ICommand?)GetValue(PressedCommandProperty); + set => SetValue(PressedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the users released thhe press on the chart. + /// + public ICommand? ReleasedCommand + { + get => (ICommand?)GetValue(ReleasedCommandProperty); + set => SetValue(ReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer/finger moves over the chart. + /// + public ICommand? MovedCommand + { + get => (ICommand?)GetValue(MovedCommandProperty); + set => SetValue(MovedCommandProperty, value); } /// /// Gets or sets a command to execute when the pointer moves over the chart. /// + [Obsolete($"Use {nameof(MovedCommand)} instead.")] public ICommand? PointerMoveCommand { - get => (ICommand?)GetValue(PointerMoveCommandProperty); - set => SetValue(PointerMoveCommandProperty, value); + get => (ICommand?)GetValue(MovedCommandProperty); + set => SetValue(MovedCommandProperty, value); } /// @@ -748,6 +796,59 @@ protected override void OnParentSet() _core?.Load(); } + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) + { + // not implemented yet? + // https://github.com/dotnet/maui/issues/16202 + //if (Keyboard.Modifiers > 0) return; + + if (!_isZoomingSectionAttached) + { + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + var zoomingSection = ((CartesianChart)CoreChart)._zoomingSection; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + _isZoomingSectionAttached = true; + } + + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PressedCommand?.CanExecute(cArgs) == true) PressedCommand.Execute(cArgs); + + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); + } + + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) + { + var location = args.Location; + + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (MovedCommand?.CanExecute(cArgs) == true) MovedCommand.Execute(cArgs); + + _core?.InvokePointerMove(location); + } + + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) + { + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); + } + + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) + { + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnExited(object? sender, Behaviours.Events.EventArgs args) + { + _core?.InvokePointerLeft(); + } + private void OnDeepCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { _core?.Update(); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs index 8e0cb10e4..764bb75bc 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartBehaviour.cs @@ -20,13 +20,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -using System; using Microsoft.Maui.Devices; namespace LiveChartsCore.SkiaSharpView.Maui; /// -/// The chart behaviour for Uno Platform. +/// The chart behaviour for MAUI. /// public class ChartBehaviour : Behaviours.ChartBehaviour { @@ -43,7 +42,7 @@ public void On(Microsoft.Maui.Controls.VisualElement element) #if ANDROID var contentViewGroup = (Microsoft.Maui.Platform.ContentViewGroup?)element.Handler?.PlatformView - ?? throw new Exception("Unable to cast to ContentViewGroup"); + ?? throw new System.Exception("Unable to cast to ContentViewGroup"); contentViewGroup.Touch += OnAndroidTouched; contentViewGroup.Hover += OnAndroidHover; @@ -53,7 +52,7 @@ public void On(Microsoft.Maui.Controls.VisualElement element) #if MACCATALYST || IOS var contentView = (Microsoft.Maui.Platform.ContentView?)element.Handler?.PlatformView - ?? throw new Exception("Unable to cast to ContentView"); + ?? throw new System.Exception("Unable to cast to ContentView"); contentView.UserInteractionEnabled = true; @@ -67,7 +66,7 @@ public void On(Microsoft.Maui.Controls.VisualElement element) #if WINDOWS var contentPanel = (Microsoft.UI.Xaml.UIElement?)element.Handler?.PlatformView - ?? throw new Exception("Unable to cast to ContentPanel"); + ?? throw new System.Exception("Unable to cast to ContentPanel"); contentPanel.PointerPressed += OnWindowsPointerPressed; contentPanel.PointerMoved += OnWindowsPointerMoved; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs index 23e518e71..70e905962 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs @@ -91,6 +91,16 @@ public PieChart() _closeTooltipTimer.Interval = TooltipCloseInterval.TotalMilliseconds; _closeTooltipTimer.Elapsed += OnTooltipTimerEllapsed; + + var chartBehaviour = new ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } #region bindable properties @@ -276,18 +286,25 @@ public PieChart() nameof(UpdateStartedCommand), typeof(ICommand), typeof(PieChart), null); /// - /// The tapped command. + /// The pressed command. /// - public static readonly BindableProperty TappedCommandProperty = + public static readonly BindableProperty PressedCommandProperty = BindableProperty.Create( - nameof(TappedCommand), typeof(ICommand), typeof(PieChart), null); + nameof(PressedCommand), typeof(ICommand), typeof(PieChart), null); + + /// + /// The released command. + /// + public static readonly BindableProperty ReleasedCommandProperty = + BindableProperty.Create( + nameof(ReleasedCommand), typeof(ICommand), typeof(PieChart), null); /// /// The pointer move command. /// - public static readonly BindableProperty PointerMoveCommandProperty = + public static readonly BindableProperty MovedCommandProperty = BindableProperty.Create( - nameof(PointerMoveCommand), typeof(ICommand), typeof(PieChart), null); + nameof(MovedCommand), typeof(ICommand), typeof(PieChart), null); /// /// The data pointer down command property @@ -532,19 +549,48 @@ public ICommand? UpdateStartedCommand /// /// Gets or sets a command to execute when the users taped the chart. /// + [Obsolete($"Replaced by {nameof(PressedCommand)} and {nameof(ReleasedCommand)}")] public ICommand? TappedCommand { - get => (ICommand?)GetValue(TappedCommandProperty); - set => SetValue(TappedCommandProperty, value); + get => (ICommand?)GetValue(ReleasedCommandProperty); + set => SetValue(ReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the prressed the chart. + /// + public ICommand? PressedCommand + { + get => (ICommand?)GetValue(PressedCommandProperty); + set => SetValue(PressedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the users released thhe press on the chart. + /// + public ICommand? ReleasedCommand + { + get => (ICommand?)GetValue(ReleasedCommandProperty); + set => SetValue(ReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer/finger moves over the chart. + /// + public ICommand? MovedCommand + { + get => (ICommand?)GetValue(MovedCommandProperty); + set => SetValue(MovedCommandProperty, value); } /// /// Gets or sets a command to execute when the pointer moves over the chart. /// + [Obsolete($"Use {nameof(MovedCommand)} instead.")] public ICommand? PointerMoveCommand { - get => (ICommand?)GetValue(PointerMoveCommandProperty); - set => SetValue(PointerMoveCommandProperty, value); + get => (ICommand?)GetValue(MovedCommandProperty); + set => SetValue(MovedCommandProperty, value); } /// @@ -648,6 +694,45 @@ protected override void OnParentSet() _core?.Load(); } + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) + { + // not implemented yet? + // https://github.com/dotnet/maui/issues/16202 + //if (Keyboard.Modifiers > 0) return; + + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PressedCommand?.CanExecute(cArgs) == true) PressedCommand.Execute(cArgs); + + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); + } + + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) + { + var location = args.Location; + + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (MovedCommand?.CanExecute(cArgs) == true) MovedCommand.Execute(cArgs); + + _core?.InvokePointerMove(location); + } + + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) + { + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); + } + + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) + { + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnExited(object? sender, Behaviours.Events.EventArgs args) + { + _core?.InvokePointerLeft(); + } + private void OnSizeChanged(object? sender, EventArgs e) { if (_core is null) return; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs index 3eab2f1c7..07bf1c4f8 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs @@ -102,6 +102,16 @@ public PolarChart() _closeTooltipTimer.Interval = TooltipCloseInterval.TotalMilliseconds; _closeTooltipTimer.Elapsed += OnTooltipTimerEllapsed; + + var chartBehaviour = new ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } #region bindable properties @@ -318,18 +328,25 @@ public PolarChart() nameof(UpdateStartedCommand), typeof(ICommand), typeof(PolarChart), null); /// - /// The tapped command. + /// The pressed command. /// - public static readonly BindableProperty TappedCommandProperty = + public static readonly BindableProperty PressedCommandProperty = BindableProperty.Create( - nameof(TappedCommand), typeof(ICommand), typeof(PolarChart), null); + nameof(PressedCommand), typeof(ICommand), typeof(PolarChart), null); + + /// + /// The released command. + /// + public static readonly BindableProperty ReleasedCommandProperty = + BindableProperty.Create( + nameof(ReleasedCommand), typeof(ICommand), typeof(PolarChart), null); /// /// The pointer move command. /// - public static readonly BindableProperty PointerMoveCommandProperty = + public static readonly BindableProperty MovedCommandProperty = BindableProperty.Create( - nameof(PointerMoveCommand), typeof(ICommand), typeof(CartesianChart), null); + nameof(MovedCommand), typeof(ICommand), typeof(PolarChart), null); /// /// The data pointer down command property @@ -572,19 +589,48 @@ public ICommand? UpdateStartedCommand /// /// Gets or sets a command to execute when the users taped the chart. /// + [Obsolete($"Replaced by {nameof(PressedCommand)} and {nameof(ReleasedCommand)}")] public ICommand? TappedCommand { - get => (ICommand?)GetValue(TappedCommandProperty); - set => SetValue(TappedCommandProperty, value); + get => (ICommand?)GetValue(ReleasedCommandProperty); + set => SetValue(ReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the prressed the chart. + /// + public ICommand? PressedCommand + { + get => (ICommand?)GetValue(PressedCommandProperty); + set => SetValue(PressedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the users released thhe press on the chart. + /// + public ICommand? ReleasedCommand + { + get => (ICommand?)GetValue(ReleasedCommandProperty); + set => SetValue(ReleasedCommandProperty, value); + } + + /// + /// Gets or sets a command to execute when the pointer/finger moves over the chart. + /// + public ICommand? MovedCommand + { + get => (ICommand?)GetValue(MovedCommandProperty); + set => SetValue(MovedCommandProperty, value); } /// /// Gets or sets a command to execute when the pointer moves over the chart. /// + [Obsolete($"Use {nameof(MovedCommand)} instead.")] public ICommand? PointerMoveCommand { - get => (ICommand?)GetValue(PointerMoveCommandProperty); - set => SetValue(PointerMoveCommandProperty, value); + get => (ICommand?)GetValue(MovedCommandProperty); + set => SetValue(MovedCommandProperty, value); } /// @@ -724,6 +770,45 @@ private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEven _core?.Update(); } + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) + { + // not implemented yet? + // https://github.com/dotnet/maui/issues/16202 + //if (Keyboard.Modifiers > 0) return; + + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PressedCommand?.CanExecute(cArgs) == true) PressedCommand.Execute(cArgs); + + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); + } + + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) + { + var location = args.Location; + + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (MovedCommand?.CanExecute(cArgs) == true) MovedCommand.Execute(cArgs); + + _core?.InvokePointerMove(location); + } + + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) + { + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); + } + + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) + { + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnExited(object? sender, Behaviours.Events.EventArgs args) + { + _core?.InvokePointerLeft(); + } + private void OnSizeChanged(object? sender, EventArgs e) { if (_core is null) return; @@ -746,7 +831,7 @@ private void OnCoreUpdateStarted(IChartView chart) UpdateStarted?.Invoke(this); } - private void OnTooltipTimerEllapsed(object sender, ElapsedEventArgs e) + private void OnTooltipTimerEllapsed(object? sender, ElapsedEventArgs e) { if (_core is null) return; MainThread.BeginInvokeOnMainThread(() => From 451d8deaa8a07fd37fcac581b1c23eeedc668ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 10:03:23 -0600 Subject: [PATCH 18/78] update maui samples --- .../Events/AddPointOnClick/View.xaml | 2 +- .../MauiSample/General/Scrollable/View.xaml | 15 ++---- .../General/Scrollable/View.xaml.cs | 49 ------------------- .../CartesianChart.xaml.cs | 3 ++ 4 files changed, 9 insertions(+), 60 deletions(-) diff --git a/samples/MauiSample/Events/AddPointOnClick/View.xaml b/samples/MauiSample/Events/AddPointOnClick/View.xaml index 0ae8b05ea..20b82463b 100644 --- a/samples/MauiSample/Events/AddPointOnClick/View.xaml +++ b/samples/MauiSample/Events/AddPointOnClick/View.xaml @@ -11,7 +11,7 @@ diff --git a/samples/MauiSample/General/Scrollable/View.xaml b/samples/MauiSample/General/Scrollable/View.xaml index a9c0ce426..96644a7e4 100644 --- a/samples/MauiSample/General/Scrollable/View.xaml +++ b/samples/MauiSample/General/Scrollable/View.xaml @@ -27,7 +27,7 @@ XAxes="{Binding ScrollableAxes}" ZoomMode="X" DrawMargin="{Binding Margin}" - UpdateStarted="OnChart_Updated"> + UpdateStartedCommand="{Binding ChartUpdatedCommand}"> - - - - + PressedCommand="{Binding PointerDownCommand}" + MovedCommand="{Binding PointerMoveCommand}" + ReleasedCommand="{Binding PointerUpCommand}" + TooltipPosition="Hidden"> diff --git a/samples/MauiSample/General/Scrollable/View.xaml.cs b/samples/MauiSample/General/Scrollable/View.xaml.cs index 97f695540..ee321910b 100644 --- a/samples/MauiSample/General/Scrollable/View.xaml.cs +++ b/samples/MauiSample/General/Scrollable/View.xaml.cs @@ -8,57 +8,8 @@ namespace MauiSample.General.Scrollable; [XamlCompilation(XamlCompilationOptions.Compile)] public partial class View : ContentPage { - private bool _isDown = false; - public View() { InitializeComponent(); } - - private void OnChart_Updated(IChartView chart) - { - var vm = (ViewModel)BindingContext; - var cartesianChart = (CartesianChart)chart; - - var x = cartesianChart.XAxes.First(); - - // update the scroll bar thumb when the chart is updated (zoom/pan) - // this will let the user know the current visible range - var thumb = vm.Thumbs[0]; - - thumb.Xi = x.MinLimit; - thumb.Xj = x.MaxLimit; - } - - private void OnPointerEntered(object sender, PointerEventArgs e) - { - _isDown = true; - } - - private void OnPointerMoved(object sender, PointerEventArgs e) - { - if (!_isDown) return; - - var vm = (ViewModel)BindingContext; - var scrollBarChart = ScrollBarChart; - - var pointerPosition = e.GetPosition(scrollBarChart); - var positionInData = scrollBarChart.ScalePixelsToData(new(pointerPosition.Value.X, pointerPosition.Value.Y)); - - var thumb = vm.Thumbs[0]; - var currentRange = thumb.Xj - thumb.Xi; - - // update the scroll bar thumb when the user is dragging the chart - thumb.Xi = positionInData.X - currentRange / 2; - thumb.Xj = positionInData.X + currentRange / 2; - - // update the chart visible range - vm.ScrollableAxes[0].MinLimit = thumb.Xi; - vm.ScrollableAxes[0].MaxLimit = thumb.Xj; - } - - private void OnPointerExited(object sender, PointerEventArgs e) - { - _isDown = false; - } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs index 40cd6f922..831bb9684 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs @@ -834,6 +834,9 @@ private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) { + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (ReleasedCommand?.CanExecute(cArgs) == true) ReleasedCommand.Execute(cArgs); + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); } From db0b4b4a4abd5505f111199ab4f1eb8a0c437fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 10:19:45 -0600 Subject: [PATCH 19/78] remove old events from uno.winui --- .../CartesianChart.xaml.cs | 94 +------------- .../MotionCanvas.xaml.cs | 121 ------------------ .../PieChart.xaml.cs | 47 ------- .../PolarChart.xaml.cs | 61 --------- 4 files changed, 2 insertions(+), 321 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs index f6601147c..e60ac9cc6 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs @@ -771,16 +771,7 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.Measuring += OnCoreMeasuring; _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - - PointerPressed += OnPointerPressed; - PointerMoved += OnPointerMoved; - PointerReleased += OnPointerReleased; - PointerWheelChanged += OnWheelChanged; - PointerExited += OnPointerExited; - SizeChanged += OnSizeChanged; - - _motionCanvas.Pinched += OnCanvasPinched; } _core.Load(); @@ -797,6 +788,8 @@ private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEven _core?.Update(); } + + private void OnSizeChanged(object? sender, SizeChangedEventArgs e) { if (_core == null) throw new Exception("Core not found!"); @@ -824,89 +817,6 @@ private void OnCoreMeasuring(IChartView chart) Measuring?.Invoke(this); } - private void OnPointerPressed(object? sender, PointerRoutedEventArgs e) - { - if (e.KeyModifiers > 0) return; - _ = CapturePointer(e.Pointer); - var p = e.GetCurrentPoint(this); - - if (PointerPressedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); - } - - var isRight = false; - if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) - { - var properties = e.GetCurrentPoint(this).Properties; - isRight = properties.IsRightButtonPressed; - } - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); - } - - private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) - { - if (DateTime.Now < _panLocketUntil) return; - - var p = e.GetCurrentPoint(motionCanvas); - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - } - - private void OnPointerReleased(object? sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } - - var isRight = false; - if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) - { - var properties = e.GetCurrentPoint(this).Properties; - isRight = properties.IsRightButtonPressed; - } - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); - ReleasePointerCapture(e.Pointer); - } - - private void OnPointerExited(object? sender, PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - - private void OnWheelChanged(object? sender, PointerRoutedEventArgs e) - { - if (_core == null) throw new Exception("core not found"); - var c = (CartesianChart)_core; - var p = e.GetCurrentPoint(this); - - c.Zoom( - new LvcPoint( - (float)p.Position.X, (float)p.Position.Y), - p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); - } - - private void OnCanvasPinched(object? sender, LiveChartsPinchEventArgs eventArgs) - { - if (_core == null) throw new Exception("core not found"); - var c = (CartesianChart)_core; - - c.Zoom(eventArgs.PinchStart, ZoomDirection.DefinedByScaleFactor, eventArgs.Scale, true); - _panLocketUntil = DateTime.Now.AddMilliseconds(500); - //_lastScale = eventArgs.Scale; - } - private void OnUnloaded(object? sender, RoutedEventArgs e) { _core?.Unload(); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs index 23a695114..9cccaf01c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs @@ -34,10 +34,6 @@ using SkiaSharp.Views.Windows; using Windows.Graphics.Display; -#if __ANDROID__ -using Android.Views; -#endif - namespace LiveChartsCore.SkiaSharpView.WinUI; /// @@ -58,10 +54,6 @@ public MotionCanvas() var canvas = (SKXamlCanvas)FindName("canvas"); _skiaElement = canvas; _skiaElement.PaintSurface += OnPaintSurface; - -#if __ANDROID__ - _scaleDetector = new ScaleGestureDetector(Context, new AndroidScaleListener(this)); -#endif } #region properties @@ -167,117 +159,4 @@ private void OnUnloaded(object sender, RoutedEventArgs e) CanvasCore.Invalidated -= OnCanvasCoreInvalidated; CanvasCore.Dispose(); } - - #region ANDROID -#if __ANDROID__ - // based on: - //https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/touch/android-touch-walkthrough - - private readonly ScaleGestureDetector _scaleDetector; - - private int _activePointerId = -1; - private float _lastTouchX; - private float _lastTouchY; - private float _posX; - private float _posY; - - private class AndroidScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener - { - private readonly MotionCanvas _canvas; - - public AndroidScaleListener(MotionCanvas canvas) - { - _canvas = canvas; - } - - /// - /// Called on scale gesture. - /// - /// - /// - public override bool OnScale(ScaleGestureDetector? detector) - { - if (detector is null) return false; - - if (detector.ScaleFactor != 1.0f) - { - _canvas.InvokePinch( - new LiveChartsPinchEventArgs - { - PinchStart = new LvcPoint { X = _canvas._lastTouchX, Y = _canvas._lastTouchY }, - Scale = detector.ScaleFactor - }); - } - return true; - } - } - - public override bool OnTouchEvent(MotionEvent? ev) - { - if (ev is null) return false; - - _ = _scaleDetector.OnTouchEvent(ev); - - var action = ev.Action & MotionEventActions.Mask; - int pointerIndex; - - switch (action) - { - case MotionEventActions.Down: - _lastTouchX = ev.GetX(); - _lastTouchY = ev.GetY(); - _activePointerId = ev.GetPointerId(0); - break; - - case MotionEventActions.Move: - pointerIndex = ev.FindPointerIndex(_activePointerId); - var x = ev.GetX(pointerIndex); - var y = ev.GetY(pointerIndex); - if (!_scaleDetector.IsInProgress) - { - // Only move the ScaleGestureDetector isn't already processing a gesture. - var deltaX = x - _lastTouchX; - var deltaY = y - _lastTouchY; - _posX += deltaX; - _posY += deltaY; - } - - _lastTouchX = x; - _lastTouchY = y; - break; - - case MotionEventActions.Up: - case MotionEventActions.Cancel: - // We no longer need to keep track of the active pointer. - _activePointerId = -1; - break; - - case MotionEventActions.PointerUp: - // check to make sure that the pointer that went up is for the gesture we're tracking. - pointerIndex = (int)(ev.Action & MotionEventActions.PointerIndexMask) >> (int)MotionEventActions.PointerIndexShift; - var pointerId = ev.GetPointerId(pointerIndex); - if (pointerId == _activePointerId) - { - // This was our active pointer going up. Choose a new - // action pointer and adjust accordingly - var newPointerIndex = pointerIndex == 0 ? 1 : 0; - _lastTouchX = ev.GetX(newPointerIndex); - _lastTouchY = ev.GetY(newPointerIndex); - _activePointerId = ev.GetPointerId(newPointerIndex); - } - break; - - default: - break; - } - - return true; - } - - private void InvokePinch(LiveChartsPinchEventArgs args) - { - Pinched?.Invoke(this, args); - } -#endif - #endregion } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs index c9079aa73..d94233e48 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs @@ -642,12 +642,6 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.Measuring += OnCoreMeasuring; _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - - PointerPressed += OnPointerPressed; - PointerReleased += PieChart_PointerReleased; - SizeChanged += OnSizeChanged; - PointerMoved += OnPointerMoved; - PointerExited += OnPointerExited; } _core.Load(); @@ -660,42 +654,6 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e) _core.Update(); } - private void OnPointerPressed(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - - if (PointerPressedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); - } - - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); - } - - private void PieChart_PointerReleased(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } - } - - private void OnPointerMoved(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(motionCanvas); - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - } - private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); @@ -717,11 +675,6 @@ private void OnCoreMeasuring(IChartView chart) Measuring?.Invoke(this); } - private void OnPointerExited(object sender, PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - private void OnUnloaded(object sender, RoutedEventArgs e) { _core?.Unload(); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs index 10ec031ec..77a45cff8 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs @@ -713,12 +713,7 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - PointerWheelChanged += OnWheelChanged; - PointerPressed += OnPointerPressed; - PointerReleased += OnPointerReleased; SizeChanged += OnSizeChanged; - PointerMoved += OnPointerMoved; - PointerExited += OnPointerExited; } _core.Load(); @@ -741,19 +736,6 @@ private void OnSizeChanged(object? sender, SizeChangedEventArgs e) _core.Update(); } - private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(motionCanvas); - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); - } - private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); @@ -775,49 +757,6 @@ private void OnCoreMeasuring(IChartView chart) Measuring?.Invoke(this); } - private void OnPointerExited(object sender, PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - - private void OnPointerReleased(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } - - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); - } - - private void OnPointerPressed(object sender, PointerRoutedEventArgs e) - { - var p = e.GetCurrentPoint(this); - - if (PointerPressedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); - } - - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); - } - - private void OnWheelChanged(object sender, PointerRoutedEventArgs e) - { - //if (_core == null) throw new Exception("core not found"); - //var c = (PolarChart)_core; - //var p = e.GetCurrentPoint(this); - - //c.Zoom( - // new System.Drawing.PointF( - // (float)p.Position.X, (float)p.Position.Y), - // p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); - } - private void OnUnloaded(object sender, RoutedEventArgs e) { _core?.Unload(); From d9e3b6b1ef468fccb82e6cacfe546b7810681dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 10:24:20 -0600 Subject: [PATCH 20/78] move uno proj --- .../AssemblyInfo.cs | 0 .../CartesianChart.xaml | 0 .../CartesianChart.xaml.cs | 0 .../ChartBehaviour.cs | 0 .../GeoMap.xaml | 0 .../GeoMap.xaml.cs | 0 .../Helpers/LiveChartsPinchEventArgs.cs | 0 .../Helpers/UnoPlatformHelpers.cs | 0 .../LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj | 0 .../MotionCanvas.xaml | 0 .../MotionCanvas.xaml.cs | 0 .../PieChart.xaml | 0 .../PieChart.xaml.cs | 0 .../PolarChart.xaml | 0 .../PolarChart.xaml.cs | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/AssemblyInfo.cs (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/CartesianChart.xaml (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/CartesianChart.xaml.cs (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/ChartBehaviour.cs (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/GeoMap.xaml (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/GeoMap.xaml.cs (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/Helpers/LiveChartsPinchEventArgs.cs (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/Helpers/UnoPlatformHelpers.cs (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/MotionCanvas.xaml (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/MotionCanvas.xaml.cs (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/PieChart.xaml (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/PieChart.xaml.cs (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/PolarChart.xaml (100%) rename src/skiasharp/{LiveChartsCore.SkiaSharpView.UnoWinUI => LiveChartsCore.SkiaSharpView.Uno.WinUI}/PolarChart.xaml.cs (100%) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/AssemblyInfo.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/AssemblyInfo.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/AssemblyInfo.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/AssemblyInfo.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/CartesianChart.xaml.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/ChartBehaviour.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/ChartBehaviour.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/ChartBehaviour.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/GeoMap.xaml.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.xaml.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/LiveChartsPinchEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/LiveChartsPinchEventArgs.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/UnoPlatformHelpers.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/Helpers/UnoPlatformHelpers.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/MotionCanvas.xaml.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PieChart.xaml.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs similarity index 100% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.UnoWinUI/PolarChart.xaml.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs From a9e27dab259cec3ce7e8bfe84c58102c632f9725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 10:24:31 -0600 Subject: [PATCH 21/78] move uno proj --- LiveCharts.sln | 114 +++++++++--------- .../Helpers/LiveChartsPinchEventArgs.cs | 32 ----- 2 files changed, 57 insertions(+), 89 deletions(-) delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs diff --git a/LiveCharts.sln b/LiveCharts.sln index 4fa7666b9..19314314d 100644 --- a/LiveCharts.sln +++ b/LiveCharts.sln @@ -108,7 +108,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoPlatformSample.DataContr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.Behaviours", "src\LiveChartsCore.Behaviours\LiveChartsCore.Behaviours.csproj", "{F7B300BA-687D-4420-B658-0D1FA7F981EB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "src\skiasharp\LiveChartsCore.SkiaSharpView.UnoWinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "src\skiasharp\LiveChartsCore.SkiaSharpView.Uno.WinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{407D2FDF-11A1-44B7-91AE-D48D37C0A65E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -2292,62 +2292,62 @@ Global {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|x64.Build.0 = Release|Any CPU {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|x86.ActiveCfg = Release|Any CPU {F7B300BA-687D-4420-B658-0D1FA7F981EB}.Release|x86.Build.0 = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|ARM.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|ARM64.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|ARM64.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|iPhone.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|x64.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|x64.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|x86.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.AppStore|x86.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|ARM.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|ARM.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|ARM64.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|iPhone.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|x64.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|x64.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|x86.ActiveCfg = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Debug|x86.Build.0 = Debug|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|Any CPU.Build.0 = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|ARM.ActiveCfg = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|ARM.Build.0 = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|ARM64.ActiveCfg = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|ARM64.Build.0 = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|iPhone.ActiveCfg = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|iPhone.Build.0 = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|x64.ActiveCfg = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|x64.Build.0 = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|x86.ActiveCfg = Release|Any CPU - {EE6F9A28-B6E5-4FBD-B5F5-1631A5F0B893}.Release|x86.Build.0 = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|ARM.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|ARM64.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|iPhone.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|x64.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|x64.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|x86.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.AppStore|x86.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|ARM.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|ARM64.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|iPhone.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|x64.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|x64.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|x86.ActiveCfg = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Debug|x86.Build.0 = Debug|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|Any CPU.Build.0 = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|ARM.ActiveCfg = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|ARM.Build.0 = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|ARM64.ActiveCfg = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|ARM64.Build.0 = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|iPhone.ActiveCfg = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|iPhone.Build.0 = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|x64.ActiveCfg = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|x64.Build.0 = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|x86.ActiveCfg = Release|Any CPU + {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs deleted file mode 100644 index 223a2b6ac..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/LiveChartsPinchEventArgs.cs +++ /dev/null @@ -1,32 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using LiveChartsCore.Drawing; - -namespace LiveChartsCore.SkiaSharpView.WinUI.Helpers; - -public class LiveChartsPinchEventArgs -{ - public float Scale { get; set; } - - public LvcPoint PinchStart { get; set; } -} From 11a54e5b3a6fd3be8f4410d2bc79a8ade4bc111e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 10:26:47 -0600 Subject: [PATCH 22/78] move uno --- .../UnoPlatformSample/UnoPlatformSample.sln | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/samples/UnoPlatformSample/UnoPlatformSample.sln b/samples/UnoPlatformSample/UnoPlatformSample.sln index e4d7a0e53..fcff39c33 100644 --- a/samples/UnoPlatformSample/UnoPlatformSample.sln +++ b/samples/UnoPlatformSample/UnoPlatformSample.sln @@ -35,10 +35,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore", "..\..\src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView", "..\..\src\skiasharp\LiveChartsCore.SkiaSharp\LiveChartsCore.SkiaSharpView.csproj", "{C3C321D8-3CA3-4714-AFF3-B71A3B819E08}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "..\..\src\skiasharp\LiveChartsCore.SkiaSharpView.UnoWinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewModelsSamples", "..\ViewModelsSamples\ViewModelsSamples.csproj", "{EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "..\..\src\skiasharp\LiveChartsCore.SkiaSharpView.Uno.WinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -243,22 +243,6 @@ Global {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|x64.Build.0 = Release|Any CPU {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|x86.ActiveCfg = Release|Any CPU {C3C321D8-3CA3-4714-AFF3-B71A3B819E08}.Release|x86.Build.0 = Release|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|arm64.ActiveCfg = Debug|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|arm64.Build.0 = Debug|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|x64.ActiveCfg = Debug|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|x64.Build.0 = Debug|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|x86.ActiveCfg = Debug|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Debug|x86.Build.0 = Debug|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|Any CPU.Build.0 = Release|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|arm64.ActiveCfg = Release|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|arm64.Build.0 = Release|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|x64.ActiveCfg = Release|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|x64.Build.0 = Release|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|x86.ActiveCfg = Release|Any CPU - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2}.Release|x86.Build.0 = Release|Any CPU {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Debug|arm64.ActiveCfg = Debug|Any CPU @@ -275,6 +259,22 @@ Global {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|x64.Build.0 = Release|Any CPU {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|x86.ActiveCfg = Release|Any CPU {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669}.Release|x86.Build.0 = Release|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Debug|arm64.ActiveCfg = Debug|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Debug|arm64.Build.0 = Debug|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Debug|x64.ActiveCfg = Debug|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Debug|x64.Build.0 = Debug|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Debug|x86.ActiveCfg = Debug|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Debug|x86.Build.0 = Debug|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|Any CPU.Build.0 = Release|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|arm64.ActiveCfg = Release|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|arm64.Build.0 = Release|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|x64.ActiveCfg = Release|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|x64.Build.0 = Release|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|x86.ActiveCfg = Release|Any CPU + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -293,8 +293,8 @@ Global {0DDD817E-0368-4477-AEA0-7760F8B22C70} = {F075631F-6FB6-476C-8007-491F72A70B15} {BB328359-ECAC-4B7F-A2FE-972CC2C4944F} = {98754DD8-C793-49EF-A506-F120FEBA666A} {C3C321D8-3CA3-4714-AFF3-B71A3B819E08} = {98754DD8-C793-49EF-A506-F120FEBA666A} - {5BAB4FCE-2CD8-4733-9F7D-1B31BEA6DCF2} = {98754DD8-C793-49EF-A506-F120FEBA666A} {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669} = {B9B91410-6F69-4DB0-A917-646B729F2467} + {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A} = {98754DD8-C793-49EF-A506-F120FEBA666A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4C6F8CF1-CF97-4BED-9F5B-F97F15C166EC} From 286e3407e31c829045ff2d24a784e848a61dd879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 11:36:01 -0600 Subject: [PATCH 23/78] ref new uno proj --- .../UnoPlatformSample/UnoPlatformSample.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj b/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj index 37b2015a7..03de68bc9 100644 --- a/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj +++ b/samples/UnoPlatformSample/UnoPlatformSample/UnoPlatformSample.csproj @@ -62,7 +62,7 @@ - + From 3f783d049fc69864b00a5b026b120ab98b10690c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 12:10:07 -0600 Subject: [PATCH 24/78] remove olg seturres in uno --- .../CartesianChart.xaml.cs | 1 + .../Helpers/UnoPlatformHelpers.cs | 7 ------- .../MotionCanvas.xaml.cs | 5 ----- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs index e60ac9cc6..87e840b18 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs @@ -1,4 +1,5 @@  + // The MIT License(MIT) // // Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs index 233535643..127bc14cb 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/Helpers/UnoPlatformHelpers.cs @@ -53,10 +53,3 @@ public static void InvokeOnUIThread(Action action, DispatcherQueue dispatcherQue DispatcherQueuePriority.Normal, () => action()); } } - -/// -/// Defines a custom pinch event handler. -/// -/// -/// -public delegate void PinchHandler(object sender, LiveChartsPinchEventArgs eventArgs); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs index 9cccaf01c..7b2b27344 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs @@ -96,11 +96,6 @@ public List> PaintTasks #endregion - /// - /// Called when the canvas detects a pinch gesture. - /// - public event PinchHandler? Pinched; - private void OnLoaded(object sender, RoutedEventArgs e) { CanvasCore.Invalidated += OnCanvasCoreInvalidated; From 154cf3beaefbe8bbb5ed7f5cd304a1f0e927a3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 13:13:11 -0600 Subject: [PATCH 25/78] add chartbehavour to unowinui controls --- .../UnoPlatformSample/UnoPlatformSample.sln | 19 +++++++ .../CartesianChart.xaml.cs | 57 +++++++++++++++++-- .../ChartBehaviour.cs | 33 ++++++----- .../MotionCanvas.xaml.cs | 1 - .../PieChart.xaml.cs | 54 +++++++++++++++++- .../PolarChart.xaml.cs | 52 ++++++++++++++++- 6 files changed, 191 insertions(+), 25 deletions(-) diff --git a/samples/UnoPlatformSample/UnoPlatformSample.sln b/samples/UnoPlatformSample/UnoPlatformSample.sln index fcff39c33..f8baa416b 100644 --- a/samples/UnoPlatformSample/UnoPlatformSample.sln +++ b/samples/UnoPlatformSample/UnoPlatformSample.sln @@ -39,6 +39,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewModelsSamples", "..\Vie EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "..\..\src\skiasharp\LiveChartsCore.SkiaSharpView.Uno.WinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.Behaviours", "..\..\src\LiveChartsCore.Behaviours\LiveChartsCore.Behaviours.csproj", "{55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -275,6 +277,22 @@ Global {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|x64.Build.0 = Release|Any CPU {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|x86.ActiveCfg = Release|Any CPU {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A}.Release|x86.Build.0 = Release|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Debug|arm64.ActiveCfg = Debug|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Debug|arm64.Build.0 = Debug|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Debug|x64.ActiveCfg = Debug|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Debug|x64.Build.0 = Debug|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Debug|x86.ActiveCfg = Debug|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Debug|x86.Build.0 = Debug|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Release|Any CPU.Build.0 = Release|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Release|arm64.ActiveCfg = Release|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Release|arm64.Build.0 = Release|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Release|x64.ActiveCfg = Release|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Release|x64.Build.0 = Release|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Release|x86.ActiveCfg = Release|Any CPU + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -295,6 +313,7 @@ Global {C3C321D8-3CA3-4714-AFF3-B71A3B819E08} = {98754DD8-C793-49EF-A506-F120FEBA666A} {EE2EB14F-01BB-4A01-89F4-0CF88CBD0669} = {B9B91410-6F69-4DB0-A917-646B729F2467} {2D5903B0-DBD3-4F49-A94C-AF44D2193C8A} = {98754DD8-C793-49EF-A506-F120FEBA666A} + {55278FF8-FED3-4A60-8AC2-0AB5BA6F84B9} = {98754DD8-C793-49EF-A506-F120FEBA666A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4C6F8CF1-CF97-4BED-9F5B-F97F15C166EC} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs index 87e840b18..4ba84322c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs @@ -37,11 +37,9 @@ using LiveChartsCore.SkiaSharpView.Drawing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Media; using LiveChartsCore.SkiaSharpView.WinUI.Helpers; using LiveChartsCore.SkiaSharpView.Painting; -using Microsoft.UI.Input; using LiveChartsCore.VisualElements; using System.Linq; using LiveChartsCore.SkiaSharpView.SKCharts; @@ -62,7 +60,6 @@ public sealed partial class CartesianChart : UserControl, ICartesianChartView _yObserver; private readonly CollectionDeepObserver> _sectionsObserver; private readonly CollectionDeepObserver> _visualsObserver; - private DateTime _panLocketUntil; #endregion @@ -772,7 +769,18 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.Measuring += OnCoreMeasuring; _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; + SizeChanged += OnSizeChanged; + + var chartBehaviour = new ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } _core.Load(); @@ -789,14 +797,53 @@ private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEven _core?.Update(); } - - private void OnSizeChanged(object? sender, SizeChangedEventArgs e) { if (_core == null) throw new Exception("Core not found!"); _core.Update(); } + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) + { + // is this working on all platforms? + //if (args.KeyModifiers > 0) return; + + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerPressedCommand?.CanExecute(cArgs) == true) PointerPressedCommand.Execute(cArgs); + + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); + } + + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) + { + var location = args.Location; + + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (PointerMoveCommand?.CanExecute(cArgs) == true) PointerMoveCommand.Execute(cArgs); + + _core?.InvokePointerMove(location); + } + + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) + { + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerReleasedCommand?.CanExecute(cArgs) == true) PointerReleasedCommand.Execute(cArgs); + + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); + } + + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) + { + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnExited(object? sender, Behaviours.Events.EventArgs args) + { + _core?.InvokePointerLeft(); + } + private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/ChartBehaviour.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/ChartBehaviour.cs index 6fac8ebf8..a2807a3fb 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/ChartBehaviour.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/ChartBehaviour.cs @@ -35,38 +35,37 @@ public class ChartBehaviour : Behaviours.ChartBehaviour /// The element. public void On(FrameworkElement element) { +#if HAS_UNO_WINUI Density = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi / 96.0f; - - element.Loaded += (sender, e) => - { +#else + Density = element.XamlRoot.RasterizationScale; +#endif #if ANDROID - element.Touch += OnAndroidTouched; - element.Hover += OnAndroidHover; + element.Touch += OnAndroidTouched; + element.Hover += OnAndroidHover; #endif #if MACCATALYST || IOS - element.UserInteractionEnabled = true; - element.AddGestureRecognizer(GetMacCatalystHover(element)); - element.AddGestureRecognizer(GetMacCatalystLongPress(element)); - element.AddGestureRecognizer(GetMacCatalystPinch(element)); - element.AddGestureRecognizer(GetMacCatalystOnPan(element)); + element.UserInteractionEnabled = true; + element.AddGestureRecognizer(GetMacCatalystHover(element)); + element.AddGestureRecognizer(GetMacCatalystLongPress(element)); + element.AddGestureRecognizer(GetMacCatalystPinch(element)); + element.AddGestureRecognizer(GetMacCatalystOnPan(element)); #endif #if WINDOWS - element.PointerPressed += OnWindowsPointerPressed; - element.PointerMoved += OnWindowsPointerMoved; - element.PointerReleased += OnWindowsPointerReleased; - element.PointerWheelChanged += OnWindowsPointerWheelChanged; - element.PointerExited += OnWindowsPointerExited; + element.PointerPressed += OnWindowsPointerPressed; + element.PointerMoved += OnWindowsPointerMoved; + element.PointerReleased += OnWindowsPointerReleased; + element.PointerWheelChanged += OnWindowsPointerWheelChanged; + element.PointerExited += OnWindowsPointerExited; #endif - - }; } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs index 7b2b27344..3fb78ba53 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/MotionCanvas.xaml.cs @@ -30,7 +30,6 @@ using LiveChartsCore.SkiaSharpView.Drawing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using LiveChartsCore.SkiaSharpView.WinUI.Helpers; using SkiaSharp.Views.Windows; using Windows.Graphics.Display; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs index d94233e48..2590cac9e 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs @@ -40,7 +40,6 @@ using LiveChartsCore.VisualElements; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Media; namespace LiveChartsCore.SkiaSharpView.WinUI; @@ -642,6 +641,18 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.Measuring += OnCoreMeasuring; _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; + + SizeChanged += OnSizeChanged; + + var chartBehaviour = new ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } _core.Load(); @@ -654,6 +665,47 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e) _core.Update(); } + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) + { + // is this working on all platforms? + //if (args.KeyModifiers > 0) return; + + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerPressedCommand?.CanExecute(cArgs) == true) PointerPressedCommand.Execute(cArgs); + + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); + } + + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) + { + var location = args.Location; + + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (PointerMoveCommand?.CanExecute(cArgs) == true) PointerMoveCommand.Execute(cArgs); + + _core?.InvokePointerMove(location); + } + + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) + { + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerReleasedCommand?.CanExecute(cArgs) == true) PointerReleasedCommand.Execute(cArgs); + + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); + } + + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) + { + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnExited(object? sender, Behaviours.Events.EventArgs args) + { + _core?.InvokePointerLeft(); + } + private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs index 77a45cff8..e0ce5327f 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs @@ -39,7 +39,6 @@ using LiveChartsCore.VisualElements; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Media; // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 @@ -714,6 +713,16 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.UpdateFinished += OnCoreUpdateFinished; SizeChanged += OnSizeChanged; + + var chartBehaviour = new ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } _core.Load(); @@ -736,6 +745,47 @@ private void OnSizeChanged(object? sender, SizeChangedEventArgs e) _core.Update(); } + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) + { + // is this working on all platforms? + //if (args.KeyModifiers > 0) return; + + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerPressedCommand?.CanExecute(cArgs) == true) PointerPressedCommand.Execute(cArgs); + + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); + } + + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) + { + var location = args.Location; + + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (PointerMoveCommand?.CanExecute(cArgs) == true) PointerMoveCommand.Execute(cArgs); + + _core?.InvokePointerMove(location); + } + + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) + { + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerReleasedCommand?.CanExecute(cArgs) == true) PointerReleasedCommand.Execute(cArgs); + + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); + } + + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) + { + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnExited(object? sender, Behaviours.Events.EventArgs args) + { + _core?.InvokePointerLeft(); + } + private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); From 35b83c807cc375cd1d75ca243484aa96afd65bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 13:38:47 -0600 Subject: [PATCH 26/78] fix android nre --- .../ChartBehaviour.Android.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs index 8b02207c6..d784f9d1f 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs @@ -34,7 +34,8 @@ public abstract partial class ChartBehaviour { private bool _isPinching; private bool _isDown; - private readonly ScaleGestureDetector _scaleDetector = null!; + private LvcPoint _lastTouch; + private ScaleGestureDetector _scaleDetector = null!; protected void OnAndroidHover(object? sender, View.HoverEventArgs e) { @@ -52,6 +53,12 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) var isRightClick = false; // can we detect this? var isPinch = e.Event.PointerCount > 1; + _scaleDetector ??= new ScaleGestureDetector( + ((View)sender!).Context!, new CustomScaleListener(scale => + { + Pinched?.Invoke(sender, new(scale, _lastTouch, _scaleDetector!)); + })); + _ = _scaleDetector.OnTouchEvent(e.Event); switch (e.Event.ActionMasked) @@ -94,6 +101,8 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) default: break; } + + _lastTouch = p; } private class CustomScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener From c7d86483d2317f2f25551c579c29e7f49f3d69c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 13:49:13 -0600 Subject: [PATCH 27/78] subscribe to pinched chart behaviour --- .../CartesianChart.xaml.cs | 12 ++++++++++++ .../CartesianChart.xaml.cs | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs index 831bb9684..2c63a7b47 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs @@ -116,6 +116,7 @@ public CartesianChart() chartBehaviour.Moved += OnMoved; chartBehaviour.Released += OnReleased; chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Pinched += OnPinched; chartBehaviour.Exited += OnExited; chartBehaviour.On(this); @@ -847,6 +848,17 @@ private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); } + private void OnPinched(object? sender, Behaviours.Events.PinchEventArgs args) + { + if (_core is null) return; + + var c = (CartesianChart)_core; + var p = args.PinchStart; + var s = c.ControlSize; + var pivot = new LvcPoint((float)(p.X * s.Width), (float)(p.Y * s.Height)); + c.Zoom(pivot, ZoomDirection.DefinedByScaleFactor, args.Scale, true); + } + private void OnExited(object? sender, Behaviours.Events.EventArgs args) { _core?.InvokePointerLeft(); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs index 4ba84322c..e2cbf3060 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs @@ -778,6 +778,7 @@ private void OnLoaded(object sender, RoutedEventArgs e) chartBehaviour.Moved += OnMoved; chartBehaviour.Released += OnReleased; chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Pinched += OnPinched; chartBehaviour.Exited += OnExited; chartBehaviour.On(this); @@ -839,6 +840,17 @@ private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); } + private void OnPinched(object? sender, Behaviours.Events.PinchEventArgs args) + { + if (_core is null) return; + + var c = (CartesianChart)_core; + var p = args.PinchStart; + var s = c.ControlSize; + var pivot = new LvcPoint((float)(p.X * s.Width), (float)(p.Y * s.Height)); + c.Zoom(pivot, ZoomDirection.DefinedByScaleFactor, args.Scale, true); + } + private void OnExited(object? sender, Behaviours.Events.EventArgs args) { _core?.InvokePointerLeft(); From ad821601bd9aecdd731bd7d862c07495746ce170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 18:18:41 -0600 Subject: [PATCH 28/78] nullables --- src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs index d784f9d1f..cf70f65be 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs @@ -35,7 +35,7 @@ public abstract partial class ChartBehaviour private bool _isPinching; private bool _isDown; private LvcPoint _lastTouch; - private ScaleGestureDetector _scaleDetector = null!; + private ScaleGestureDetector? _scaleDetector; protected void OnAndroidHover(object? sender, View.HoverEventArgs e) { From 72d40adcd28785b74cbcdc32c894708ab1f2cca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 18:34:13 -0600 Subject: [PATCH 29/78] add behaviiours to uno (uwp) --- .../Behaviours/ChartBehaviour.Android.cs | 126 +++++++++++++++ .../Behaviours/ChartBehaviour.MacCatalyst.cs | 146 ++++++++++++++++++ .../Behaviours/ChartBehaviour.Windows.cs | 77 +++++++++ .../Behaviours/ChartBehaviour._shared.cs | 115 ++++++++++++++ .../Behaviours/Events/EventArgs.cs | 43 ++++++ .../Events/Handler.cs} | 16 +- .../Behaviours/Events/PinchEventArgs.cs | 54 +++++++ .../Behaviours/Events/PinchHandler.cs | 30 ++++ .../Behaviours/Events/PressedEventArgs.cs | 48 ++++++ .../Behaviours/Events/PressedHandler.cs | 30 ++++ .../Behaviours/Events/ScreenEventArgs.cs | 47 ++++++ .../Behaviours/Events/ScreenHandler.cs | 30 ++++ .../Behaviours/Events/ScrollEventArgs.cs | 48 ++++++ .../Behaviours/Events/ScrollHandler.cs | 30 ++++ .../CartesianChart.xaml.cs | 146 +++++++----------- .../Helpers/UnoPlatformHelpers.cs | 22 --- .../MotionCanvas.xaml.cs | 127 --------------- .../PieChart.xaml.cs | 90 ++++++----- .../PolarChart.xaml.cs | 111 ++++++------- 19 files changed, 993 insertions(+), 343 deletions(-) create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.MacCatalyst.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Windows.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour._shared.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/EventArgs.cs rename src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/{Helpers/LiveChartsPinchEventArgs.cs => Behaviours/Events/Handler.cs} (81%) create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PinchEventArgs.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PinchHandler.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PressedEventArgs.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PressedHandler.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScreenEventArgs.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScreenHandler.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScrollEventArgs.cs create mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScrollHandler.cs diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs new file mode 100644 index 000000000..005361a98 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs @@ -0,0 +1,126 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if ANDROID + +using Android.Views; +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours; + +/// +/// A class that adds platform-specific events to the chart. +/// +public partial class ChartBehaviour +{ + private bool _isPinching; + private bool _isDown; + private LvcPoint _lastTouch; + private ScaleGestureDetector? _scaleDetector; + + protected void OnAndroidHover(object? sender, View.HoverEventArgs e) + { + if (e.Event is null) return; + + var p = new LvcPoint(e.Event.GetX() / Density, e.Event.GetY() / Density); + Moved!.Invoke(sender, new(p, e.Event)); + } + + protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) + { + if (e.Event is null) return; + + var p = new LvcPoint(e.Event.GetX() / Density, e.Event.GetY() / Density); + var isRightClick = false; // can we detect this? + var isPinch = e.Event.PointerCount > 1; + + _scaleDetector ??= new ScaleGestureDetector( + ((View)sender!).Context!, new CustomScaleListener(scale => + { + Pinched?.Invoke(sender, new(scale, _lastTouch, _scaleDetector!)); + })); + + _ = _scaleDetector.OnTouchEvent(e.Event); + + switch (e.Event.ActionMasked) + { + case MotionEventActions.ButtonPress: + case MotionEventActions.Pointer1Down: + case MotionEventActions.Pointer2Down: + case MotionEventActions.Pointer3Down: + case MotionEventActions.Down: + _isPinching = isPinch; + _isDown = true; + if (!_isPinching) + Pressed?.Invoke(sender, new(p, isRightClick, e.Event)); + break; + case MotionEventActions.Move: + case MotionEventActions.HoverMove: + // the Moved event is only raised when the pointer is down, + // it is also fired from the hover handler when the pointer is not down. + if (!_isPinching && _isDown) + Moved?.Invoke(sender, new(p, e.Event)); + break; + case MotionEventActions.ButtonRelease: + case MotionEventActions.Pointer1Up: + case MotionEventActions.Pointer2Up: + case MotionEventActions.Pointer3Up: + case MotionEventActions.Up: + case MotionEventActions.Cancel: + if (!_isPinching && _isDown) + Released?.Invoke(sender, new(p, isRightClick, e.Event)); + else + _isPinching = false; + _isDown = false; + break; + case MotionEventActions.HoverEnter: + case MotionEventActions.HoverExit: + case MotionEventActions.Mask: + case MotionEventActions.Outside: + case MotionEventActions.PointerIdMask: + case MotionEventActions.PointerIdShift: + default: + break; + } + + _lastTouch = p; + } + + private class CustomScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener + { + private readonly Action _onScaled; + + public CustomScaleListener(Action onSacaled) + { + _onScaled = onSacaled; + } + + public override bool OnScale(ScaleGestureDetector? detector) + { + if (detector is null || detector.ScaleFactor == 1) return false; + _onScaled(detector.ScaleFactor); + return true; + } + } +} + +#endif diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.MacCatalyst.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.MacCatalyst.cs new file mode 100644 index 000000000..f6a51e644 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.MacCatalyst.cs @@ -0,0 +1,146 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if MACCATALYST || IOS + +using System; +using LiveChartsCore.Drawing; +using UIKit; + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours; + +/// +/// A class that adds platform-specific events to the chart. +/// +public partial class ChartBehaviour +{ + protected UIHoverGestureRecognizer GetMacCatalystHover(UIView view) + { + return new UIHoverGestureRecognizer((UIHoverGestureRecognizer e) => + { + switch (e.State) + { + case UIGestureRecognizerState.Changed: + var p = e.LocationInView(view); + Moved!.Invoke(view, new(new(p.X, p.Y), e)); + break; + case UIGestureRecognizerState.Cancelled: + case UIGestureRecognizerState.Failed: + case UIGestureRecognizerState.Ended: + Exited?.Invoke(view, new(e)); + break; + case UIGestureRecognizerState.Possible: + case UIGestureRecognizerState.Began: + default: + break; + } + }); + } + + protected UILongPressGestureRecognizer GetMacCatalystLongPress(UIView view) + { + return new UILongPressGestureRecognizer((UILongPressGestureRecognizer e) => + { + var location = e.LocationInView(view); + var p = new LvcPoint((float)location.X, (float)location.Y); + var isRightClick = false; // can we detect this? + var isPinch = e.NumberOfTouches > 1; + + switch (e.State) + { + case UIGestureRecognizerState.Began: + Pressed?.Invoke(view, new(p, isRightClick, e)); + break; + case UIGestureRecognizerState.Changed: + Moved?.Invoke(view, new(p, e)); + break; + case UIGestureRecognizerState.Cancelled: + case UIGestureRecognizerState.Ended: + Released?.Invoke(view, new(p, isRightClick, e)); + break; + case UIGestureRecognizerState.Possible: + case UIGestureRecognizerState.Failed: + default: + break; + } + }) + { + MinimumPressDuration = 0, + ShouldRecognizeSimultaneously = (g1, g2) => true + }; + } + + private float _previousScale = 1; + protected UIPinchGestureRecognizer GetMacCatalystPinch(UIView view) + { + return new UIPinchGestureRecognizer((UIPinchGestureRecognizer e) => + { + var p = e.LocationInView(view); + + switch (e.State) + { + case UIGestureRecognizerState.Began: + _previousScale = 1; + break; + case UIGestureRecognizerState.Changed: + var s = (float)e.Scale; + var delta = _previousScale - s; + Pinched?.Invoke(view, new(1 - delta, new(p.X, p.Y), e)); + _previousScale = s; + break; + case UIGestureRecognizerState.Ended: + case UIGestureRecognizerState.Cancelled: + break; + case UIGestureRecognizerState.Possible: + case UIGestureRecognizerState.Failed: + default: + break; + } + }) + { + ShouldRecognizeSimultaneously = (g1, g2) => true + }; + } + + private CGPoint? _last; + protected UIPanGestureRecognizer GetMacCatalystOnPan(UIView view) + { + return new UIPanGestureRecognizer((UIPanGestureRecognizer e) => + { + var l = e.LocationInView(view); + _last ??= l; + var delta = _last.Value.Y - l.Y; + var isZoom = e.NumberOfTouches == 0; + var tolerance = 10; // just a fator to avoid multiple calls. + + if (e.State == UIGestureRecognizerState.Ended || !isZoom || Math.Abs(delta) < tolerance) return; + Scrolled?.Invoke(view, new(new(l.X, l.Y), delta, e)); + _last = l; + }) + { + AllowedScrollTypesMask = UIScrollTypeMask.Discrete | UIScrollTypeMask.Continuous, + MinimumNumberOfTouches = 0 + }; + } +} + +#endif diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Windows.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Windows.cs new file mode 100644 index 000000000..6cfcb3b68 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Windows.cs @@ -0,0 +1,77 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if UAP10_0_18362 + +using Windows.UI.Xaml; +using Windows.UI.Xaml.Input; + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours; + +/// +/// A class that adds platform-specific events to the chart. +/// +public partial class ChartBehaviour +{ + protected void OnWindowsPointerPressed(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(sender as UIElement); + if (p is null) return; + + Pressed!.Invoke( + sender, + new(new(p.Position.X, p.Position.Y), p.Properties.IsRightButtonPressed, e)); + } + + protected void OnWindowsPointerMoved(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(sender as UIElement); + if (p is null) return; + + Moved!.Invoke( + sender, + new(new(p.Position.X, p.Position.Y), e)); + } + + protected void OnWindowsPointerReleased(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(sender as UIElement); + if (p is null) return; + + Released!.Invoke( + sender, + new(new(p.Position.X, p.Position.Y), p.Properties.IsRightButtonPressed, e)); + } + + protected void OnWindowsPointerWheelChanged(object sender, PointerRoutedEventArgs e) + { + var p = e.GetCurrentPoint(sender as UIElement); + Scrolled!.Invoke(sender, new(new(p.Position.X, p.Position.Y), p.Properties.MouseWheelDelta, e)); + } + + protected void OnWindowsPointerExited(object sender, PointerRoutedEventArgs e) + { + Exited?.Invoke(sender, new(e)); + } +} + +#endif diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour._shared.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour._shared.cs new file mode 100644 index 000000000..21fdb27e8 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour._shared.cs @@ -0,0 +1,115 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; +using Windows.UI.Xaml; + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours; + +// ----- +// NOTE (HELP WANTED?) +// this code is repeated, ideally it should be shared between all the projects +// but I am not able to consume the LiveChartsCore.Behaviours project from here +// the thing is that the #IF WINDOWS is not working as expected, already ttried with +// uap10.0.19041 withhour success. +// ----- + +/// +/// A class that adds platform-specific events to the chart. +/// +public partial class ChartBehaviour +{ + /// + /// Gets or sets the screen density. + /// + public double Density { get; set; } + + /// + /// Called when the pointer/tap is pressed. + /// + public event PressedHandler? Pressed; + + /// + /// Called when the pointer/tap is released. + /// + public event PressedHandler? Released; + + /// + /// Called when the pointer/tap moves. + /// + public event ScreenHandler? Moved; + + /// + /// Called when the pointer exits the control. + /// + public event Handler? Exited; + + /// + /// Called when the control is pinched. + /// + public event PinchHandler? Pinched; + + /// + /// Called when the control is scrolled. + /// + public event ScrollHandler? Scrolled; + + /// + /// Attaches the native events on the specified element. + /// + /// The element. + public void On(FrameworkElement element) + { +#if HAS_UNO_WINUI + Density = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi / 96.0f; +#else + Density = element.XamlRoot.RasterizationScale; +#endif + +#if ANDROID + + element.Touch += OnAndroidTouched; + element.Hover += OnAndroidHover; + +#endif + +#if MACCATALYST || IOS + + element.UserInteractionEnabled = true; + element.AddGestureRecognizer(GetMacCatalystHover(element)); + element.AddGestureRecognizer(GetMacCatalystLongPress(element)); + element.AddGestureRecognizer(GetMacCatalystPinch(element)); + element.AddGestureRecognizer(GetMacCatalystOnPan(element)); + +#endif + +#if UAP10_0_18362 + + element.PointerPressed += OnWindowsPointerPressed; + element.PointerMoved += OnWindowsPointerMoved; + element.PointerReleased += OnWindowsPointerReleased; + element.PointerWheelChanged += OnWindowsPointerWheelChanged; + element.PointerExited += OnWindowsPointerExited; + +#endif + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/EventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/EventArgs.cs new file mode 100644 index 000000000..07c6f320b --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/EventArgs.cs @@ -0,0 +1,43 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the screen event args. +/// +public class EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The original event. + public EventArgs(object originalEvent) + { + OriginalEvent = originalEvent; + } + + /// + /// Gets the original event. + /// + public object OriginalEvent { get; } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Helpers/LiveChartsPinchEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/Handler.cs similarity index 81% rename from src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Helpers/LiveChartsPinchEventArgs.cs rename to src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/Handler.cs index db0c8a55d..e13012e70 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Helpers/LiveChartsPinchEventArgs.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/Handler.cs @@ -20,13 +20,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -using LiveChartsCore.Drawing; +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; -namespace LiveChartsCore.SkiaSharpView.Uno.Helpers; - -public class LiveChartsPinchEventArgs -{ - public float Scale { get; set; } - - public LvcPoint PinchStart { get; set; } -} +/// +/// Defines the pinch event handler. +/// +/// The sender. +/// The args. +public delegate void Handler(object? sender, EventArgs args); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PinchEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PinchEventArgs.cs new file mode 100644 index 000000000..155343d9c --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PinchEventArgs.cs @@ -0,0 +1,54 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the pinch event args. +/// +public class PinchEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The scale. + /// The start. + /// The original event. + public PinchEventArgs(float scale, LvcPoint pinchStart, object originalEvent) + : base(originalEvent) + { + Scale = scale; + PinchStart = pinchStart; + } + + /// + /// Gets the scale. + /// + public float Scale { get; } + + /// + /// Gets the pinch star location. + /// + public LvcPoint PinchStart { get; set; } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PinchHandler.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PinchHandler.cs new file mode 100644 index 000000000..b556a50d4 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PinchHandler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the pinch event handler. +/// +/// The sender. +/// The args. +public delegate void PinchHandler(object? sender, PinchEventArgs args); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PressedEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PressedEventArgs.cs new file mode 100644 index 000000000..a5bd9cb80 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PressedEventArgs.cs @@ -0,0 +1,48 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the pointer event args. +/// +public class PressedEventArgs : ScreenEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The pointer location. + /// Indicates whether the action is secondary. + /// The original event. + public PressedEventArgs(LvcPoint location, bool isSecondaryPress, object originalEvent) + : base(location, originalEvent) + { + IsSecondaryPress = isSecondaryPress; + } + + /// + /// Gets a value indicating whether the action is a secondary press. + /// + public bool IsSecondaryPress { get; } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PressedHandler.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PressedHandler.cs new file mode 100644 index 000000000..639b9653c --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/PressedHandler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the sreen event handler. +/// +/// The sender. +/// The args. +public delegate void PressedHandler(object? sender, PressedEventArgs args); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScreenEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScreenEventArgs.cs new file mode 100644 index 000000000..7fc312251 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScreenEventArgs.cs @@ -0,0 +1,47 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the screen event args. +/// +public class ScreenEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The pointer location. + /// The original event. + public ScreenEventArgs(LvcPoint location, object originalEvent) + : base(originalEvent) + { + Location = location; + } + + /// + /// Gets the pointer location. + /// + public LvcPoint Location { get; } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScreenHandler.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScreenHandler.cs new file mode 100644 index 000000000..3aedd72a5 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScreenHandler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the sreen event handler. +/// +/// The sender. +/// The args. +public delegate void ScreenHandler(object? sender, ScreenEventArgs args); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScrollEventArgs.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScrollEventArgs.cs new file mode 100644 index 000000000..91d741360 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScrollEventArgs.cs @@ -0,0 +1,48 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the scroll event args. +/// +public class ScrollEventArgs : ScreenEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The pointer location. + /// Indicates the scroll delta. + /// The original event. + public ScrollEventArgs(LvcPoint location, double scrollDelta, object originalEvent) + : base(location, originalEvent) + { + ScrollDelta = scrollDelta; + } + + /// + /// Gets the scroll delta. + /// + public double ScrollDelta { get; } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScrollHandler.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScrollHandler.cs new file mode 100644 index 000000000..2852f9967 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/Events/ScrollHandler.cs @@ -0,0 +1,30 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours.Events; + +/// +/// Defines the scrroll event handler. +/// +/// The sender. +/// The args. +public delegate void ScrollHandler(object? sender, ScrollEventArgs args); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/CartesianChart.xaml.cs index fbe44fe7e..22fdd82fa 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/CartesianChart.xaml.cs @@ -39,10 +39,8 @@ using LiveChartsCore.SkiaSharpView.SKCharts; using LiveChartsCore.SkiaSharpView.Uno.Helpers; using LiveChartsCore.VisualElements; -using Windows.Devices.Input; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 @@ -61,7 +59,6 @@ public sealed partial class CartesianChart : UserControl, ICartesianChartView _yObserver; private readonly CollectionDeepObserver> _sectionsObserver; private readonly CollectionDeepObserver> _visualsObserver; - private DateTime _panLocketUntil; #endregion @@ -767,15 +764,18 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - PointerPressed += OnPointerPressed; - PointerMoved += OnPointerMoved; - PointerReleased += OnPointerReleased; - PointerWheelChanged += OnWheelChanged; - PointerExited += OnPointerExited; - SizeChanged += OnSizeChanged; - _motionCanvas.Pinched += OnCanvasPinched; + var chartBehaviour = new Behaviours.ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Pinched += OnPinched; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } _core.Load(); @@ -798,117 +798,77 @@ private void OnSizeChanged(object? sender, SizeChangedEventArgs e) _core.Update(); } - private void OnCoreUpdateFinished(IChartView chart) + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) { - UpdateFinished?.Invoke(this); - } + // is this working on all platforms? + //if (args.KeyModifiers > 0) return; - private void OnCoreUpdateStarted(IChartView chart) - { - if (UpdateStartedCommand is not null) - { - var args = new ChartCommandArgs(this); - if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); - } - - UpdateStarted?.Invoke(this); - } + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerPressedCommand?.CanExecute(cArgs) == true) PointerPressedCommand.Execute(cArgs); - private void OnCoreMeasuring(IChartView chart) - { - Measuring?.Invoke(this); + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); } - private void OnPointerPressed(object? sender, PointerRoutedEventArgs e) + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) { - if (e.KeyModifiers > 0) return; + var location = args.Location; - _ = CapturePointer(e.Pointer); - var p = e.GetCurrentPoint(this); + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (PointerMoveCommand?.CanExecute(cArgs) == true) PointerMoveCommand.Execute(cArgs); - if (PointerPressedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); - } - - var isRight = false; - if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) - { - var properties = e.GetCurrentPoint(this).Properties; - isRight = properties.IsRightButtonPressed; - } - - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); + _core?.InvokePointerMove(location); } - private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) { - if (DateTime.Now < _panLocketUntil) return; - - var p = e.GetCurrentPoint(motionCanvas); - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } - - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerReleasedCommand?.CanExecute(cArgs) == true) PointerReleasedCommand.Execute(cArgs); - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); } - private void OnPointerReleased(object? sender, PointerRoutedEventArgs e) + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) { - var p = e.GetCurrentPoint(this); - - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } - var isRight = false; - if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) - { - var properties = e.GetCurrentPoint(this).Properties; - isRight = properties.IsRightButtonPressed; - } + private void OnPinched(object? sender, Behaviours.Events.PinchEventArgs args) + { + if (_core is null) return; - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); - ReleasePointerCapture(e.Pointer); + var c = (CartesianChart)_core; + var p = args.PinchStart; + var s = c.ControlSize; + var pivot = new LvcPoint((float)(p.X * s.Width), (float)(p.Y * s.Height)); + c.Zoom(pivot, ZoomDirection.DefinedByScaleFactor, args.Scale, true); } - private void OnPointerExited(object? sender, PointerRoutedEventArgs e) + private void OnExited(object? sender, Behaviours.Events.EventArgs args) { _core?.InvokePointerLeft(); } - private void OnWheelChanged(object? sender, PointerRoutedEventArgs e) + private void OnCoreUpdateFinished(IChartView chart) { - if (_core == null) throw new Exception("core not found"); - var c = (CartesianChart)_core; - var p = e.GetCurrentPoint(this); - - c.Zoom( - new LvcPoint( - (float)p.Position.X, (float)p.Position.Y), - p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + UpdateFinished?.Invoke(this); } - private void OnCanvasPinched(object? sender, LiveChartsPinchEventArgs eventArgs) + private void OnCoreUpdateStarted(IChartView chart) { - if (_core == null) throw new Exception("core not found"); - var c = (CartesianChart)_core; + if (UpdateStartedCommand is not null) + { + var args = new ChartCommandArgs(this); + if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); + } + + UpdateStarted?.Invoke(this); + } - c.Zoom(eventArgs.PinchStart, ZoomDirection.DefinedByScaleFactor, eventArgs.Scale, true); - _panLocketUntil = DateTime.Now.AddMilliseconds(500); - //_lastScale = eventArgs.Scale; + private void OnCoreMeasuring(IChartView chart) + { + Measuring?.Invoke(this); } private void OnUnloaded(object? sender, RoutedEventArgs e) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Helpers/UnoPlatformHelpers.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Helpers/UnoPlatformHelpers.cs index c8bef055a..6937a5b23 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Helpers/UnoPlatformHelpers.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Helpers/UnoPlatformHelpers.cs @@ -51,29 +51,7 @@ public static void InvokeOnUIThread(Action action) return; } - // we get about 20 fps when the chart is updated in short periods of time. - - // see general/multithreading2 sample - // this samples forces the data update to run in the UI thread always, and adds a new data point every 10ms. - - // UWP seems to struggle handling the updates. - // theorically the chart is redrawn at a rate of 20~ fps - // but that is not true, the UI thread seems to be locked. - - // NOTES: - // 1. UWP is the only platform that behaves like this. - // 2. Notice the WPF.Host sample behaves much better. - - // How can we help UWP to handle this? What am I missing? - _ = CoreApplication.MainView.CoreWindow.Dispatcher .RunAsync(CoreDispatcherPriority.High, () => action()); } } - -/// -/// Defines a custom pinch event handler. -/// -/// -/// -public delegate void PinchHandler(object sender, LiveChartsPinchEventArgs eventArgs); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/MotionCanvas.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/MotionCanvas.xaml.cs index 22c37e688..18965e7c2 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/MotionCanvas.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/MotionCanvas.xaml.cs @@ -32,11 +32,6 @@ using Windows.Graphics.Display; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using LiveChartsCore.SkiaSharpView.Uno.Helpers; - -#if __ANDROID__ -using Android.Views; -#endif namespace LiveChartsCore.SkiaSharpView.Uno; @@ -58,10 +53,6 @@ public MotionCanvas() var canvas = (SKXamlCanvas)FindName("canvas"); _skiaElement = canvas; _skiaElement.PaintSurface += OnPaintSurface; - -#if __ANDROID__ - _scaleDetector = new ScaleGestureDetector(Context, new AndroidScaleListener(this)); -#endif } #region properties @@ -104,11 +95,6 @@ public List> PaintTasks #endregion - /// - /// Called when the canvas detects a pinch gesture. - /// - public event PinchHandler? Pinched; - private void OnLoaded(object sender, RoutedEventArgs e) { CanvasCore.Invalidated += OnCanvasCoreInvalidated; @@ -161,117 +147,4 @@ private void OnUnloaded(object sender, RoutedEventArgs e) CanvasCore.Invalidated -= OnCanvasCoreInvalidated; CanvasCore.Dispose(); } - - #region ANDROID -#if __ANDROID__ - // based on: - //https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/touch/android-touch-walkthrough - - private readonly ScaleGestureDetector _scaleDetector; - - private int _activePointerId = -1; - private float _lastTouchX; - private float _lastTouchY; - private float _posX; - private float _posY; - - private class AndroidScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener - { - private readonly MotionCanvas _canvas; - - public AndroidScaleListener(MotionCanvas canvas) - { - _canvas = canvas; - } - - /// - /// Called on scale gesture. - /// - /// - /// - public override bool OnScale(ScaleGestureDetector? detector) - { - if (detector is null) return false; - - if (detector.ScaleFactor != 1.0f) - { - _canvas.InvokePinch( - new LiveChartsPinchEventArgs - { - PinchStart = new LvcPoint { X = _canvas._lastTouchX, Y = _canvas._lastTouchY }, - Scale = detector.ScaleFactor - }); - } - return true; - } - } - - public override bool OnTouchEvent(MotionEvent? ev) - { - if (ev is null) return false; - - _ = _scaleDetector.OnTouchEvent(ev); - - var action = ev.Action & MotionEventActions.Mask; - int pointerIndex; - - switch (action) - { - case MotionEventActions.Down: - _lastTouchX = ev.GetX(); - _lastTouchY = ev.GetY(); - _activePointerId = ev.GetPointerId(0); - break; - - case MotionEventActions.Move: - pointerIndex = ev.FindPointerIndex(_activePointerId); - var x = ev.GetX(pointerIndex); - var y = ev.GetY(pointerIndex); - if (!_scaleDetector.IsInProgress) - { - // Only move the ScaleGestureDetector isn't already processing a gesture. - var deltaX = x - _lastTouchX; - var deltaY = y - _lastTouchY; - _posX += deltaX; - _posY += deltaY; - } - - _lastTouchX = x; - _lastTouchY = y; - break; - - case MotionEventActions.Up: - case MotionEventActions.Cancel: - // We no longer need to keep track of the active pointer. - _activePointerId = -1; - break; - - case MotionEventActions.PointerUp: - // check to make sure that the pointer that went up is for the gesture we're tracking. - pointerIndex = (int)(ev.Action & MotionEventActions.PointerIndexMask) >> (int)MotionEventActions.PointerIndexShift; - var pointerId = ev.GetPointerId(pointerIndex); - if (pointerId == _activePointerId) - { - // This was our active pointer going up. Choose a new - // action pointer and adjust accordingly - var newPointerIndex = pointerIndex == 0 ? 1 : 0; - _lastTouchX = ev.GetX(newPointerIndex); - _lastTouchY = ev.GetY(newPointerIndex); - _activePointerId = ev.GetPointerId(newPointerIndex); - } - break; - - default: - break; - } - - return true; - } - - private void InvokePinch(LiveChartsPinchEventArgs args) - { - Pinched?.Invoke(this, args); - } -#endif - #endregion } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/PieChart.xaml.cs index 15c4fc7b3..897c43284 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/PieChart.xaml.cs @@ -39,7 +39,6 @@ using LiveChartsCore.VisualElements; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; namespace LiveChartsCore.SkiaSharpView.Uno; @@ -62,11 +61,11 @@ public PieChart() InitializeComponent(); _seriesObserver = new CollectionDeepObserver( - (object sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), - (object sender, PropertyChangedEventArgs e) => _core?.Update()); + (object? sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), + (object? sender, PropertyChangedEventArgs e) => _core?.Update()); _visualsObserver = new CollectionDeepObserver>( - (object sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), - (object sender, PropertyChangedEventArgs e) => _core?.Update()); + (object? sender, NotifyCollectionChangedEventArgs e) => _core?.Update(), + (object? sender, PropertyChangedEventArgs e) => _core?.Update()); SetValue(SeriesProperty, new ObservableCollection()); SetValue(VisualElementsProperty, new ObservableCollection>()); @@ -642,11 +641,18 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - PointerPressed += OnPointerPressed; - PointerReleased += PieChart_PointerReleased; SizeChanged += OnSizeChanged; - PointerMoved += OnPointerMoved; - PointerExited += OnPointerExited; + + var chartBehaviour = new Behaviours.ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Pinched += OnPinched; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } _core.Load(); @@ -659,41 +665,56 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e) _core.Update(); } - private void OnPointerPressed(object sender, PointerRoutedEventArgs e) + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) { - var p = e.GetCurrentPoint(this); + // is this working on all platforms? + //if (args.KeyModifiers > 0) return; - if (PointerPressedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); - } + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerPressedCommand?.CanExecute(cArgs) == true) PointerPressedCommand.Execute(cArgs); - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); } - private void PieChart_PointerReleased(object sender, PointerRoutedEventArgs e) + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) { - var p = e.GetCurrentPoint(this); + var location = args.Location; - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (PointerMoveCommand?.CanExecute(cArgs) == true) PointerMoveCommand.Execute(cArgs); + + _core?.InvokePointerMove(location); } - private void OnPointerMoved(object sender, PointerRoutedEventArgs e) + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) { - var p = e.GetCurrentPoint(motionCanvas); + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerReleasedCommand?.CanExecute(cArgs) == true) PointerReleasedCommand.Execute(cArgs); - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); + } + + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) + { + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + } + + private void OnPinched(object? sender, Behaviours.Events.PinchEventArgs args) + { + if (_core is null) return; + + var c = (CartesianChart)_core; + var p = args.PinchStart; + var s = c.ControlSize; + var pivot = new LvcPoint((float)(p.X * s.Width), (float)(p.Y * s.Height)); + c.Zoom(pivot, ZoomDirection.DefinedByScaleFactor, args.Scale, true); + } - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + private void OnExited(object? sender, Behaviours.Events.EventArgs args) + { + _core?.InvokePointerLeft(); } private void OnCoreUpdateFinished(IChartView chart) @@ -717,11 +738,6 @@ private void OnCoreMeasuring(IChartView chart) Measuring?.Invoke(this); } - private void OnPointerExited(object sender, PointerRoutedEventArgs e) - { - _core?.InvokePointerLeft(); - } - private void OnUnloaded(object sender, RoutedEventArgs e) { _core?.Unload(); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/PolarChart.xaml.cs index a3683dd50..668f7a3c2 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/PolarChart.xaml.cs @@ -39,7 +39,6 @@ using LiveChartsCore.VisualElements; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 @@ -707,109 +706,111 @@ private void OnLoaded(object sender, RoutedEventArgs e) _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - PointerWheelChanged += OnWheelChanged; - PointerPressed += OnPointerPressed; - PointerReleased += OnPointerReleased; SizeChanged += OnSizeChanged; - PointerMoved += OnPointerMoved; - PointerExited += OnPointerExited; + + var chartBehaviour = new Behaviours.ChartBehaviour(); + + chartBehaviour.Pressed += OnPressed; + chartBehaviour.Moved += OnMoved; + chartBehaviour.Released += OnReleased; + chartBehaviour.Scrolled += OnScrolled; + chartBehaviour.Pinched += OnPinched; + chartBehaviour.Exited += OnExited; + + chartBehaviour.On(this); } _core.Load(); _core.Update(); } - private void OnDeepCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void OnDeepCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { _core?.Update(); } - private void OnDeepCollectionPropertyChanged(object sender, PropertyChangedEventArgs e) + private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEventArgs e) { _core?.Update(); } - private void OnSizeChanged(object sender, SizeChangedEventArgs e) + private void OnSizeChanged(object? sender, SizeChangedEventArgs e) { if (_core == null) throw new Exception("Core not found!"); _core.Update(); } - private void OnPointerMoved(object sender, PointerRoutedEventArgs e) + private void OnPressed(object? sender, Behaviours.Events.PressedEventArgs args) { - var p = e.GetCurrentPoint(motionCanvas); + // is this working on all platforms? + //if (args.KeyModifiers > 0) return; - if (PointerMoveCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerMoveCommand.CanExecute(args)) PointerMoveCommand.Execute(args); - } + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerPressedCommand?.CanExecute(cArgs) == true) PointerPressedCommand.Execute(cArgs); - _core?.InvokePointerMove(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerDown(args.Location, args.IsSecondaryPress); } - private void OnCoreUpdateFinished(IChartView chart) + private void OnMoved(object? sender, Behaviours.Events.ScreenEventArgs args) { - UpdateFinished?.Invoke(this); - } + var location = args.Location; - private void OnCoreUpdateStarted(IChartView chart) - { - if (UpdateStartedCommand is not null) - { - var args = new ChartCommandArgs(this); - if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); - } + var cArgs = new PointerCommandArgs(this, new(location.X, location.Y), args.OriginalEvent); + if (PointerMoveCommand?.CanExecute(cArgs) == true) PointerMoveCommand.Execute(cArgs); - UpdateStarted?.Invoke(this); + _core?.InvokePointerMove(location); } - private void OnCoreMeasuring(IChartView chart) + private void OnReleased(object? sender, Behaviours.Events.PressedEventArgs args) { - Measuring?.Invoke(this); + var cArgs = new PointerCommandArgs(this, new(args.Location.X, args.Location.Y), args); + if (PointerReleasedCommand?.CanExecute(cArgs) == true) PointerReleasedCommand.Execute(cArgs); + + _core?.InvokePointerUp(args.Location, args.IsSecondaryPress); } - private void OnPointerExited(object sender, PointerRoutedEventArgs e) + private void OnScrolled(object? sender, Behaviours.Events.ScrollEventArgs args) { - _core?.InvokePointerLeft(); + if (_core is null) throw new Exception("core not found"); + var c = (CartesianChart)_core; + c.Zoom(args.Location, args.ScrollDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); } - private void OnPointerReleased(object sender, PointerRoutedEventArgs e) + private void OnPinched(object? sender, Behaviours.Events.PinchEventArgs args) { - var p = e.GetCurrentPoint(this); + if (_core is null) return; - if (PointerReleasedCommand is not null) - { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerReleasedCommand.CanExecute(args)) PointerReleasedCommand.Execute(args); - } + var c = (CartesianChart)_core; + var p = args.PinchStart; + var s = c.ControlSize; + var pivot = new LvcPoint((float)(p.X * s.Width), (float)(p.Y * s.Height)); + c.Zoom(pivot, ZoomDirection.DefinedByScaleFactor, args.Scale, true); + } - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); + private void OnExited(object? sender, Behaviours.Events.EventArgs args) + { + _core?.InvokePointerLeft(); } - private void OnPointerPressed(object sender, PointerRoutedEventArgs e) + private void OnCoreUpdateFinished(IChartView chart) { - var p = e.GetCurrentPoint(this); + UpdateFinished?.Invoke(this); + } - if (PointerPressedCommand is not null) + private void OnCoreUpdateStarted(IChartView chart) + { + if (UpdateStartedCommand is not null) { - var args = new PointerCommandArgs(this, new(p.Position.X, p.Position.Y), e); - if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); + var args = new ChartCommandArgs(this); + if (UpdateStartedCommand.CanExecute(args)) UpdateStartedCommand.Execute(args); } - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); + UpdateStarted?.Invoke(this); } - private void OnWheelChanged(object sender, PointerRoutedEventArgs e) + private void OnCoreMeasuring(IChartView chart) { - //if (_core == null) throw new Exception("core not found"); - //var c = (PolarChart)_core; - //var p = e.GetCurrentPoint(this); - - //c.Zoom( - // new System.Drawing.PointF( - // (float)p.Position.X, (float)p.Position.Y), - // p.Properties.MouseWheelDelta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); + Measuring?.Invoke(this); } private void OnUnloaded(object sender, RoutedEventArgs e) From c004cdcd739f93ca7809ac2ca418ac9bafdbf2b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 5 Sep 2023 18:43:18 -0600 Subject: [PATCH 30/78] update uno win nav --- .../UnoPlatformSample/Presentation/MainPage.xaml | 6 ++++-- .../Presentation/MainPage.xaml.cs | 16 ++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml index 13985d31e..47ba83084 100644 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml @@ -31,8 +31,10 @@ - - + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs index 201a9c9c2..5f17eb590 100644 --- a/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs +++ b/samples/UnoPlatformSample/UnoPlatformSample/Presentation/MainPage.xaml.cs @@ -19,14 +19,6 @@ public MainPage() public string[] Samples { get; set; } - private void Border_PointerPressed(object sender, PointerRoutedEventArgs e) - { - grid.ColumnDefinitions[0].Width = new GridLength(0); - - var ctx = (string)((FrameworkElement)sender).DataContext; - LoadSample(ctx); - } - private void LoadSample(string route) { route = route.Replace('/', '.'); @@ -39,4 +31,12 @@ private void Button_Click(object sender, RoutedEventArgs e) grid.ColumnDefinitions[0].Width = _isMenuOpen ? new GridLength(0) : new GridLength(250); _isMenuOpen = !_isMenuOpen; } + + private void Button_Click_1(object sender, RoutedEventArgs e) + { + grid.ColumnDefinitions[0].Width = new GridLength(0); + + var ctx = (string)((FrameworkElement)sender).DataContext; + LoadSample(ctx); + } } From e1654ebf7c14048f6aecfa01c0ae3912295cb26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Fri, 8 Sep 2023 20:47:34 -0600 Subject: [PATCH 31/78] deploy maui destop --- LiveCharts.Maui.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/LiveCharts.Maui.sln b/LiveCharts.Maui.sln index 99a1f95cd..c2f1f3246 100644 --- a/LiveCharts.Maui.sln +++ b/LiveCharts.Maui.sln @@ -33,6 +33,7 @@ Global {288347E2-11DE-447E-ADF7-1C0EC789713B}.Release|Any CPU.Build.0 = Release|Any CPU {0CFF42C6-E143-48DA-A01B-16097E2769FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0CFF42C6-E143-48DA-A01B-16097E2769FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CFF42C6-E143-48DA-A01B-16097E2769FF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {0CFF42C6-E143-48DA-A01B-16097E2769FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {0CFF42C6-E143-48DA-A01B-16097E2769FF}.Release|Any CPU.Build.0 = Release|Any CPU {0CFF42C6-E143-48DA-A01B-16097E2769FF}.Release|Any CPU.Deploy.0 = Release|Any CPU From 0a6253373e4671262b4118b4a7bd88e2ff57da92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Fri, 8 Sep 2023 20:49:03 -0600 Subject: [PATCH 32/78] try avalonia pinch --- .../CartesianChart.axaml.cs | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs index df1869a30..7105ef203 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs @@ -29,7 +29,6 @@ using System.Windows.Input; using Avalonia; using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; using Avalonia.Markup.Xaml; using Avalonia.Media; @@ -111,9 +110,14 @@ public CartesianChart() PointerPressed += CartesianChart_PointerPressed; PointerMoved += CartesianChart_PointerMoved; + PointerReleased += CartesianChart_PointerReleased; PointerWheelChanged += CartesianChart_PointerWheelChanged; PointerExited += CartesianChart_PointerLeave; + var pinchGesture = new PinchGestureRecognizer(); + GestureRecognizers.Add(pinchGesture); + AddHandler(Gestures.PinchEvent, CartesianChart_Pinched); + DetachedFromVisualTree += CartesianChart_DetachedFromVisualTree; } @@ -743,9 +747,11 @@ private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEven _core?.Update(); } + private DateTime _lastPresed; + private readonly int _tolearance = 100; + private void CartesianChart_PointerPressed(object? sender, PointerPressedEventArgs e) { - if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return; if (e.KeyModifiers > 0) return; var p = e.GetPosition(this); @@ -755,12 +761,14 @@ private void CartesianChart_PointerPressed(object? sender, PointerPressedEventAr if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); } - foreach (var w in desktop.Windows) w.PointerReleased += Window_PointerReleased; _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), e.GetCurrentPoint(this).Properties.IsRightButtonPressed); + _lastPresed = DateTime.Now; } private void CartesianChart_PointerMoved(object? sender, PointerEventArgs e) { + + if ((DateTime.Now - _lastPresed).TotalMilliseconds < _tolearance) return; var p = e.GetPosition(_avaloniaCanvas); if (PointerMoveCommand is not null) @@ -772,10 +780,9 @@ private void CartesianChart_PointerMoved(object? sender, PointerEventArgs e) _core?.InvokePointerMove(new LvcPoint((float)p.X, (float)p.Y)); } - private void Window_PointerReleased(object? sender, PointerReleasedEventArgs e) + private void CartesianChart_PointerReleased(object? sender, PointerReleasedEventArgs e) { - if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return; - foreach (var w in desktop.Windows) w.PointerReleased -= Window_PointerReleased; + if ((DateTime.Now - _lastPresed).TotalMilliseconds < _tolearance) return; var p = e.GetPosition(this); if (PointerReleasedCommand is not null) @@ -802,6 +809,24 @@ private void CartesianChart_PointerWheelChanged(object? sender, PointerWheelEven c.Zoom(new LvcPoint((float)p.X, (float)p.Y), e.Delta.Y > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut); } + private float _previousScale = 1; + private void CartesianChart_Pinched(object? sender, PinchEventArgs e) + { + if (_core is null) return; + + var c = (CartesianChart)_core; + var p = e.ScaleOrigin; + var s = c.ControlSize; + var pivot = new LvcPoint((float)(p.X * s.Width), (float)(p.Y * s.Height)); + + var scale = (float)e.Scale; + var delta = _previousScale - scale; + if (Math.Abs(delta) > 0.05) delta = 0; // ignore the first call. + _previousScale = scale; + + c.Zoom(pivot, ZoomDirection.DefinedByScaleFactor, 1 - delta, true); + } + private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); From ce08a03a1f405414568e7310ec9822c3867944ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Fri, 8 Sep 2023 21:38:25 -0600 Subject: [PATCH 33/78] try 5 --- src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs index dec0a8a00..cfc8c4426 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs @@ -130,7 +130,7 @@ protected UIPanGestureRecognizer GetMacCatalystOnPan(UIView view) _last ??= l; var delta = _last.Value.Y - l.Y; var isZoom = e.NumberOfTouches == 0; - var tolerance = 10; // just a fator to avoid multiple calls. + var tolerance = 5; // just a fator to avoid multiple calls. if (e.State == UIGestureRecognizerState.Ended || !isZoom || Math.Abs(delta) < tolerance) return; Scrolled?.Invoke(view, new(new(l.X, l.Y), delta, e)); From db61f33b7895213710b05475de62b23c54ecbd4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Fri, 8 Sep 2023 23:17:03 -0600 Subject: [PATCH 34/78] add secondary click on double tap --- src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs | 9 ++++++++- .../ChartBehaviour.MacCatalyst.cs | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs index cf70f65be..9ad2112ac 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs @@ -36,6 +36,8 @@ public abstract partial class ChartBehaviour private bool _isDown; private LvcPoint _lastTouch; private ScaleGestureDetector? _scaleDetector; + private CustomScaleListener _customScaleListener = null!; + private DateTime _previousPress = DateTime.MinValue; protected void OnAndroidHover(object? sender, View.HoverEventArgs e) { @@ -54,7 +56,7 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) var isPinch = e.Event.PointerCount > 1; _scaleDetector ??= new ScaleGestureDetector( - ((View)sender!).Context!, new CustomScaleListener(scale => + ((View)sender!).Context!, _customScaleListener = new CustomScaleListener(scale => { Pinched?.Invoke(sender, new(scale, _lastTouch, _scaleDetector!)); })); @@ -72,6 +74,8 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) _isDown = true; if (!_isPinching) Pressed?.Invoke(sender, new(p, isRightClick, e.Event)); + _previousPress = DateTime.Now; + _customScaleListener.Paused = isRightClick && !isPinch; break; case MotionEventActions.Move: case MotionEventActions.HoverMove: @@ -91,6 +95,7 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) else _isPinching = false; _isDown = false; + _customScaleListener.Paused = false; break; case MotionEventActions.HoverEnter: case MotionEventActions.HoverExit: @@ -114,6 +119,8 @@ public CustomScaleListener(Action onSacaled) _onScaled = onSacaled; } + public bool Paused { get; set; } + public override bool OnScale(ScaleGestureDetector? detector) { if (detector is null || detector.ScaleFactor == 1) return false; diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs index cfc8c4426..fab6f4a77 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.MacCatalyst.cs @@ -33,6 +33,8 @@ namespace LiveChartsCore.Behaviours; /// public partial class ChartBehaviour { + private DateTime _previousPress = DateTime.MinValue; + protected UIHoverGestureRecognizer GetMacCatalystHover(UIView view) { return new UIHoverGestureRecognizer((UIHoverGestureRecognizer e) => @@ -62,13 +64,14 @@ protected UILongPressGestureRecognizer GetMacCatalystLongPress(UIView view) { var location = e.LocationInView(view); var p = new LvcPoint((float)location.X, (float)location.Y); - var isRightClick = false; // can we detect this? + var isRightClick = (DateTime.Now - _previousPress).TotalMilliseconds < 500; var isPinch = e.NumberOfTouches > 1; switch (e.State) { case UIGestureRecognizerState.Began: Pressed?.Invoke(view, new(p, isRightClick, e)); + _previousPress = DateTime.Now; break; case UIGestureRecognizerState.Changed: Moved?.Invoke(view, new(p, e)); From ad1e58050a21b0ed731802b9af1106673393c5ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Fri, 8 Sep 2023 23:20:55 -0600 Subject: [PATCH 35/78] add secondary on double click on avalonia --- .../CartesianChart.axaml.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs index 7105ef203..9ee2f1a70 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs @@ -748,8 +748,7 @@ private void OnDeepCollectionPropertyChanged(object? sender, PropertyChangedEven } private DateTime _lastPresed; - private readonly int _tolearance = 100; - + private readonly int _tolearance = 50; private void CartesianChart_PointerPressed(object? sender, PointerPressedEventArgs e) { if (e.KeyModifiers > 0) return; @@ -761,7 +760,11 @@ private void CartesianChart_PointerPressed(object? sender, PointerPressedEventAr if (PointerPressedCommand.CanExecute(args)) PointerPressedCommand.Execute(args); } - _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), e.GetCurrentPoint(this).Properties.IsRightButtonPressed); + var isSecondary = + e.GetCurrentPoint(this).Properties.IsRightButtonPressed || + (DateTime.Now - _lastPresed).TotalMilliseconds < 500; + + _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), isSecondary); _lastPresed = DateTime.Now; } From 38cdac45c72557590ba2af3abbbcfc1a509e016a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Fri, 8 Sep 2023 23:28:22 -0600 Subject: [PATCH 36/78] also uno uwp --- .../Behaviours/ChartBehaviour.Android.cs | 11 +++++++++-- .../Behaviours/ChartBehaviour.MacCatalyst.cs | 7 +++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs index 005361a98..fc024e7dd 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs @@ -30,12 +30,14 @@ namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours; /// /// A class that adds platform-specific events to the chart. /// -public partial class ChartBehaviour +public abstract partial class ChartBehaviour { private bool _isPinching; private bool _isDown; private LvcPoint _lastTouch; private ScaleGestureDetector? _scaleDetector; + private CustomScaleListener _customScaleListener = null!; + private DateTime _previousPress = DateTime.MinValue; protected void OnAndroidHover(object? sender, View.HoverEventArgs e) { @@ -54,7 +56,7 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) var isPinch = e.Event.PointerCount > 1; _scaleDetector ??= new ScaleGestureDetector( - ((View)sender!).Context!, new CustomScaleListener(scale => + ((View)sender!).Context!, _customScaleListener = new CustomScaleListener(scale => { Pinched?.Invoke(sender, new(scale, _lastTouch, _scaleDetector!)); })); @@ -72,6 +74,8 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) _isDown = true; if (!_isPinching) Pressed?.Invoke(sender, new(p, isRightClick, e.Event)); + _previousPress = DateTime.Now; + _customScaleListener.Paused = isRightClick && !isPinch; break; case MotionEventActions.Move: case MotionEventActions.HoverMove: @@ -91,6 +95,7 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) else _isPinching = false; _isDown = false; + _customScaleListener.Paused = false; break; case MotionEventActions.HoverEnter: case MotionEventActions.HoverExit: @@ -114,6 +119,8 @@ public CustomScaleListener(Action onSacaled) _onScaled = onSacaled; } + public bool Paused { get; set; } + public override bool OnScale(ScaleGestureDetector? detector) { if (detector is null || detector.ScaleFactor == 1) return false; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.MacCatalyst.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.MacCatalyst.cs index f6a51e644..d8e110332 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.MacCatalyst.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.MacCatalyst.cs @@ -33,6 +33,8 @@ namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours; /// public partial class ChartBehaviour { + private DateTime _previousPress = DateTime.MinValue; + protected UIHoverGestureRecognizer GetMacCatalystHover(UIView view) { return new UIHoverGestureRecognizer((UIHoverGestureRecognizer e) => @@ -62,13 +64,14 @@ protected UILongPressGestureRecognizer GetMacCatalystLongPress(UIView view) { var location = e.LocationInView(view); var p = new LvcPoint((float)location.X, (float)location.Y); - var isRightClick = false; // can we detect this? + var isRightClick = (DateTime.Now - _previousPress).TotalMilliseconds < 500; var isPinch = e.NumberOfTouches > 1; switch (e.State) { case UIGestureRecognizerState.Began: Pressed?.Invoke(view, new(p, isRightClick, e)); + _previousPress = DateTime.Now; break; case UIGestureRecognizerState.Changed: Moved?.Invoke(view, new(p, e)); @@ -130,7 +133,7 @@ protected UIPanGestureRecognizer GetMacCatalystOnPan(UIView view) _last ??= l; var delta = _last.Value.Y - l.Y; var isZoom = e.NumberOfTouches == 0; - var tolerance = 10; // just a fator to avoid multiple calls. + var tolerance = 5; // just a fator to avoid multiple calls. if (e.State == UIGestureRecognizerState.Ended || !isZoom || Math.Abs(delta) < tolerance) return; Scrolled?.Invoke(view, new(new(l.X, l.Y), delta, e)); From 6e95876b440427308dc6cd3bff5bc04bb2315daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 12:09:15 -0600 Subject: [PATCH 37/78] clean events in core chart --- src/LiveChartsCore/Chart.cs | 67 ++++--------------- .../CartesianChart.axaml.cs | 1 - 2 files changed, 14 insertions(+), 54 deletions(-) diff --git a/src/LiveChartsCore/Chart.cs b/src/LiveChartsCore/Chart.cs index 8202d5b03..e50925809 100644 --- a/src/LiveChartsCore/Chart.cs +++ b/src/LiveChartsCore/Chart.cs @@ -87,11 +87,6 @@ protected Chart( : new ActionThrottler(UpdateThrottlerUnlocked, TimeSpan.FromMilliseconds(50)); _updateThrottler.ThrottlerTimeSpan = view.UpdaterThrottler; - PointerDown += Chart_PointerDown; - PointerMove += Chart_PointerMove; - PointerUp += Chart_PointerUp; - PointerLeft += Chart_PointerLeft; - _tooltipThrottler = new ActionThrottler(TooltipThrottlerUnlocked, TimeSpan.FromMilliseconds(50)); _panningThrottler = new ActionThrottler(PanningThrottlerUnlocked, TimeSpan.FromMilliseconds(30)); @@ -117,16 +112,6 @@ protected Chart( /// public event ChartEventHandler? UpdateFinished; - internal event Action PointerDown; - - internal event Action PointerMove; - - internal event Action PointerUp; - - internal event Action PointerLeft; - - internal event Action? PanGesture; - #region properties /// @@ -349,7 +334,9 @@ public virtual void Unload() internal virtual void InvokePointerDown(LvcPoint point, bool isSecondaryAction) { - PointerDown?.Invoke(point); + _isPanning = true; + _pointerPreviousPanningPosition = point; + _pointerPanningStartPosition = point; lock (View.SyncContext) { @@ -385,12 +372,20 @@ internal virtual void InvokePointerDown(LvcPoint point, bool isSecondaryAction) internal virtual void InvokePointerMove(LvcPoint point) { - PointerMove?.Invoke(point); + _pointerPosition = point; + _isPointerIn = true; + _tooltipThrottler.Call(); + if (!_isPanning) return; + _pointerPanningPosition = point; + _panningThrottler.Call(); } internal virtual void InvokePointerUp(LvcPoint point, bool isSecondaryAction) { - PointerUp?.Invoke(point); + if (!_isPanning) return; + _isPanning = false; + _pointerPanningPosition = point; + _panningThrottler.Call(); } internal void InvokePointerLeft() @@ -398,12 +393,8 @@ internal void InvokePointerLeft() _isToolTipOpen = false; Tooltip?.Hide(this); CleanHoveredPoints(new()); - PointerLeft?.Invoke(); - } - internal void InvokePanGestrue(PanGestureEventArgs eventArgs) - { - PanGesture?.Invoke(eventArgs); + _isPointerIn = false; } /// @@ -712,34 +703,4 @@ private void OnCanvasValidated(MotionCanvas chart) { InvokeOnUpdateFinished(); } - - private void Chart_PointerDown(LvcPoint pointerPosition) - { - _isPanning = true; - _pointerPreviousPanningPosition = pointerPosition; - _pointerPanningStartPosition = pointerPosition; - } - - private void Chart_PointerMove(LvcPoint pointerPosition) - { - _pointerPosition = pointerPosition; - _isPointerIn = true; - _tooltipThrottler.Call(); - if (!_isPanning) return; - _pointerPanningPosition = pointerPosition; - _panningThrottler.Call(); - } - - private void Chart_PointerLeft() - { - _isPointerIn = false; - } - - private void Chart_PointerUp(LvcPoint pointerPosition) - { - if (!_isPanning) return; - _isPanning = false; - _pointerPanningPosition = pointerPosition; - _panningThrottler.Call(); - } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs index 9ee2f1a70..bc161f226 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs @@ -770,7 +770,6 @@ private void CartesianChart_PointerPressed(object? sender, PointerPressedEventAr private void CartesianChart_PointerMoved(object? sender, PointerEventArgs e) { - if ((DateTime.Now - _lastPresed).TotalMilliseconds < _tolearance) return; var p = e.GetPosition(_avaloniaCanvas); From 835e6b327e3f5a652517ded417ba430ddba743ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 13:54:40 -0600 Subject: [PATCH 38/78] add net6 target to avalonia --- .../LiveChartsCore.SkiaSharpView.Avalonia.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj index 37bbac400..565d708e1 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj @@ -3,7 +3,7 @@ Library 11.0 enable - netcoreapp2.0;netstandard2.0;net462; + netcoreapp2.0;netstandard2.0;net462;net6.0 LiveChartsCore.SkiaSharpView.Avalonia LiveChartsCore.SkiaSharpView.Avalonia 2.0.0-beta.950 From 067a1a8476fc0ecb59e62ab57d6c776c262e33a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 13:56:06 -0600 Subject: [PATCH 39/78] hahndle mobile devices tooltips from core --- src/LiveChartsCore/Chart.cs | 56 ++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/LiveChartsCore/Chart.cs b/src/LiveChartsCore/Chart.cs index e50925809..3918f3f5d 100644 --- a/src/LiveChartsCore/Chart.cs +++ b/src/LiveChartsCore/Chart.cs @@ -23,7 +23,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; @@ -56,13 +55,14 @@ public abstract class Chart : IChart private readonly ActionThrottler _updateThrottler; private readonly ActionThrottler _tooltipThrottler; private readonly ActionThrottler _panningThrottler; + private bool _isTooltipCanceled; private LvcPoint _pointerPanningStartPosition = new(-10, -10); private LvcPoint _pointerPanningPosition = new(-10, -10); private LvcPoint _pointerPreviousPanningPosition = new(-10, -10); private bool _isPanning = false; private readonly Dictionary _activePoints = new(); private LvcSize _previousSize = new(); - private DateTime _tooltipClosesAt = DateTime.MaxValue; + private readonly bool _isMobile; #endregion @@ -90,17 +90,11 @@ protected Chart( _tooltipThrottler = new ActionThrottler(TooltipThrottlerUnlocked, TimeSpan.FromMilliseconds(50)); _panningThrottler = new ActionThrottler(PanningThrottlerUnlocked, TimeSpan.FromMilliseconds(30)); - _ = new Timer(o => - { - if (DateTime.Now < _tooltipClosesAt) return; +#if NET5_0_OR_GREATER - _tooltipClosesAt = DateTime.MaxValue; - view.InvokeOnUIThread(() => - { - Tooltip?.Hide(this); - canvas.Invalidate(); - }); - }, null, 2000, 2000); + _isMobile = OperatingSystem.IsOSPlatform("Android") || OperatingSystem.IsOSPlatform("iOS"); + +#endif } /// @@ -338,8 +332,10 @@ internal virtual void InvokePointerDown(LvcPoint point, bool isSecondaryAction) _pointerPreviousPanningPosition = point; _pointerPanningStartPosition = point; - lock (View.SyncContext) + lock (Canvas.Sync) { + if (_isMobile) _isTooltipCanceled = false; + var strategy = VisibleSeries.GetTooltipFindingStrategy(); // fire the series event. @@ -375,6 +371,7 @@ internal virtual void InvokePointerMove(LvcPoint point) _pointerPosition = point; _isPointerIn = true; _tooltipThrottler.Call(); + if (!_isPanning) return; _pointerPanningPosition = point; _panningThrottler.Call(); @@ -382,6 +379,16 @@ internal virtual void InvokePointerMove(LvcPoint point) internal virtual void InvokePointerUp(LvcPoint point, bool isSecondaryAction) { + if (_isMobile) + { + lock (Canvas.Sync) + { + _isTooltipCanceled = true; + } + + View.InvokeOnUIThread(CloseTooltip); + } + if (!_isPanning) return; _isPanning = false; _pointerPanningPosition = point; @@ -390,10 +397,7 @@ internal virtual void InvokePointerUp(LvcPoint point, bool isSecondaryAction) internal void InvokePointerLeft() { - _isToolTipOpen = false; - Tooltip?.Hide(this); - CleanHoveredPoints(new()); - + View.InvokeOnUIThread(CloseTooltip); _isPointerIn = false; } @@ -484,7 +488,7 @@ protected virtual Task UpdateThrottlerUnlocked() } /// - /// Updates thhe bounds tracker. + /// Updates the bounds tracker. /// protected void UpdateBounds() { @@ -624,7 +628,6 @@ protected void DrawToolTip() x < DrawMarginLocation.X || x > DrawMarginLocation.X + DrawMarginSize.Width || y < DrawMarginLocation.Y || y > DrawMarginLocation.Y + DrawMarginSize.Height) { - _tooltipClosesAt = DateTime.Now.AddSeconds(1.5); return; } @@ -641,15 +644,10 @@ protected void DrawToolTip() CleanHoveredPoints(o); - if (isEmpty) - { - _tooltipClosesAt = DateTime.Now.AddSeconds(1.5); - return; - } + if (isEmpty) return; Tooltip?.Show(points, this); _isToolTipOpen = true; - _tooltipClosesAt = DateTime.MaxValue; } private void CleanHoveredPoints(object comparer) @@ -670,6 +668,7 @@ private Task TooltipThrottlerUnlocked() { lock (Canvas.Sync) { + if (_isTooltipCanceled) return; DrawToolTip(); Canvas.Invalidate(); } @@ -699,6 +698,13 @@ private Task PanningThrottlerUnlocked() })); } + private void CloseTooltip() + { + _isToolTipOpen = false; + Tooltip?.Hide(this); + CleanHoveredPoints(new()); + } + private void OnCanvasValidated(MotionCanvas chart) { InvokeOnUpdateFinished(); From 1daaba5d145fdb3accabdde65233d95336dfb204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 16:39:20 -0600 Subject: [PATCH 40/78] split into avalonia dektop/android --- LiveCharts.sln | 122 ++++++++++++++++++ samples/AvaloniaSample/App.axaml.cs | 6 +- .../AvaloniaSample/Assets/avalonia-logo.ico | Bin 0 -> 176111 bytes samples/AvaloniaSample/AvaloniaSample.csproj | 28 ++-- .../Axes/ColorsAndPosition/View.axaml.cs | 2 +- .../Axes/Crosshairs/View.axaml.cs | 2 +- .../CustomSeparatorsInterval/View.axaml.cs | 2 +- .../Axes/DateTimeScaled/View.axaml.cs | 2 +- .../Axes/LabelsFormat/View.axaml.cs | 2 +- .../Axes/LabelsFormat2/View.axaml.cs | 2 +- .../Axes/LabelsRotation/View.axaml.cs | 2 +- .../Axes/Logarithmic/View.axaml.cs | 2 +- .../Axes/Multiple/View.axaml.cs | 2 +- .../Axes/NamedLabels/View.axaml.cs | 2 +- .../AvaloniaSample/Axes/Paging/View.axaml.cs | 2 +- .../AvaloniaSample/Axes/Shared/View.axaml.cs | 2 +- .../AvaloniaSample/Axes/Style/View.axaml.cs | 2 +- .../Axes/TimeSpanScaled/View.axaml.cs | 2 +- .../Bars/AutoUpdate/View.axaml.cs | 2 +- .../AvaloniaSample/Bars/Basic/View.axaml.cs | 2 +- .../AvaloniaSample/Bars/Custom/View.axaml.cs | 2 +- .../Bars/DelayedAnimation/View.axaml.cs | 2 +- .../AvaloniaSample/Bars/Layered/View.axaml.cs | 2 +- .../AvaloniaSample/Bars/Race/View.axaml.cs | 2 +- .../Bars/RowsWithLabels/View.axaml.cs | 2 +- .../AvaloniaSample/Bars/Spacing/View.axaml.cs | 2 +- .../Bars/WithBackground/View.axaml.cs | 2 +- .../AvaloniaSample/Box/Basic/View.axaml.cs | 2 +- .../Design/LinearGradients/View.axaml.cs | 2 +- .../Design/RadialGradients/View.axaml.cs | 2 +- .../Design/StrokeDashArray/View.axaml.cs | 2 +- .../AvaloniaSample/Error/Basic/View.axaml.cs | 2 +- .../Events/AddPointOnClick/View.axaml.cs | 2 +- .../Events/Cartesian/View.axaml.cs | 2 +- .../AvaloniaSample/Events/Pie/View.axaml.cs | 2 +- .../AvaloniaSample/Events/Polar/View.axaml.cs | 2 +- .../Financial/BasicCandlesticks/View.axaml.cs | 2 +- .../General/Animations/View.axaml.cs | 2 +- .../General/ChartToImage/View.axaml.cs | 2 +- .../General/ConditionalDraw/View.axaml.cs | 2 +- .../General/Legends/View.axaml.cs | 2 +- .../General/MapPoints/View.axaml.cs | 2 +- .../General/MultiThreading/View.axaml.cs | 2 +- .../General/MultiThreading2/View.axaml.cs | 2 +- .../General/NullPoints/View.axaml.cs | 2 +- .../General/RealTime/View.axaml.cs | 2 +- .../General/Scrollable/View.axaml.cs | 2 +- .../General/Sections/View.axaml.cs | 2 +- .../General/Sections2/View.axaml.cs | 2 +- .../General/TemplatedLegends/View.axaml.cs | 2 +- .../General/TemplatedTooltips/View.axaml.cs | 2 +- .../General/Tooltips/View.axaml.cs | 2 +- .../General/UserDefinedTypes/View.axaml.cs | 2 +- .../General/Visibility/View.axaml.cs | 2 +- .../General/VisualElements/View.axaml.cs | 2 +- samples/AvaloniaSample/GlobalSuppressions.cs | 10 -- .../AvaloniaSample/Heat/Basic/View.axaml.cs | 2 +- .../AvaloniaSample/Lines/Area/View.axaml.cs | 2 +- .../Lines/AutoUpdate/View.axaml.cs | 2 +- .../AvaloniaSample/Lines/Basic/View.axaml.cs | 2 +- .../AvaloniaSample/Lines/Custom/View.axaml.cs | 2 +- .../Lines/Padding/View.axaml.cs | 2 +- .../Lines/Properties/View.axaml.cs | 2 +- .../Lines/Straight/View.axaml.cs | 2 +- samples/AvaloniaSample/Lines/XY/View.axaml.cs | 2 +- .../AvaloniaSample/Lines/Zoom/View.axaml.cs | 2 +- samples/AvaloniaSample/MainView.axaml | 61 +++++++++ samples/AvaloniaSample/MainView.axaml.cs | 49 +++++++ samples/AvaloniaSample/MainWindow.axaml | 55 +------- samples/AvaloniaSample/MainWindow.axaml.cs | 18 +-- .../Pies/AngularGauge/View.axaml.cs | 2 +- .../Pies/AutoUpdate/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Basic/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Custom/View.axaml.cs | 2 +- .../Pies/Doughnut/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Gauge/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Gauge1/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Gauge2/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Gauge3/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Gauge4/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Gauge5/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Gauges/View.axaml.cs | 2 +- .../Pies/NightingaleRose/View.axaml.cs | 2 +- .../Pies/Processing/View.axaml.cs | 2 +- .../AvaloniaSample/Pies/Pushout/View.axaml.cs | 2 +- .../AvaloniaSample.Android.csproj | 36 ++++++ .../Platforms/AvaloniaSample.Android/Icon.png | Bin 0 -> 14349 bytes .../AvaloniaSample.Android/MainActivity.cs | 24 ++++ .../Properties/AndroidManifest.xml | 6 + .../Resources/drawable/splash_screen.xml | 13 ++ .../Resources/values-night/colors.xml | 4 + .../Resources/values/colors.xml | 4 + .../Resources/values/styles.xml | 12 ++ .../AvaloniaSample.Desktop.csproj | 20 +++ .../AvaloniaSample.Desktop/Program.cs | 24 ++++ .../AvaloniaSample.Desktop/app.manifest | 18 +++ .../AvaloniaSample/Polar/Basic/View.axaml.cs | 2 +- .../Polar/Coordinates/View.axaml.cs | 2 +- .../Polar/RadialArea/View.axaml.cs | 2 +- samples/AvaloniaSample/Program.cs | 23 ---- .../Scatter/AutoUpdate/View.axaml.cs | 2 +- .../Scatter/Basic/View.axaml.cs | 2 +- .../Scatter/Bubbles/View.axaml.cs | 2 +- .../Scatter/Custom/View.axaml.cs | 2 +- .../StackedArea/Basic/View.axaml.cs | 2 +- .../StackedArea/StepArea/View.axaml.cs | 2 +- .../StackedBars/Basic/View.axaml.cs | 2 +- .../StackedBars/Groups/View.axaml.cs | 2 +- .../StepLines/Area/View.axaml.cs | 2 +- .../StepLines/AutoUpdate/View.axaml.cs | 2 +- .../StepLines/Basic/View.axaml.cs | 2 +- .../StepLines/Custom/View.axaml.cs | 2 +- .../StepLines/Properties/View.axaml.cs | 2 +- .../StepLines/Zoom/View.axaml.cs | 2 +- .../Test/ChangeSeriesInstance/View.axaml.cs | 2 +- .../Test/Dispose/UserControl1.axaml.cs | 2 +- .../AvaloniaSample/Test/Dispose/View.axaml.cs | 2 +- .../MotionCanvasDispose/UserControl1.axaml.cs | 2 +- .../Test/MotionCanvasDispose/View.axaml.cs | 2 +- .../VisualTest/DataTemplate/View.axaml.cs | 2 +- .../VisualTest/ReattachVisual/View.axaml.cs | 2 +- .../VisualTest/Tabs/View.axaml.cs | 2 +- .../TwoChartsOneSeries/View.axaml.cs | 2 +- samples/AvaloniaSample/nuget.config | 11 -- 124 files changed, 518 insertions(+), 230 deletions(-) create mode 100644 samples/AvaloniaSample/Assets/avalonia-logo.ico delete mode 100644 samples/AvaloniaSample/GlobalSuppressions.cs create mode 100644 samples/AvaloniaSample/MainView.axaml create mode 100644 samples/AvaloniaSample/MainView.axaml.cs create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Android/AvaloniaSample.Android.csproj create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Icon.png create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Android/MainActivity.cs create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Properties/AndroidManifest.xml create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/drawable/splash_screen.xml create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values-night/colors.xml create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values/colors.xml create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values/styles.xml create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/AvaloniaSample.Desktop.csproj create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/Program.cs create mode 100644 samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/app.manifest delete mode 100644 samples/AvaloniaSample/Program.cs delete mode 100644 samples/AvaloniaSample/nuget.config diff --git a/LiveCharts.sln b/LiveCharts.sln index 19314314d..b6f0c81f7 100644 --- a/LiveCharts.sln +++ b/LiveCharts.sln @@ -110,6 +110,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.Behaviours", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveChartsCore.SkiaSharpView.Uno.WinUI", "src\skiasharp\LiveChartsCore.SkiaSharpView.Uno.WinUI\LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj", "{407D2FDF-11A1-44B7-91AE-D48D37C0A65E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaSample.Desktop", "samples\AvaloniaSample\Platforms\AvaloniaSample.Desktop\AvaloniaSample.Desktop.csproj", "{9FE9808D-0ADD-4D30-968D-573E229781CA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{275DDC84-8855-4AE4-8C91-423030EA6368}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaSample.Android", "samples\AvaloniaSample\Platforms\AvaloniaSample.Android\AvaloniaSample.Android.csproj", "{6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -2348,6 +2354,119 @@ Global {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|x64.Build.0 = Release|Any CPU {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|x86.ActiveCfg = Release|Any CPU {407D2FDF-11A1-44B7-91AE-D48D37C0A65E}.Release|x86.Build.0 = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|ARM.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|ARM64.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|iPhone.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|x64.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|x64.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|x86.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.AppStore|x86.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|ARM.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|ARM64.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|iPhone.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|x64.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|x64.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|x86.ActiveCfg = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Debug|x86.Build.0 = Debug|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|Any CPU.Build.0 = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|ARM.ActiveCfg = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|ARM.Build.0 = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|ARM64.ActiveCfg = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|ARM64.Build.0 = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|iPhone.ActiveCfg = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|iPhone.Build.0 = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|x64.ActiveCfg = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|x64.Build.0 = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|x86.ActiveCfg = Release|Any CPU + {9FE9808D-0ADD-4D30-968D-573E229781CA}.Release|x86.Build.0 = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|ARM.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|ARM64.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|iPhone.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|x64.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|x64.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|x86.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.AppStore|x86.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|ARM.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|ARM64.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|iPhone.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|x64.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|x64.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|x86.ActiveCfg = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Debug|x86.Build.0 = Debug|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|Any CPU.Build.0 = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|ARM.ActiveCfg = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|ARM.Build.0 = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|ARM64.ActiveCfg = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|ARM64.Build.0 = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|iPhone.ActiveCfg = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|iPhone.Build.0 = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|x64.ActiveCfg = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|x64.Build.0 = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|x86.ActiveCfg = Release|Any CPU + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2389,6 +2508,9 @@ Global {28F4B811-A3DB-44A9-BB38-F072EE3E20F5} = {E8C464D7-B1F8-4331-9DCD-3A6E87503A0E} {CEFD8CA2-64E7-4DF3-AC4D-601A88FC0F1E} = {2F6A1323-9B22-4AFC-9199-A705B72B7885} {03BDCD7C-5428-450B-A757-531AFD36C37E} = {C9A1646F-FABA-48C3-A48B-B4A359D66105} + {9FE9808D-0ADD-4D30-968D-573E229781CA} = {275DDC84-8855-4AE4-8C91-423030EA6368} + {275DDC84-8855-4AE4-8C91-423030EA6368} = {2F6A1323-9B22-4AFC-9199-A705B72B7885} + {6D29698D-7225-4BCE-A3FF-EBB1CB08AADA} = {275DDC84-8855-4AE4-8C91-423030EA6368} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2040E57B-591B-4849-BD29-B4583C81F167} diff --git a/samples/AvaloniaSample/App.axaml.cs b/samples/AvaloniaSample/App.axaml.cs index 73afe2394..4ea53cff0 100644 --- a/samples/AvaloniaSample/App.axaml.cs +++ b/samples/AvaloniaSample/App.axaml.cs @@ -8,7 +8,7 @@ namespace AvaloniaSample; -public class App : Application +public partial class App : Application { public override void Initialize() { @@ -47,6 +47,10 @@ public override void OnFrameworkInitializationCompleted() { desktop.MainWindow = new MainWindow(); } + else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) + { + singleViewPlatform.MainView = new MainView(); + } base.OnFrameworkInitializationCompleted(); } diff --git a/samples/AvaloniaSample/Assets/avalonia-logo.ico b/samples/AvaloniaSample/Assets/avalonia-logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..da8d49ff9b94e52778f5324a1b87dd443a698b57 GIT binary patch literal 176111 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 zds⪻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

r@R8DskCg$QY%d=x6zD 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

!LxQh!NmF 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 - WinExe - net6.0 + net7.0 enable - false 11.0 - - false - + + + + + - + + + + + - - + + + + + - - - diff --git a/samples/AvaloniaSample/Axes/ColorsAndPosition/View.axaml.cs b/samples/AvaloniaSample/Axes/ColorsAndPosition/View.axaml.cs index 7efac0678..e64890dce 100644 --- a/samples/AvaloniaSample/Axes/ColorsAndPosition/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/ColorsAndPosition/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.ColorsAndPosition; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/Crosshairs/View.axaml.cs b/samples/AvaloniaSample/Axes/Crosshairs/View.axaml.cs index 8f805927d..449fe763c 100644 --- a/samples/AvaloniaSample/Axes/Crosshairs/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/Crosshairs/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.Crosshairs; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/CustomSeparatorsInterval/View.axaml.cs b/samples/AvaloniaSample/Axes/CustomSeparatorsInterval/View.axaml.cs index 1de303fe8..630834ba9 100644 --- a/samples/AvaloniaSample/Axes/CustomSeparatorsInterval/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/CustomSeparatorsInterval/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.CustomSeparatorsInterval; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/DateTimeScaled/View.axaml.cs b/samples/AvaloniaSample/Axes/DateTimeScaled/View.axaml.cs index 42542e3e8..cad1a9cdc 100644 --- a/samples/AvaloniaSample/Axes/DateTimeScaled/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/DateTimeScaled/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.DateTimeScaled; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/LabelsFormat/View.axaml.cs b/samples/AvaloniaSample/Axes/LabelsFormat/View.axaml.cs index bbc1947a0..1b7e31285 100644 --- a/samples/AvaloniaSample/Axes/LabelsFormat/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/LabelsFormat/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.LabelsFormat; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/LabelsFormat2/View.axaml.cs b/samples/AvaloniaSample/Axes/LabelsFormat2/View.axaml.cs index de587ccd6..96ce7ec71 100644 --- a/samples/AvaloniaSample/Axes/LabelsFormat2/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/LabelsFormat2/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.LabelsFormat2; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/LabelsRotation/View.axaml.cs b/samples/AvaloniaSample/Axes/LabelsRotation/View.axaml.cs index 0cb4aef40..cd768d1b5 100644 --- a/samples/AvaloniaSample/Axes/LabelsRotation/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/LabelsRotation/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.LabelsRotation; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/Logarithmic/View.axaml.cs b/samples/AvaloniaSample/Axes/Logarithmic/View.axaml.cs index 2901e9041..c4b7122b2 100644 --- a/samples/AvaloniaSample/Axes/Logarithmic/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/Logarithmic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.Logarithmic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/Multiple/View.axaml.cs b/samples/AvaloniaSample/Axes/Multiple/View.axaml.cs index 68ee285ec..ad48b6e7f 100644 --- a/samples/AvaloniaSample/Axes/Multiple/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/Multiple/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.Multiple; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/NamedLabels/View.axaml.cs b/samples/AvaloniaSample/Axes/NamedLabels/View.axaml.cs index 03eee69e7..08f9fcdc7 100644 --- a/samples/AvaloniaSample/Axes/NamedLabels/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/NamedLabels/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.NamedLabels; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/Paging/View.axaml.cs b/samples/AvaloniaSample/Axes/Paging/View.axaml.cs index a790436a7..0261cc76a 100644 --- a/samples/AvaloniaSample/Axes/Paging/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/Paging/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.Paging; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/Shared/View.axaml.cs b/samples/AvaloniaSample/Axes/Shared/View.axaml.cs index 089125c39..fd55c7cf0 100644 --- a/samples/AvaloniaSample/Axes/Shared/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/Shared/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.Shared; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/Style/View.axaml.cs b/samples/AvaloniaSample/Axes/Style/View.axaml.cs index 15418528d..b981c8c17 100644 --- a/samples/AvaloniaSample/Axes/Style/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/Style/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.Style; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Axes/TimeSpanScaled/View.axaml.cs b/samples/AvaloniaSample/Axes/TimeSpanScaled/View.axaml.cs index fd6a36efe..731446ebe 100644 --- a/samples/AvaloniaSample/Axes/TimeSpanScaled/View.axaml.cs +++ b/samples/AvaloniaSample/Axes/TimeSpanScaled/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Axes.TimeSpanScaled; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Bars/AutoUpdate/View.axaml.cs b/samples/AvaloniaSample/Bars/AutoUpdate/View.axaml.cs index 055594a03..23f7321e7 100644 --- a/samples/AvaloniaSample/Bars/AutoUpdate/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/AutoUpdate/View.axaml.cs @@ -5,7 +5,7 @@ namespace AvaloniaSample.Bars.AutoUpdate; -public class View : UserControl +public partial class View : UserControl { private bool? isStreaming = false; diff --git a/samples/AvaloniaSample/Bars/Basic/View.axaml.cs b/samples/AvaloniaSample/Bars/Basic/View.axaml.cs index 4e6cd8647..5c0ecc324 100644 --- a/samples/AvaloniaSample/Bars/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Bars.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Bars/Custom/View.axaml.cs b/samples/AvaloniaSample/Bars/Custom/View.axaml.cs index d8197275a..0e126c8cc 100644 --- a/samples/AvaloniaSample/Bars/Custom/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/Custom/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Bars.Custom; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Bars/DelayedAnimation/View.axaml.cs b/samples/AvaloniaSample/Bars/DelayedAnimation/View.axaml.cs index 3beaafeac..a71e7abab 100644 --- a/samples/AvaloniaSample/Bars/DelayedAnimation/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/DelayedAnimation/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Bars.DelayedAnimation; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Bars/Layered/View.axaml.cs b/samples/AvaloniaSample/Bars/Layered/View.axaml.cs index 2a2aedc94..a261d3c25 100644 --- a/samples/AvaloniaSample/Bars/Layered/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/Layered/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Bars.Layered; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Bars/Race/View.axaml.cs b/samples/AvaloniaSample/Bars/Race/View.axaml.cs index 4a1486988..5ba20dabb 100644 --- a/samples/AvaloniaSample/Bars/Race/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/Race/View.axaml.cs @@ -6,7 +6,7 @@ namespace AvaloniaSample.Bars.Race; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Bars/RowsWithLabels/View.axaml.cs b/samples/AvaloniaSample/Bars/RowsWithLabels/View.axaml.cs index 96935c16c..353304bc6 100644 --- a/samples/AvaloniaSample/Bars/RowsWithLabels/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/RowsWithLabels/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Bars.RowsWithLabels; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Bars/Spacing/View.axaml.cs b/samples/AvaloniaSample/Bars/Spacing/View.axaml.cs index 717c5802f..586159643 100644 --- a/samples/AvaloniaSample/Bars/Spacing/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/Spacing/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Bars.Spacing; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Bars/WithBackground/View.axaml.cs b/samples/AvaloniaSample/Bars/WithBackground/View.axaml.cs index 0fea2024b..859c74190 100644 --- a/samples/AvaloniaSample/Bars/WithBackground/View.axaml.cs +++ b/samples/AvaloniaSample/Bars/WithBackground/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Bars.WithBackground; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Box/Basic/View.axaml.cs b/samples/AvaloniaSample/Box/Basic/View.axaml.cs index 7ad074201..7298bdddc 100644 --- a/samples/AvaloniaSample/Box/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/Box/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Box.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Design/LinearGradients/View.axaml.cs b/samples/AvaloniaSample/Design/LinearGradients/View.axaml.cs index 170fa13d5..f123144dd 100644 --- a/samples/AvaloniaSample/Design/LinearGradients/View.axaml.cs +++ b/samples/AvaloniaSample/Design/LinearGradients/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Design.LinearGradients; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Design/RadialGradients/View.axaml.cs b/samples/AvaloniaSample/Design/RadialGradients/View.axaml.cs index 16abc7fa3..d34c76257 100644 --- a/samples/AvaloniaSample/Design/RadialGradients/View.axaml.cs +++ b/samples/AvaloniaSample/Design/RadialGradients/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Design.RadialGradients; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Design/StrokeDashArray/View.axaml.cs b/samples/AvaloniaSample/Design/StrokeDashArray/View.axaml.cs index 72ffba9ab..aa94d3169 100644 --- a/samples/AvaloniaSample/Design/StrokeDashArray/View.axaml.cs +++ b/samples/AvaloniaSample/Design/StrokeDashArray/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Design.StrokeDashArray; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Error/Basic/View.axaml.cs b/samples/AvaloniaSample/Error/Basic/View.axaml.cs index 352d1e853..d2fe621ce 100644 --- a/samples/AvaloniaSample/Error/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/Error/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Error.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Events/AddPointOnClick/View.axaml.cs b/samples/AvaloniaSample/Events/AddPointOnClick/View.axaml.cs index fb341fe6e..714cbf3fd 100644 --- a/samples/AvaloniaSample/Events/AddPointOnClick/View.axaml.cs +++ b/samples/AvaloniaSample/Events/AddPointOnClick/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Events.AddPointOnClick; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Events/Cartesian/View.axaml.cs b/samples/AvaloniaSample/Events/Cartesian/View.axaml.cs index 7c853b865..6d32cf7a8 100644 --- a/samples/AvaloniaSample/Events/Cartesian/View.axaml.cs +++ b/samples/AvaloniaSample/Events/Cartesian/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Events.Cartesian; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Events/Pie/View.axaml.cs b/samples/AvaloniaSample/Events/Pie/View.axaml.cs index 0c59dab15..3b41d8aee 100644 --- a/samples/AvaloniaSample/Events/Pie/View.axaml.cs +++ b/samples/AvaloniaSample/Events/Pie/View.axaml.cs @@ -8,7 +8,7 @@ namespace AvaloniaSample.Events.Pie; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Events/Polar/View.axaml.cs b/samples/AvaloniaSample/Events/Polar/View.axaml.cs index 40d1ea1b9..5b0c9ba57 100644 --- a/samples/AvaloniaSample/Events/Polar/View.axaml.cs +++ b/samples/AvaloniaSample/Events/Polar/View.axaml.cs @@ -8,7 +8,7 @@ namespace AvaloniaSample.Events.Polar; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Financial/BasicCandlesticks/View.axaml.cs b/samples/AvaloniaSample/Financial/BasicCandlesticks/View.axaml.cs index cb2ca798c..8ce3bde66 100644 --- a/samples/AvaloniaSample/Financial/BasicCandlesticks/View.axaml.cs +++ b/samples/AvaloniaSample/Financial/BasicCandlesticks/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Financial.BasicCandlesticks; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/Animations/View.axaml.cs b/samples/AvaloniaSample/General/Animations/View.axaml.cs index cb35737da..bdc84ed84 100644 --- a/samples/AvaloniaSample/General/Animations/View.axaml.cs +++ b/samples/AvaloniaSample/General/Animations/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.Animations; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/ChartToImage/View.axaml.cs b/samples/AvaloniaSample/General/ChartToImage/View.axaml.cs index 3db6dbf0e..06b336bc1 100644 --- a/samples/AvaloniaSample/General/ChartToImage/View.axaml.cs +++ b/samples/AvaloniaSample/General/ChartToImage/View.axaml.cs @@ -5,7 +5,7 @@ namespace AvaloniaSample.General.ChartToImage; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/ConditionalDraw/View.axaml.cs b/samples/AvaloniaSample/General/ConditionalDraw/View.axaml.cs index 2c6e9ce6a..0c370f7d7 100644 --- a/samples/AvaloniaSample/General/ConditionalDraw/View.axaml.cs +++ b/samples/AvaloniaSample/General/ConditionalDraw/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.ConditionalDraw; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/Legends/View.axaml.cs b/samples/AvaloniaSample/General/Legends/View.axaml.cs index 39cce1ff9..ba64be8b0 100644 --- a/samples/AvaloniaSample/General/Legends/View.axaml.cs +++ b/samples/AvaloniaSample/General/Legends/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.Legends; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/MapPoints/View.axaml.cs b/samples/AvaloniaSample/General/MapPoints/View.axaml.cs index abc881a61..b3e976f81 100644 --- a/samples/AvaloniaSample/General/MapPoints/View.axaml.cs +++ b/samples/AvaloniaSample/General/MapPoints/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.MapPoints; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/MultiThreading/View.axaml.cs b/samples/AvaloniaSample/General/MultiThreading/View.axaml.cs index 250cd5898..8a8769123 100644 --- a/samples/AvaloniaSample/General/MultiThreading/View.axaml.cs +++ b/samples/AvaloniaSample/General/MultiThreading/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.MultiThreading; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/MultiThreading2/View.axaml.cs b/samples/AvaloniaSample/General/MultiThreading2/View.axaml.cs index bdff012e1..d6c1afbfc 100644 --- a/samples/AvaloniaSample/General/MultiThreading2/View.axaml.cs +++ b/samples/AvaloniaSample/General/MultiThreading2/View.axaml.cs @@ -6,7 +6,7 @@ namespace AvaloniaSample.General.MultiThreading2; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/NullPoints/View.axaml.cs b/samples/AvaloniaSample/General/NullPoints/View.axaml.cs index 7b6b11665..40f28c8d6 100644 --- a/samples/AvaloniaSample/General/NullPoints/View.axaml.cs +++ b/samples/AvaloniaSample/General/NullPoints/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.NullPoints; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/RealTime/View.axaml.cs b/samples/AvaloniaSample/General/RealTime/View.axaml.cs index dd6bed55c..19da23b8b 100644 --- a/samples/AvaloniaSample/General/RealTime/View.axaml.cs +++ b/samples/AvaloniaSample/General/RealTime/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.RealTime; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/Scrollable/View.axaml.cs b/samples/AvaloniaSample/General/Scrollable/View.axaml.cs index c8505f117..b03620e43 100644 --- a/samples/AvaloniaSample/General/Scrollable/View.axaml.cs +++ b/samples/AvaloniaSample/General/Scrollable/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.Scrollable; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/Sections/View.axaml.cs b/samples/AvaloniaSample/General/Sections/View.axaml.cs index 06564d739..642123bde 100644 --- a/samples/AvaloniaSample/General/Sections/View.axaml.cs +++ b/samples/AvaloniaSample/General/Sections/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.Sections; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/Sections2/View.axaml.cs b/samples/AvaloniaSample/General/Sections2/View.axaml.cs index 0e9f6c34e..7a067d1f1 100644 --- a/samples/AvaloniaSample/General/Sections2/View.axaml.cs +++ b/samples/AvaloniaSample/General/Sections2/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.Sections2; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/TemplatedLegends/View.axaml.cs b/samples/AvaloniaSample/General/TemplatedLegends/View.axaml.cs index fe124409d..5c54e1bed 100644 --- a/samples/AvaloniaSample/General/TemplatedLegends/View.axaml.cs +++ b/samples/AvaloniaSample/General/TemplatedLegends/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.TemplatedLegends; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/TemplatedTooltips/View.axaml.cs b/samples/AvaloniaSample/General/TemplatedTooltips/View.axaml.cs index 95894c9a5..ac744395b 100644 --- a/samples/AvaloniaSample/General/TemplatedTooltips/View.axaml.cs +++ b/samples/AvaloniaSample/General/TemplatedTooltips/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.TemplatedTooltips; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/Tooltips/View.axaml.cs b/samples/AvaloniaSample/General/Tooltips/View.axaml.cs index a09682581..6654e3bc7 100644 --- a/samples/AvaloniaSample/General/Tooltips/View.axaml.cs +++ b/samples/AvaloniaSample/General/Tooltips/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.Tooltips; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/UserDefinedTypes/View.axaml.cs b/samples/AvaloniaSample/General/UserDefinedTypes/View.axaml.cs index e80430e6a..3c71d61e2 100644 --- a/samples/AvaloniaSample/General/UserDefinedTypes/View.axaml.cs +++ b/samples/AvaloniaSample/General/UserDefinedTypes/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.UserDefinedTypes; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/Visibility/View.axaml.cs b/samples/AvaloniaSample/General/Visibility/View.axaml.cs index 77e6c086f..737b37446 100644 --- a/samples/AvaloniaSample/General/Visibility/View.axaml.cs +++ b/samples/AvaloniaSample/General/Visibility/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.Visibility; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/General/VisualElements/View.axaml.cs b/samples/AvaloniaSample/General/VisualElements/View.axaml.cs index 6d3b64875..8f9141412 100644 --- a/samples/AvaloniaSample/General/VisualElements/View.axaml.cs +++ b/samples/AvaloniaSample/General/VisualElements/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.General.VisualElements; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/GlobalSuppressions.cs b/samples/AvaloniaSample/GlobalSuppressions.cs deleted file mode 100644 index 4fc270371..000000000 --- a/samples/AvaloniaSample/GlobalSuppressions.cs +++ /dev/null @@ -1,10 +0,0 @@ -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("Style", "IDE0058:Expression value is never used", Justification = "", Scope = "member", Target = "~M:AvaloniaSample.MainWindowViewModel.SetDark")] -[assembly: SuppressMessage("Style", "IDE0073:The file header is missing or not located at the top of the file", Justification = "")] -[assembly: SuppressMessage("Style", "IDE0005:Using directive is unnecessary.", Justification = "")] diff --git a/samples/AvaloniaSample/Heat/Basic/View.axaml.cs b/samples/AvaloniaSample/Heat/Basic/View.axaml.cs index 5b57e8b0b..7d0456677 100644 --- a/samples/AvaloniaSample/Heat/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/Heat/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Heat.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Lines/Area/View.axaml.cs b/samples/AvaloniaSample/Lines/Area/View.axaml.cs index b6b9dd448..5241da264 100644 --- a/samples/AvaloniaSample/Lines/Area/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/Area/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Lines.Area; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Lines/AutoUpdate/View.axaml.cs b/samples/AvaloniaSample/Lines/AutoUpdate/View.axaml.cs index d27aa5203..91cab8340 100644 --- a/samples/AvaloniaSample/Lines/AutoUpdate/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/AutoUpdate/View.axaml.cs @@ -5,7 +5,7 @@ namespace AvaloniaSample.Lines.AutoUpdate; -public class View : UserControl +public partial class View : UserControl { private bool? isStreaming = false; diff --git a/samples/AvaloniaSample/Lines/Basic/View.axaml.cs b/samples/AvaloniaSample/Lines/Basic/View.axaml.cs index 0132d85ae..b260a5339 100644 --- a/samples/AvaloniaSample/Lines/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Lines.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Lines/Custom/View.axaml.cs b/samples/AvaloniaSample/Lines/Custom/View.axaml.cs index af770d5e9..a862b91f5 100644 --- a/samples/AvaloniaSample/Lines/Custom/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/Custom/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Lines.Custom; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Lines/Padding/View.axaml.cs b/samples/AvaloniaSample/Lines/Padding/View.axaml.cs index ff2ddfb88..b55802992 100644 --- a/samples/AvaloniaSample/Lines/Padding/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/Padding/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Lines.Padding; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Lines/Properties/View.axaml.cs b/samples/AvaloniaSample/Lines/Properties/View.axaml.cs index e5721ba6c..d6a93f523 100644 --- a/samples/AvaloniaSample/Lines/Properties/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/Properties/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Lines.Properties; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Lines/Straight/View.axaml.cs b/samples/AvaloniaSample/Lines/Straight/View.axaml.cs index e47afeebf..66cf79618 100644 --- a/samples/AvaloniaSample/Lines/Straight/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/Straight/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Lines.Straight; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Lines/XY/View.axaml.cs b/samples/AvaloniaSample/Lines/XY/View.axaml.cs index 1fd49c54e..ada1dc5e9 100644 --- a/samples/AvaloniaSample/Lines/XY/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/XY/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Lines.XY; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Lines/Zoom/View.axaml.cs b/samples/AvaloniaSample/Lines/Zoom/View.axaml.cs index 3d50b401f..6b3d23486 100644 --- a/samples/AvaloniaSample/Lines/Zoom/View.axaml.cs +++ b/samples/AvaloniaSample/Lines/Zoom/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Lines.Zoom; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/MainView.axaml b/samples/AvaloniaSample/MainView.axaml new file mode 100644 index 000000000..61f4bcd98 --- /dev/null +++ b/samples/AvaloniaSample/MainView.axaml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/AvaloniaSample/MainView.axaml.cs b/samples/AvaloniaSample/MainView.axaml.cs new file mode 100644 index 000000000..c63e589f2 --- /dev/null +++ b/samples/AvaloniaSample/MainView.axaml.cs @@ -0,0 +1,49 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using Avalonia.Controls; + +namespace AvaloniaSample; +public partial class MainView : UserControl +{ + public MainView() + { + InitializeComponent(); + + DataContext = new MainWindowViewModel(); + LoadContent("Design.LinearGradients"); + } + + private void OnPointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e) + { + if ((sender as Border)?.DataContext is not string ctx) throw new Exception("Sample not found"); + LoadContent(ctx.Replace('/', '.')); + } + + private void LoadContent(string view) + { + var content = this.FindControl("content")!; + content.Content = Activator.CreateInstance(null!, $"AvaloniaSample.{view}.View")?.Unwrap(); + if (DataContext is not MainWindowViewModel dc) throw new Exception(); + } +} diff --git a/samples/AvaloniaSample/MainWindow.axaml b/samples/AvaloniaSample/MainWindow.axaml index fa76454b7..13c8b2c75 100644 --- a/samples/AvaloniaSample/MainWindow.axaml +++ b/samples/AvaloniaSample/MainWindow.axaml @@ -12,59 +12,6 @@ x:Class="AvaloniaSample.MainWindow" WindowStartupLocation="CenterScreen"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/samples/AvaloniaSample/MainWindow.axaml.cs b/samples/AvaloniaSample/MainWindow.axaml.cs index f8935dfd5..a62681a55 100644 --- a/samples/AvaloniaSample/MainWindow.axaml.cs +++ b/samples/AvaloniaSample/MainWindow.axaml.cs @@ -5,7 +5,7 @@ namespace AvaloniaSample; -public class MainWindow : Window +public partial class MainWindow : Window { public MainWindow() { @@ -13,22 +13,6 @@ public MainWindow() #if DEBUG this.AttachDevTools(); #endif - - DataContext = new MainWindowViewModel(); - LoadContent("Design.LinearGradients"); - } - - private void OnPointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e) - { - if ((sender as Border)?.DataContext is not string ctx) throw new Exception("Sample not found"); - LoadContent(ctx.Replace('/', '.')); - } - - private void LoadContent(string view) - { - var content = this.FindControl("content")!; - content.Content = Activator.CreateInstance(null!, $"AvaloniaSample.{view}.View")?.Unwrap(); - if (DataContext is not MainWindowViewModel dc) throw new Exception(); } private void InitializeComponent() diff --git a/samples/AvaloniaSample/Pies/AngularGauge/View.axaml.cs b/samples/AvaloniaSample/Pies/AngularGauge/View.axaml.cs index 36033c80f..34617a9ff 100644 --- a/samples/AvaloniaSample/Pies/AngularGauge/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/AngularGauge/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.AngularGauge; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/AutoUpdate/View.axaml.cs b/samples/AvaloniaSample/Pies/AutoUpdate/View.axaml.cs index cfc3df022..edf70680d 100644 --- a/samples/AvaloniaSample/Pies/AutoUpdate/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/AutoUpdate/View.axaml.cs @@ -5,7 +5,7 @@ namespace AvaloniaSample.Pies.AutoUpdate; -public class View : UserControl +public partial class View : UserControl { private bool? isStreaming = false; diff --git a/samples/AvaloniaSample/Pies/Basic/View.axaml.cs b/samples/AvaloniaSample/Pies/Basic/View.axaml.cs index ec9e9035f..6ee809c65 100644 --- a/samples/AvaloniaSample/Pies/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Custom/View.axaml.cs b/samples/AvaloniaSample/Pies/Custom/View.axaml.cs index 67445be6b..6854539ca 100644 --- a/samples/AvaloniaSample/Pies/Custom/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Custom/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Custom; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Doughnut/View.axaml.cs b/samples/AvaloniaSample/Pies/Doughnut/View.axaml.cs index 5c9059e74..486366e0d 100644 --- a/samples/AvaloniaSample/Pies/Doughnut/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Doughnut/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Doughnut; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Gauge/View.axaml.cs b/samples/AvaloniaSample/Pies/Gauge/View.axaml.cs index 8028724be..e8f1d0ade 100644 --- a/samples/AvaloniaSample/Pies/Gauge/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Gauge/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Gauge; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Gauge1/View.axaml.cs b/samples/AvaloniaSample/Pies/Gauge1/View.axaml.cs index 8cdddd52d..c90db7581 100644 --- a/samples/AvaloniaSample/Pies/Gauge1/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Gauge1/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Gauge1; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Gauge2/View.axaml.cs b/samples/AvaloniaSample/Pies/Gauge2/View.axaml.cs index d3c5631bd..fab027f17 100644 --- a/samples/AvaloniaSample/Pies/Gauge2/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Gauge2/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Gauge2; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Gauge3/View.axaml.cs b/samples/AvaloniaSample/Pies/Gauge3/View.axaml.cs index 0f49649c6..d77288364 100644 --- a/samples/AvaloniaSample/Pies/Gauge3/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Gauge3/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Gauge3; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Gauge4/View.axaml.cs b/samples/AvaloniaSample/Pies/Gauge4/View.axaml.cs index e45947bf6..21ce91b3f 100644 --- a/samples/AvaloniaSample/Pies/Gauge4/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Gauge4/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Gauge4; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Gauge5/View.axaml.cs b/samples/AvaloniaSample/Pies/Gauge5/View.axaml.cs index 786d3d712..5e3b9d152 100644 --- a/samples/AvaloniaSample/Pies/Gauge5/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Gauge5/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Gauge5; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Gauges/View.axaml.cs b/samples/AvaloniaSample/Pies/Gauges/View.axaml.cs index 65c17f5d7..4d1f1148c 100644 --- a/samples/AvaloniaSample/Pies/Gauges/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Gauges/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Gauges; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/NightingaleRose/View.axaml.cs b/samples/AvaloniaSample/Pies/NightingaleRose/View.axaml.cs index ce2f893c2..b8b23c9dc 100644 --- a/samples/AvaloniaSample/Pies/NightingaleRose/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/NightingaleRose/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.NightingaleRose; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Processing/View.axaml.cs b/samples/AvaloniaSample/Pies/Processing/View.axaml.cs index bde80fd09..1249653c8 100644 --- a/samples/AvaloniaSample/Pies/Processing/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Processing/View.axaml.cs @@ -8,7 +8,7 @@ namespace AvaloniaSample.Pies.Processing; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Pies/Pushout/View.axaml.cs b/samples/AvaloniaSample/Pies/Pushout/View.axaml.cs index 1834f7b98..4e2aafd3c 100644 --- a/samples/AvaloniaSample/Pies/Pushout/View.axaml.cs +++ b/samples/AvaloniaSample/Pies/Pushout/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Pies.Pushout; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/AvaloniaSample.Android.csproj b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/AvaloniaSample.Android.csproj new file mode 100644 index 000000000..bf1270ab2 --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/AvaloniaSample.Android.csproj @@ -0,0 +1,36 @@ + + + + Exe + net7.0-android + 21 + enable + com.CompanyName.AvaloniaSample + 1 + 1.0 + apk + False + + + + + + + + + + + Resources\drawable\Icon.png + + + + + + + + + + + + + diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Icon.png b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..41a2a618fb02e4cb7f6a15caf572b693bfe1ebb1 GIT binary patch literal 14349 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 +{ + protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) + { + return base.CustomizeAppBuilder(builder) + .WithInterFont() + .UseReactiveUI(); + } +} diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Properties/AndroidManifest.xml b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Properties/AndroidManifest.xml new file mode 100644 index 000000000..d5a465ef9 --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Properties/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/drawable/splash_screen.xml b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/drawable/splash_screen.xml new file mode 100644 index 000000000..2e920b4b3 --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/drawable/splash_screen.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values-night/colors.xml b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values-night/colors.xml new file mode 100644 index 000000000..3d47b6fc5 --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values-night/colors.xml @@ -0,0 +1,4 @@ + + + #212121 + diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values/colors.xml b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values/colors.xml new file mode 100644 index 000000000..59279d5d3 --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values/colors.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values/styles.xml b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values/styles.xml new file mode 100644 index 000000000..6e534de2f --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Android/Resources/values/styles.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/AvaloniaSample.Desktop.csproj b/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/AvaloniaSample.Desktop.csproj new file mode 100644 index 000000000..1f953cba5 --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/AvaloniaSample.Desktop.csproj @@ -0,0 +1,20 @@ + + + + WinExe + + net7.0 + enable + true + app.manifest + + + + + + + + + + diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/Program.cs b/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/Program.cs new file mode 100644 index 000000000..19b14cd7a --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/Program.cs @@ -0,0 +1,24 @@ +using System; + +using Avalonia; +using Avalonia.ReactiveUI; + +namespace AvaloniaApplication1.Desktop; + +class Program +{ + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace() + .UseReactiveUI(); +} diff --git a/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/app.manifest b/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/app.manifest new file mode 100644 index 000000000..67ca5f9b1 --- /dev/null +++ b/samples/AvaloniaSample/Platforms/AvaloniaSample.Desktop/app.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/samples/AvaloniaSample/Polar/Basic/View.axaml.cs b/samples/AvaloniaSample/Polar/Basic/View.axaml.cs index c7ee3a48c..3385bc8ad 100644 --- a/samples/AvaloniaSample/Polar/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/Polar/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Polar.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Polar/Coordinates/View.axaml.cs b/samples/AvaloniaSample/Polar/Coordinates/View.axaml.cs index 298e7ff34..670e74057 100644 --- a/samples/AvaloniaSample/Polar/Coordinates/View.axaml.cs +++ b/samples/AvaloniaSample/Polar/Coordinates/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Polar.Coordinates; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Polar/RadialArea/View.axaml.cs b/samples/AvaloniaSample/Polar/RadialArea/View.axaml.cs index c7170a496..ec0322da8 100644 --- a/samples/AvaloniaSample/Polar/RadialArea/View.axaml.cs +++ b/samples/AvaloniaSample/Polar/RadialArea/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Polar.RadialArea; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Program.cs b/samples/AvaloniaSample/Program.cs deleted file mode 100644 index ccefa264b..000000000 --- a/samples/AvaloniaSample/Program.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Avalonia; - -namespace AvaloniaSample; - -class Program -{ - // Initialization code. Don't use any Avalonia, third-party APIs or any - // SynchronizationContext-reliant code before AppMain is called: things aren't initialized - // yet and stuff might break. - public static void Main(string[] args) - { - BuildAvaloniaApp() - .StartWithClassicDesktopLifetime(args); - } - - // Avalonia configuration, don't remove; also used by visual designer. - public static AppBuilder BuildAvaloniaApp() - { - return AppBuilder.Configure() - .UsePlatformDetect() - .LogToTrace(); - } -} diff --git a/samples/AvaloniaSample/Scatter/AutoUpdate/View.axaml.cs b/samples/AvaloniaSample/Scatter/AutoUpdate/View.axaml.cs index 0d3db4f7d..5d855cacb 100644 --- a/samples/AvaloniaSample/Scatter/AutoUpdate/View.axaml.cs +++ b/samples/AvaloniaSample/Scatter/AutoUpdate/View.axaml.cs @@ -5,7 +5,7 @@ namespace AvaloniaSample.Scatter.AutoUpdate; -public class View : UserControl +public partial class View : UserControl { private bool? isStreaming = false; diff --git a/samples/AvaloniaSample/Scatter/Basic/View.axaml.cs b/samples/AvaloniaSample/Scatter/Basic/View.axaml.cs index e98a50e4b..451d44c11 100644 --- a/samples/AvaloniaSample/Scatter/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/Scatter/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Scatter.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Scatter/Bubbles/View.axaml.cs b/samples/AvaloniaSample/Scatter/Bubbles/View.axaml.cs index 4490dfc93..9edcecb62 100644 --- a/samples/AvaloniaSample/Scatter/Bubbles/View.axaml.cs +++ b/samples/AvaloniaSample/Scatter/Bubbles/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Scatter.Bubbles; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Scatter/Custom/View.axaml.cs b/samples/AvaloniaSample/Scatter/Custom/View.axaml.cs index 4dcb84790..2b6b308a8 100644 --- a/samples/AvaloniaSample/Scatter/Custom/View.axaml.cs +++ b/samples/AvaloniaSample/Scatter/Custom/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Scatter.Custom; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StackedArea/Basic/View.axaml.cs b/samples/AvaloniaSample/StackedArea/Basic/View.axaml.cs index fe59d6233..b534ed344 100644 --- a/samples/AvaloniaSample/StackedArea/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/StackedArea/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StackedArea.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StackedArea/StepArea/View.axaml.cs b/samples/AvaloniaSample/StackedArea/StepArea/View.axaml.cs index 6882d8530..4765e60f5 100644 --- a/samples/AvaloniaSample/StackedArea/StepArea/View.axaml.cs +++ b/samples/AvaloniaSample/StackedArea/StepArea/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StackedArea.StepArea; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StackedBars/Basic/View.axaml.cs b/samples/AvaloniaSample/StackedBars/Basic/View.axaml.cs index 67c411029..2e47a75ab 100644 --- a/samples/AvaloniaSample/StackedBars/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/StackedBars/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StackedBars.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StackedBars/Groups/View.axaml.cs b/samples/AvaloniaSample/StackedBars/Groups/View.axaml.cs index 0bf4749e0..a1136e330 100644 --- a/samples/AvaloniaSample/StackedBars/Groups/View.axaml.cs +++ b/samples/AvaloniaSample/StackedBars/Groups/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StackedBars.Groups; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StepLines/Area/View.axaml.cs b/samples/AvaloniaSample/StepLines/Area/View.axaml.cs index 71284d47f..0d9d2ef92 100644 --- a/samples/AvaloniaSample/StepLines/Area/View.axaml.cs +++ b/samples/AvaloniaSample/StepLines/Area/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StepLines.Area; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StepLines/AutoUpdate/View.axaml.cs b/samples/AvaloniaSample/StepLines/AutoUpdate/View.axaml.cs index 5f9a486f3..08227576a 100644 --- a/samples/AvaloniaSample/StepLines/AutoUpdate/View.axaml.cs +++ b/samples/AvaloniaSample/StepLines/AutoUpdate/View.axaml.cs @@ -5,7 +5,7 @@ namespace AvaloniaSample.StepLines.AutoUpdate; -public class View : UserControl +public partial class View : UserControl { private bool? isStreaming = false; diff --git a/samples/AvaloniaSample/StepLines/Basic/View.axaml.cs b/samples/AvaloniaSample/StepLines/Basic/View.axaml.cs index da8e1bfe1..6b0051434 100644 --- a/samples/AvaloniaSample/StepLines/Basic/View.axaml.cs +++ b/samples/AvaloniaSample/StepLines/Basic/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StepLines.Basic; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StepLines/Custom/View.axaml.cs b/samples/AvaloniaSample/StepLines/Custom/View.axaml.cs index 688270070..c07250352 100644 --- a/samples/AvaloniaSample/StepLines/Custom/View.axaml.cs +++ b/samples/AvaloniaSample/StepLines/Custom/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StepLines.Custom; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StepLines/Properties/View.axaml.cs b/samples/AvaloniaSample/StepLines/Properties/View.axaml.cs index 2e6a2703b..04cd29883 100644 --- a/samples/AvaloniaSample/StepLines/Properties/View.axaml.cs +++ b/samples/AvaloniaSample/StepLines/Properties/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StepLines.Properties; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/StepLines/Zoom/View.axaml.cs b/samples/AvaloniaSample/StepLines/Zoom/View.axaml.cs index 18572178f..37b4aa21c 100644 --- a/samples/AvaloniaSample/StepLines/Zoom/View.axaml.cs +++ b/samples/AvaloniaSample/StepLines/Zoom/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.StepLines.Zoom; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Test/ChangeSeriesInstance/View.axaml.cs b/samples/AvaloniaSample/Test/ChangeSeriesInstance/View.axaml.cs index e234aaa21..a39ec5836 100644 --- a/samples/AvaloniaSample/Test/ChangeSeriesInstance/View.axaml.cs +++ b/samples/AvaloniaSample/Test/ChangeSeriesInstance/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Test.ChangeSeriesInstance; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Test/Dispose/UserControl1.axaml.cs b/samples/AvaloniaSample/Test/Dispose/UserControl1.axaml.cs index 28f1a0329..1f08a1b27 100644 --- a/samples/AvaloniaSample/Test/Dispose/UserControl1.axaml.cs +++ b/samples/AvaloniaSample/Test/Dispose/UserControl1.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Test.Dispose; -public class UserControl1 : UserControl +public partial class UserControl1 : UserControl { public UserControl1() { diff --git a/samples/AvaloniaSample/Test/Dispose/View.axaml.cs b/samples/AvaloniaSample/Test/Dispose/View.axaml.cs index 846e4d556..7c2f72667 100644 --- a/samples/AvaloniaSample/Test/Dispose/View.axaml.cs +++ b/samples/AvaloniaSample/Test/Dispose/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Test.Dispose; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/Test/MotionCanvasDispose/UserControl1.axaml.cs b/samples/AvaloniaSample/Test/MotionCanvasDispose/UserControl1.axaml.cs index d8bfc5f86..c176ede9f 100644 --- a/samples/AvaloniaSample/Test/MotionCanvasDispose/UserControl1.axaml.cs +++ b/samples/AvaloniaSample/Test/MotionCanvasDispose/UserControl1.axaml.cs @@ -6,7 +6,7 @@ namespace AvaloniaSample.Test.MotionCanvasDispose; -public class UserControl1 : UserControl +public partial class UserControl1 : UserControl { public UserControl1() { diff --git a/samples/AvaloniaSample/Test/MotionCanvasDispose/View.axaml.cs b/samples/AvaloniaSample/Test/MotionCanvasDispose/View.axaml.cs index 4e95b4cb8..e1f9f6498 100644 --- a/samples/AvaloniaSample/Test/MotionCanvasDispose/View.axaml.cs +++ b/samples/AvaloniaSample/Test/MotionCanvasDispose/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.Test.MotionCanvasDispose; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/VisualTest/DataTemplate/View.axaml.cs b/samples/AvaloniaSample/VisualTest/DataTemplate/View.axaml.cs index 28803d5b4..6588f3fc4 100644 --- a/samples/AvaloniaSample/VisualTest/DataTemplate/View.axaml.cs +++ b/samples/AvaloniaSample/VisualTest/DataTemplate/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.VisualTest.DataTemplate; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/VisualTest/ReattachVisual/View.axaml.cs b/samples/AvaloniaSample/VisualTest/ReattachVisual/View.axaml.cs index 016160a02..ff9ff1ed6 100644 --- a/samples/AvaloniaSample/VisualTest/ReattachVisual/View.axaml.cs +++ b/samples/AvaloniaSample/VisualTest/ReattachVisual/View.axaml.cs @@ -4,7 +4,7 @@ namespace AvaloniaSample.VisualTest.ReattachVisual; -public class View : UserControl +public partial class View : UserControl { private bool _isInVisualTree = true; diff --git a/samples/AvaloniaSample/VisualTest/Tabs/View.axaml.cs b/samples/AvaloniaSample/VisualTest/Tabs/View.axaml.cs index 58f2574bf..cfa9d520a 100644 --- a/samples/AvaloniaSample/VisualTest/Tabs/View.axaml.cs +++ b/samples/AvaloniaSample/VisualTest/Tabs/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.VisualTest.Tabs; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/VisualTest/TwoChartsOneSeries/View.axaml.cs b/samples/AvaloniaSample/VisualTest/TwoChartsOneSeries/View.axaml.cs index 7701a7c21..e0aac604b 100644 --- a/samples/AvaloniaSample/VisualTest/TwoChartsOneSeries/View.axaml.cs +++ b/samples/AvaloniaSample/VisualTest/TwoChartsOneSeries/View.axaml.cs @@ -3,7 +3,7 @@ namespace AvaloniaSample.VisualTest.TwoChartsOneSeries; -public class View : UserControl +public partial class View : UserControl { public View() { diff --git a/samples/AvaloniaSample/nuget.config b/samples/AvaloniaSample/nuget.config deleted file mode 100644 index 6c273ab3d..000000000 --- a/samples/AvaloniaSample/nuget.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - From a4a7d27a82cafcf0b67348e3adbbad5120eb696b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 17:59:07 -0600 Subject: [PATCH 41/78] remove abstract modifier --- .../Behaviours/ChartBehaviour.Android.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs index fc024e7dd..b7a5f45dc 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs @@ -30,7 +30,7 @@ namespace LiveChartsCore.SkiaSharpView.Uno.Behaviours; /// /// A class that adds platform-specific events to the chart. /// -public abstract partial class ChartBehaviour +public partial class ChartBehaviour { private bool _isPinching; private bool _isDown; From 99d2be0a70bcdc8a4bdd22445995f0c39972ea12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 18:46:59 -0600 Subject: [PATCH 42/78] remove timer approach from maui --- .../CartesianChart.xaml.cs | 28 ---------------- .../PieChart.xaml.cs | 32 ++----------------- .../PolarChart.xaml.cs | 32 ++----------------- 3 files changed, 4 insertions(+), 88 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs index 2c63a7b47..2d3b5e278 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs @@ -27,7 +27,6 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Linq; -using System.Timers; using System.Windows.Input; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; @@ -61,8 +60,6 @@ public partial class CartesianChart : ContentView, ICartesianChartView> _visualsObserver; private IChartLegend? _legend = new SKDefaultLegend(); private IChartTooltip? _tooltip = new SKDefaultTooltip(); - private TimeSpan _tooltipCloseInterval = TimeSpan.FromMilliseconds(3500); - private readonly Timer _closeTooltipTimer = new(); private bool _isZoomingSectionAttached; #endregion @@ -107,9 +104,6 @@ public CartesianChart() _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - _closeTooltipTimer.Interval = TooltipCloseInterval.TotalMilliseconds; - _closeTooltipTimer.Elapsed += OnTooltipTimerEllapsed; - var chartBehaviour = new ChartBehaviour(); chartBehaviour.Pressed += OnPressed; @@ -690,17 +684,6 @@ public ICommand? VisualElementsPointerDownCommand set => SetValue(VisualElementsPointerDownCommandProperty, value); } - /// - /// Gets or sets the interval to close a tooltip once the tooltip was opened, - /// this propery has only effect on mobile devices, on desktop devices, the tooltip is - /// closed when the pointer leaves the chart. - /// - public TimeSpan TooltipCloseInterval - { - get => _tooltipCloseInterval; - set { _tooltipCloseInterval = value; _closeTooltipTimer.Interval = value.TotalMilliseconds; } - } - #endregion /// @@ -879,17 +862,6 @@ private void OnSizeChanged(object? sender, EventArgs e) _core?.Update(); } - private void OnTooltipTimerEllapsed(object? sender, ElapsedEventArgs e) - { - if (_core is null) return; - MainThread.BeginInvokeOnMainThread(() => - { - Tooltip?.Hide(_core); - _core.Canvas.Invalidate(); - _closeTooltipTimer.Stop(); - }); - } - private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs index 70e905962..977494d68 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs @@ -26,7 +26,6 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Linq; -using System.Timers; using System.Windows.Input; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; @@ -55,8 +54,6 @@ public partial class PieChart : ContentView, IPieChartView> _visualsObserver; private IChartLegend? _legend = new SKDefaultLegend(); private IChartTooltip? _tooltip = new SKDefaultTooltip(); - private TimeSpan _tooltipCloseInterval = TimeSpan.FromMilliseconds(3500); - private readonly Timer _closeTooltipTimer = new(); #endregion @@ -89,9 +86,6 @@ public PieChart() _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - _closeTooltipTimer.Interval = TooltipCloseInterval.TotalMilliseconds; - _closeTooltipTimer.Elapsed += OnTooltipTimerEllapsed; - var chartBehaviour = new ChartBehaviour(); chartBehaviour.Pressed += OnPressed; @@ -557,7 +551,7 @@ public ICommand? TappedCommand } /// - /// Gets or sets a command to execute when the prressed the chart. + /// Gets or sets a command to execute when the pressed the chart. /// public ICommand? PressedCommand { @@ -566,7 +560,7 @@ public ICommand? PressedCommand } /// - /// Gets or sets a command to execute when the users released thhe press on the chart. + /// Gets or sets a command to execute when the users released the press on the chart. /// public ICommand? ReleasedCommand { @@ -620,17 +614,6 @@ public ICommand? VisualElementsPointerDownCommand set => SetValue(VisualElementsPointerDownCommandProperty, value); } - /// - /// Gets or sets the interval to close a tooltip once the tooltip was opened, - /// this propery has only effect on mobile devices, on desktop devices, the tooltip is - /// closed when the pointer leaves the chart. - /// - public TimeSpan TooltipCloseInterval - { - get => _tooltipCloseInterval; - set { _tooltipCloseInterval = value; _closeTooltipTimer.Interval = value.TotalMilliseconds; } - } - #endregion /// @@ -739,17 +722,6 @@ private void OnSizeChanged(object? sender, EventArgs e) _core.Update(); } - private void OnTooltipTimerEllapsed(object? sender, ElapsedEventArgs e) - { - if (_core is null) return; - MainThread.BeginInvokeOnMainThread(() => - { - Tooltip?.Hide(_core); - _core.Canvas.Invalidate(); - _closeTooltipTimer.Stop(); - }); - } - private void OnCoreUpdateFinished(IChartView chart) { UpdateFinished?.Invoke(this); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs index 07bf1c4f8..76246d25f 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs @@ -26,7 +26,6 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Linq; -using System.Timers; using System.Windows.Input; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; @@ -57,8 +56,6 @@ public partial class PolarChart : ContentView, IPolarChartView> _visualsObserver; private IChartLegend? _legend = new SKDefaultLegend(); private IChartTooltip? _tooltip = new SKDefaultTooltip(); - private TimeSpan _tooltipCloseInterval = TimeSpan.FromMilliseconds(3500); - private readonly Timer _closeTooltipTimer = new(); #endregion @@ -100,9 +97,6 @@ public PolarChart() _core.UpdateStarted += OnCoreUpdateStarted; _core.UpdateFinished += OnCoreUpdateFinished; - _closeTooltipTimer.Interval = TooltipCloseInterval.TotalMilliseconds; - _closeTooltipTimer.Elapsed += OnTooltipTimerEllapsed; - var chartBehaviour = new ChartBehaviour(); chartBehaviour.Pressed += OnPressed; @@ -597,7 +591,7 @@ public ICommand? TappedCommand } /// - /// Gets or sets a command to execute when the prressed the chart. + /// Gets or sets a command to execute when the pressed the chart. /// public ICommand? PressedCommand { @@ -606,7 +600,7 @@ public ICommand? PressedCommand } /// - /// Gets or sets a command to execute when the users released thhe press on the chart. + /// Gets or sets a command to execute when the users released the press on the chart. /// public ICommand? ReleasedCommand { @@ -660,17 +654,6 @@ public ICommand? VisualElementsPointerDownCommand set => SetValue(VisualElementsPointerDownCommandProperty, value); } - /// - /// Gets or sets the interval to close a tooltip once the tooltip was opened, - /// this propery has only effect on mobile devices, on desktop devices, the tooltip is - /// closed when the pointer leaves the chart. - /// - public TimeSpan TooltipCloseInterval - { - get => _tooltipCloseInterval; - set { _tooltipCloseInterval = value; _closeTooltipTimer.Interval = value.TotalMilliseconds; } - } - #endregion /// @@ -831,17 +814,6 @@ private void OnCoreUpdateStarted(IChartView chart) UpdateStarted?.Invoke(this); } - private void OnTooltipTimerEllapsed(object? sender, ElapsedEventArgs e) - { - if (_core is null) return; - MainThread.BeginInvokeOnMainThread(() => - { - Tooltip?.Hide(_core); - _core.Canvas.Invalidate(); - _closeTooltipTimer.Stop(); - }); - } - private void OnCoreMeasuring(IChartView chart) { Measuring?.Invoke(this); From fc6f3ccbfe5272bd69315c67f9e7c205c3d8f075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 21:21:48 -0600 Subject: [PATCH 43/78] improve zooming docs by platform --- docs/samples/lines/zoom/selection-zoom.gif | Bin 0 -> 164146 bytes docs/samples/lines/zoom/template.md | 89 ++++++++++++++------- 2 files changed, 62 insertions(+), 27 deletions(-) create mode 100644 docs/samples/lines/zoom/selection-zoom.gif diff --git a/docs/samples/lines/zoom/selection-zoom.gif b/docs/samples/lines/zoom/selection-zoom.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb8c8ff2f09037d8c5e7d88949eb2db711a0675a GIT binary patch literal 164146 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 we8-FsP?N|J+BJ46CL< + sample image + + +{{~ if wpf || winforms || winui || eto ~}} + +:::tip +Right click on the chart, hold and drag to select an area on the chart. +::: + +{{~ end ~}} + + +{{~ maui || uno || avalonia ~}} + +:::tip +On **Windows**, right click on the chart, hold and drag to select an area on the chart. +::: + +:::tip +On **MacOS**, **Android** or **iOS** double click/tap the chart, hold the last click/tap and drag to select an area. +::: + +{{~ end ~}} + + +{{~ uno || avalonia || blazor ~}} + +:::tip +On the **Browser**, right click on the chart, hold and drag to select an area on the chart (no touch devices yet). +::: + +{{~ end ~}} + {{ render this "~/shared/relatedTo.md" }} From 50b95843de903ef1776fb0ea394c849616818ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 21:46:25 -0600 Subject: [PATCH 44/78] explain tooltips across os/frameworks --- docs/_assets/tooltip-custom-template.gif | Bin 0 -> 152064 bytes docs/cartesianChart/tooltips.md | 14 +++++++++++++- .../samples/general/customTooltips/template.md | 7 +++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 docs/_assets/tooltip-custom-template.gif diff --git a/docs/_assets/tooltip-custom-template.gif b/docs/_assets/tooltip-custom-template.gif new file mode 100644 index 0000000000000000000000000000000000000000..5a40c64d637013503d310248e9ced2ed33aa24f1 GIT binary patch literal 152064 zcmd42byQn@`>&Y<_XKx$D1~4_ic7FUf#OiCI20&FTN>Qm-QC?5i=A1RMX3f2>?0mELoxPI(zU#BETTw{?CSv9cq5ygV01OW}&*inXWTiFa zp**}OK)~avYgAN>$9L|>7vQh963QpSRJCIVBZUWmR(( z*C7EMc;WJsG{~qB}IoPp+*dbhUS4D114ZfnTwy3SWU|_gnX1ZfzvF~Dk z;N!j(?7x~E|E(Z*uB^DfqP(H9s;Hvrq(?(pL7`1jrE)!pUQ&GpsQ-~7IMTs+pz?e)!L-QM2a{rPu2 z-2b1}!^8jN;{E^p>f=rSpEvyT%l?=5`OhEtf7toI{QCc;hR0^idw?VsHM};rI{=f2 z(`cwRuQvqDq?`$_%kPgM=eJuLsw)_bp_dJ(R;n)?PGHw6HyW-l8cpG~7|B#>C?3y% zz1?3LZYcShBNc#6quf|JSpZMqG#+Uzn=a8PP|i|rDxa;;Yq0w<(o`{DW7-=|W6vMt z-{3M-Zamst_1({EdfO-o;^3#*`W@goM-JYv(Kqa+V^}}Q>rT6W3*wixs6@k-U6YJRI8Aclm ztp!oL@0#i0CH@}v^7&x19>&fyD`mw}yt^L3JHWmXDKKZV5e3^W-G~;y+}((gLg(0w zl_Ry?jDxe5ZN{q#?QJG#C~#~gYU|i;CFxm}Z6zDI?`@@+26JquS|;0Wr`Z&jZKpdl z?`>x|4{+>cy3N_{WO;6v?PR~d+}p`Pcqa~0SP|Rp=7qAB@8*YZLv{;jwi)^g6LswN zic+o0%fL2L`y4?Q4xIa?g_?&J9LiSakti0{3 zyXKngYx*>A>}!YW1s&@8XfqBQ%%6;M*G$ORJL*n7SFvxJcaM14{H=bZs%7&znp10Y zaz*vaoqVqS)`Nix?T%k|*fpQ7Naf#rPF>D8`Xcpnw59?;=8)KhLS=v4Bg2qc3%-YP zpQz%qQJ?flG?{_0m=m3QsD^dKkNe4YnBiDd8o8$<#Gy!qTE;UK*I}WiZr~`aLe-zK zZNTVgOyH}V%!FJEH)gd&2aX$(x9Nr3BoqCg<8l@L4;s{50<~RpMjk&e=1oJYq(GJ_ zSzY>88C6mX4lOi7C{GF%6ZEZzjm@TZbsPonrMZb$f3F}gc&=6h$(*j%LfL3xxZn}F zpQUAb3Vsn*qP+c=dB36xa6E=W@y8=+Ezw zFR`~*oA%j&OL2R*Ws4l*0;veBS%!zZ^Z7Rqf39|F9`5gcA3Z!wT9DG-D|Ue>j}e%v zxgfHkE_BgjzZ)&7YgV{)Z`m56N{h~Wm9V{|-$}cuV3C>=-a~kU=gYnKLyC7g4?xNl z$Py8NWet-i>Dqjk6RUwEc~!mmOfL9d0GIKX!xiCJ;g-02K`c(jmTU;%MW}`<4J0Bp zjhQnpB*UL!Ae+3O$J{C0(7?Q=5yr>keG(ahQjpvSuVNMIi?oR>Se;2_5t<8+Bn&8^ z{;dZPH6M=t?#d*4J~RlsIZ;M9kkC>n49R4l#Of#)wxYJhDu~uc#8$>LmnkR(>7B-F zj4>w(adbR4!ApEkyp;&YlF?$^OeihP<1FeMp>3a{uZ=9ivZg39usTU@ohf4Yys6>? zY@lx=wnFp5Dl)&>PeoNKhT6kbxhaX#x6_Kr(yp1UFS+>qVU%%&W#cC<(@M*qW*F<% z(FvC#L6qd(qyBOeuK0E7bN6?wrpg)ukS-wnqOs)X#A2Zv;o(yzPf9e=V|6+-?c8!E z_5@smvUi$6IozXCBYLdeGT~5 zkIHo*MXfWUMOax`@a(2km7h(MCC*KgG$~w#!x@x)dXC3UL=Y1wIx|WlsH7N_YD_#C z9HqI6_k7D1LkAt&b-q?GY>LSTGaZ*pK%lMWKUK zI8-W+;OK#XFJ-##QHpFG z;>wd@v8$j87C&^IV!xRFJUj-|MPC;Mf81&oZNb^(cVrQ)@Cjujqa)g62`Q&!7l2;e4g9@7KrA?e17=Ts+NNS{2a|$BjC-f{o1f= zYfLUnHMTZ*6NLEfPAfzh`b9IOsM-M)j|NlWmSX}2)2}@Xba8haTvc1kb>4S;<1Kk0 zOx;U1gg|+EA2(eIVjlJA^dt!%ceeTw5SnU(#sk-Nu>v*qEu>>B7^eu5>~__y;yI@t z_&i(&3#GIT*#$Qih}~^33|zAXrq++ZoI&%f%=oNeAO;NVPxuAe#m(iHO!U5k-gD8} zb@n(v?7$F@KOL<(`#7dZZ!g`Xo$U<(IH9uykxvDna5MRpbe~#tlX|~h8c&SEVVjrN z^6W|AL8Q(ev^c(67|+joBj4d~es8tN;i@Dm1(y^7u1KWYsL5TN@bSyVvE|dB`HmdkI3D%RSHH3Newn~vH}xXV z&n)jpaei%4W_Ic`1SasC`oE4q#rG=$U@=bEEzw9}B<1_{W3ZVivbMohs+FlVs_OAl zub6q&FLb~C>86g2sf$%J`igV?mJ#g(r!)D%hz$63;aSsHW3!tXt7AlYa_zosySMf- z_$?$wB8YQmzy3*dNY!HM#^6x%Hn8vi#o@ z#IIz?cqaS(VR0g_8-Z%*w4Z698$LPj|tilI)`_cxX)>RY$z_0qWJQWh#d5hvW! zz&{?oyDcJ9J4`dW#62xuiXlYdQpTJGc8!BvPrKf8767?5P!b4H_!NNzt0;*w2sF6% z=VbN67D61%k9aoFo=Z)l1-8cpFrfzoV*)XOy+M~C z1q6pEEGYCX0=!1fqb_S}b;3Ebd|~{&lQ=KL&wF9I<{J zdYLyD(MQs@IO@e%7w}s)M655u_>2V278wWP2tK*e4MzGCBR{6O-p5>#!#GXj@Zup{ z@f2w%A<1#!Fuyo1rjN2G=<6vTtejnoT_NW1V9_((xhs?m#svOrVP|p(KtCkT)1P52 zh%+FtEX9Ws5De-@i`!)<_4_Ej3R>5V;F^t6XXn)Pf?=%!2mnCvF#ylh{UsJe*Ooy- zpD3vWN=BckVD_Gx*T+yJSy_Y=YU&r@335b0xdQ@Tgo)vUfg(geFD(0R`FH%2DYV3a zvXIn9a+32BDDAO(PHZZhbuvkuCyY1Zc`KBgm(xWFR<9(0uK|mf*Jo6;^4rjtXU%MD zND)0vfdV~?C`iIrEg3ZQK;7x+JL$v>?h;*~3J<@w`!s$6Db5xS7=9O&nis@G@0-D4 z)FG(biDncS@Md_{aHz;7!p1cpi`c>1OB;f@j2Tf;mTDcw@w7{q^9&$NkIIh>yxRg* zoMs^s0NlOF+{HctC??MoO@cNY4}(k^gmTbybL7e262eLRS5x`tbE?`>lL%3w!_qI< zQJx$F2)aPL0MyE!+>b=rjaRxQUfIbcX5H@`{S)lJ1lg|?+iSNf=wlJPAc7eTNR(Qj z<*Zrj3Ry%D3jsuK#wDmam`7+|xM2av?WM`tkRgy}A?9vE{@cRdN?(@MR?$FFX`e_X z-N8UQk$|)4OumQ^!YPLEfh7RB0sa?LMfYd`ASXYF+ZNM6*WI7UiV{21N+Bt}xmf11 z_#<(N_zMgkj<=WABph&HlUF{eG&(oEFN#4fifn0cxp`Q7DM_$Rc(X~QkZq!!rQ?WI zayUG-oXEenj0st$8|P03K*<+{1UrL3-l4o{IuCyDuNS zFa76;n;?8mPkLi4yFo`7<%Z$%Mq=PW%En5J*XBb-tV&$ft(Mhup07Ooh`g)5aQH>6qY zNvoKDyARW+2#E8&Gl*rC@AXBYwtcMwL)OC}lpI`|7LUSGtC-8C^GmN5tRWpWS;F=G*W4at|;HVLQ$7Ey}%s}75ojl;4?$+iwNJ} zhD_ID5UDhCur8S=Cn`^@4+>=)G`6yFkyC6H#8CT*a~jB+n~n+T?t^wCb-M*zyCG}7 z4Q<`jksP@p{N(H?cw^8fyqwRDL3Dr~>RI&7b};V}7j(==K%7bF4jj1}Rb&Oy)yemm z>`nlo`f_%%zXa(;@{byD$iMG{!a*maeT2eE;#ZB%?u2tg$-%MyYVE!0P!y92XlcKe zPcig9Pn1Kzxsw*r2VCfR`E9@{6ZV3eN$U_?q6Ernh0-6B898w9*5-#&>QrEs5*!1W zsS(UlskoDUpHBM<=ZE-Chj3r?OJD2y$NKQxk)}9sNCQwR*ka6PtJSB0-1I048ZG!{ zBTfDzF(o4keC*b>V`EEW6L(`s>Tx9Z7=c-@5B>PW-E%VMIx~4pzo7AP)p4B{qbcTo zQzSYt6#?qw(ImzR2kPdCyI_9?4)l2rGM8>IgkE9K`+#fRcU@3_QO?Ull1&E=F53vX z0w5iIL8}eNuS#&AD%U`z$B-&90$oHttNbdR!N9bwyixN+*etT@ycu}kr74u=O8!H zP$6jgY2}cBF-+(QG3ysQp4Ta`2s6RMih!$8u6ZYMlIMsZx)~vMj{JPaVvEO{YIjVP6 zkG>(7?++5VF^Bh^0Jbuh#s@I;b8cwX!rQEAvCs98?%DKw)V5(D^thkv4Dk9BXUaH9 znlZ<`Z8=?T=Tpap388P=#^3Zld^_-flt*z$Bj$v7IV8X+JY7>FQru1VpGjIAM<>Ro zMt^YSID+$jW_5kA=rNw}!)qF-;us!>(t?A2L4O#$_<_>!1I#_UVr;ecV_}14kkn-< z$#t1)188ad^e~I$*Z9+8HSiC|jI(Eo7tdZrKZC?Nj<)TsU=gkA@vUBHuAXwOoK-DI zbuZxht|aR$gQJ(@#CVB)Nl1V3kn?~s@Kdm!C*aT;;_*NTBslJ((pj9=t&A&Y%hp!L z*Cf~0p!n;Ztm{IwYa-PfAICSsaKApq-;`k36cpTmoU95z2hzrFDn~EgU#CmpFKH|j zX=bZy<3nP{zcEk9vPn!BFK^Vn20XnNwgqo!J>O*2TeewVF_2ih7n8{9jFK1o{li0Q z$I@xX)_%z=dSk9}`(@nvZvA==ay=jF_!J){fNy(FdwX_lx{PM+p=$d>b*+iSE5GQ4 zY}ws3r`-@Ah)vb9Uf-_v+U^=?FP?`Jrm-(Tv;AU%tL1K(?ilbCjBL!`!;kw?(xy?G zu3jraQeXX~(aE_5e+dgAgYer+KL!0P2WCAxET51qDzK$Npqw=wYEB+bpB}QcfN*(d zagZSKYqGg$4(}}f=bt(ImcgGYY^jlRBeeToH#>q`?C*}zQC}USe>}!~g)UTkjJtA- z|8NYZJ0bjXY>PN1eRFbjPk0bOYQD^Al4UM8&iQ)+Tx5TrdbfO}@@wZ|c$3f!-T3&F zm+lNIc_#4cOz7b>)`aL6Ekk-Y(TNF%Xlxb>5tp$G!ARi}zH{=j#f;UYPwF z^Z&*93c~a8OfTocAm>b^PFn2bEU`X}taLQkIR~-C$@B&Mark`E(OH9lMDrE5_S1c0 zmkWcBzdZ@gjADpPYKTlFIn>~TTrZs%qs|S+_pr>~dzG%#U0kX|e)mCtKR7|$bABhs zT=={pBIp4JBCoR_u5;;b@+EHykFIZ2IZgVo;N49bLo3F9W-- z1cNY|R&F~VZoBC2vU1Q~bKK>;I#74K%YK7yguI)$f4D=^{h5;dGqZB%m3z1FaINwQ z!aM~A2TGMla_;M3aJP9wR5(3qrM~V;1}~tW%A&o#{&On%a1nrZQX^&R{D5VNu8(|p zjEw%C?Ja6`cE{@a$lUMh<$H6o$K?mufg|EM ztroT19X(7nGPBgGu{AK_)!N=g=vevZd^hK?&JUiDl9 zO#1nd0zxO^<2JsaeZCR)03)p;HhJhhbRu#4&}NwR_aR7K_@U5Axl|K(0xiqN6Cjnr z)44&CJu``8 zk+|0vMR?2fVR~XwMa|8Y^NFMdR*N4Xj|}BZuic4-IddNP3|>mbM{A2#QdTEzhOZ+OKXXr(CP3%GNu`+S$Hkj`x7Q?S$a+ zVEtr5Avol0jY;e{D&I%Ha_Tsn^AW73IXXX}!8wUi>E$8+?06)KpYD}?9KAW`pLr$&{~k-wiVN4%XFBf4 z@EcrZ60c=fSJ=&1k-rbGlb~p-F>DN22_jr*x#45ijqF-^f2r6NaYrB`VG8_C`Vth8 z*^hw8n1aaIKerD>e>jSuH{2BNKGUw1YHPPnzVEHNr1)I>V+(BE6a$pJp_(-7YS+VE>OZ03xB{m0l!O%#ZiE6STj{h1R5G$ zSgtbh3*Iko;t;d2x1j)q)A6?t%7sW5f-P&|8MX9DEES_z6avH7FYBdJ+;mulu~I19 zi88g9K>@UMz=iQGM7GXNxXQFI{AzEwQapS71wI^g_Xs zgO8Da(!>-%s8gXrFwI!`Ut0$jV->ZjT^JK_X=D}Gr0?ZMW>(&{qfRQ*-`VelGP+5sSKwAlk?&8MN(vnv z3%tHJ=%rXLR7JQ;_x^bA?UAyIcLWbrAw4y>tf@qu!0<(q?3stROSnAkS@j{k4rcZC zY&c>)$ykX#^x*#Ub5(D`J{1FC#*Ow1uJ-%wv^q1nDGs_yfZEyWu>4gtQSq??_Y%oH z?n5lM**O9ox(Xy6O6+QuCl6CwdO~b1-yiJ-`tYPo9WVy)<&Abxuo_FEJbEWdza1Ld z!L)f`m13!6Rd;K&ga)AQ8g2@3O>{&V`xu8iDk55|6kJ)xXt6b934Du#VMwA@jRwf! zd^!qSDqGIbSLZV@As&ZRKaSQ46m~^+^nLJhe zmR>wiY{U~~``J-+BufXkMe6f1{r93t7w<+VHb=tuJYHiJR!tK|G!}YfTho{-=ZJNq zc*7cwd4t7warsruvjDM$Q%a$r2(?5D6z;`jeK(!-XT{coF5j5;E}o=)ij%sx@Ilgl z6LPVPI@Iv6pTXvN7r_!`SE-#oM#Ul5p`P^fZs1np?9%;n#Oni|!QV@6-k#az<8h*x z;s!^>bQw_rHbFTNYlZHxFIAe6Zg1RvP=^Kd?*yHoQi!wv_%+w^H2?MC(rw>0DZd_^ z)+PGt`!@=|ULg8}D{9+&Hs1NfF-hsO-G$5{*hkaUf_wW&2OK0uS36Qo{`i>khdgGC z*P!vG%liA{p4<%41a1fV!7J=rc3q`?g_+`lqk1n9=>xCB+>D zJ|I?Xa$d`Ww<&G8k@R9YXZd&8k=V~a)k13>&WKoQ`d`R&G3yy5!-eU6A&41C}F)G~y7Vk`vu^p`CXfcy&d_O2y}fQWSPmI$#RW2k;@gX*RoQ z&%5bRW$2hu1Zt%z`?~4ndYH9)7`S^V#AR3ld)Q~BSsi-9Jnv;V`g-V@1NcjO!r%eW zp&njT8J@$Q&?^}}IaylfUg-N!aaaHp(F;rL6)Ef$ZIl%iKw-4(eHMu+yAVkhDTPTL zmdw~EBhV)+*C(glCvVxO;MS)Y*auJSQ!4CJZtPR(>rImoTwuUL zZopD|;I-v|mD_-I;DAlyfNkM`UE_d#-+;r+faB(X)A_&~)In$BK^NvhSAoH|a)WN# zgYPT{-Q5N~0tY=4731K31bbQq*_R0hUWiWFofMi3G+35ivN#BM_3^doU+k$783{0k%j+9a4{ z62dY`$P$M5TUi2P03HC`QKPQYuz58g?>zE^=lb3N}7UP60}8Au1kWs;96=?}>&_ zgpN;yflq{qPlT0Ego97y2~-3M6%mGti13Su@xvqpM5TnprG=l#3O|z*5?2rsQxp_c z5`ZZSJf<};RRNfq0POiAf-r4Cn4TcaNC;*s1hWx_xx-+7BCtqNSc(`dM;uoC3|1up zYmgLamlElf78#Kdosboslog$p6I+xQUse=fgFoAZKigK4*nKX$|3YC;6TYjdxcowK z>bd-&I=u0PYMz!x(o3yyT^&C?eRl&RCqol!BQtYjb3>EYINXoZPiTeR81X} zOq~=>o#jkjrOe#L&Af%peECcfT(1JyUWG8f3THBnVlYpjw@Cb(Bsz;EI?H4_%M`lT zX>`_^^tQPSjzx@b%9-5im^|B=-ghzi_A?=dnfynY1IAec$Jv9%xq`=^hKxbO#)QI0 zVG*OEk)vXfqtBwoBx1&;;*in_)3V9)@@d}{GFRX^n@ah+%0-7NB}b}dr+-m?ruH|_ z%TLwIPBhAnw8{>3O83l*mmCX`?gazB`JV#wnj`Y+;`6JL3#&3ps&mV#iz}+jYw9X% z8>;J@YMWZ>TiP1iKec@7Z2A19^>bHiXZL?->+Ej(@<`ABp7yTZfB4+f-`O|VJuuWW zIMO#fIxsReI5sgf{&jc)Ir?>S3^_GEIX(WUc1_KEot{O`%uPNrJ3sX|({l@t%*-#$ z&M(d`EY2-_n_K)g|2GSZ-xt39#p1W6#qUes{^tAAk4Kh%EdN-3WMz5fu~t`C*Vfk8 z*EcpcH#fJowzmJOo!#Bt{r&xegM*(xe?IzS$H&JfCnu+;XJ=>U=jRs}7nhfpzoFyM zM`h{Ze^8dpOYQ|lipsNk|D`Nh46^o!|E(-3`Kgf#op}7EEV1f}sAB!4EMY~M6^1of ztN0YvyHWg0SsKxMRF<@gl?s%j(t~Eia#-Zeex&met5j1pA!xqWMo83?)#VyzIFIT! zWBPSx8S*k32N?cZ#w$o!eTMg8&mHIPhG-S2x9cz<~zC1ec;}vonz^=5wWR zgH?6rk@tP1pumsGLZ9^P2+@o2S!ctJYOIW^!^NleHJ_t8ikuoh`DEOw3AH-M_YG1? z@<2rvw#LLncd(z`4D1!Il_+x=FsN(*#c}K>eM}l~OO}PH0G7!Y zv2->zmLpKo>a8^;`shFm8J5fDe5EJei3&2lg$rOVYK3ijC13W&0eMQyf;GvWUCeJW zj2yPHv~qT)X5vcjLxqaZNwqg*Gz~({lFN-36xgwe3AmDfE>6<$S~ZTv6_?uBC_0Z_tJCp~z!zx2`P~DQN!Y(x zl{9&GCrg;H7|PuO)4ccJl~s?}nchpamP5)IvpDQMW0tXBRkzO#+SlCt!9M)hgRf#* z*E_ZUB69$pio9W*@YbQRw zHq!t@J@@q@|by++>R*Ef}T%zXhSP(z)kzQiBUi;I9qp953K<4-J9cG8NQY6Cd87c__H@C%%yp(lfYJIH5!h z#JPOl8HWKo2J{h#jdd-plM60$?UAKbbM51o`EniLwefHr;tv1f{E4&J$@vR=&zJKE z>zar27!&I&{RswzB>gEmN6hL}gY3tS^A4?tj*DK4kDo3_-#&cWo`lwHHKT{A$DUoM zNrG?A%btR7kJ=PZ{Z5L(-9!Ei;QZ32 zLY0;lMo*Ag3H8P7#|kF#*Erv%8Py2JRD4vHl95DV@H}kYp&ruq;~-wuHEvb7EMy%cUfI0W9uNO=+pSIs9(8R}ydJqgo@%qK2^_j4MYgzJsvleP@? zKYB_Lrnm*`CRBI2>qD0^Mzl>4ESN?*wdeH#_fRlp~4Oki)>pzAj?Mn*~m zk{USWJ;uC3kdnF${MUVf(&N4W1Z)MAQ1CvZD5riA+ z$-Rh>k!zHGHZ3bYEB9;xE&^gdtkbg ze~y`7k&16E+`mIAXizL{k}v89cfvMD(jj~530vyve}y&m^dDIMy?Fe{mi7;SImiEj zJ?)I+Z#dJ=IMe@M=Fx0^ggfKxN#Af-E6=s7&R< zW&hggu$s}hs;<k_4Q4y4b9!nEkjMsUt3xh zTAJ6I8#bF8w%c2`yT5D?4D1XKZH$erO-!sKCs(ItmZsi+4*{?X3<;iEx*baHlnad~xp zb9Z<5AD#L?i~r+&!QU$L5HhDf;-3A#sLY;_oEH1}`tc6fzf@*78_1F%1{#Brg~&fD zGhw5rni;AyY0zIP^PX%zE{*5tZsViMe4cGw+x0J%`6s2c-(rK!v<~^B%B*X-=4q0p zGM^m;MA^MprROPI{-WB;(1mlg!`~J}G}tH%t69&Ux|7HjKdrVH;e*f*jHRuMe@YSS zaBx4$-kl~)@l*KeD*Ji9(&FhSDZOU+c)a5Qsg0K~93|t!;IAj2n2wkF^@-H0Phc;% zN9<*DcHeuSBj@OJzVdjBc!Yfaa&K|T<7;+x8Z%s==;`~x?BW+rb4(4H#0S5#qgPEI zCBNL4-%akUd{jdtUqPVqyw3H(WM!Z6KM>rd*8u0Utp!TF)LRZBpD4`pq;@Bt4p|9e zUsqvvwO$WxRAe%aT1oe1 z{MPkUKgqvUW|kxjSlbIAMj!_w1>G2cXVa9Y#F~y;Hw;N!Nov^2bemXYaVNs+0^)FE zGWTS8Vxx|W2WDT#Sdfjq?UtSbQ%>Z035tF#uv9>0^JtqX+bh;x8h!z!JJ#30s31XA zgIVF5?n| zL+-V@#Yu1hjwaJORHg3SSwj^ys|Hxy@)*a9CDM$MVOhdR_Jf5+lw3~Z{H8qR8jDjW z9FrDCUn-~8jpy3G+Az@W)S+kax7&7W%x5tTO)Nyu9fy=vU7$&>5!4a)_Xic-ke^Dm z()8*T>^4(yCU9T0{-It!(U-`&PP{!k<3ZZD*ibn}w#GBGs%#FviUcxbLzwC5i23K_n4^0*l4N z&_Xr>K+SzqNalwM9yl?j3hZ|+J$xwS{J-yGq<~QLJzgd|!=Z@NFru4qfI|R|T zPX8gTK3fY7Fs+uN<@H7822O-$HB3!x97`^P%TJ}6*zV%Sry)Gv$&QL{0E|A22bh4_ zt9~)J&IjM3lc#Cd^QU8iNAHuO-oZb(&WX{<=oj*{Uj_b%_|=W_zz+5e+z``~m@&}c zjlIckAn^V+{|XC)iaJ^I;TFq#57VQNY@9y^jH=Le$ z-b=kyAE<{=is1t$oN_=qTt<}LmM42?rz|JbL*fTYlRC?9ndVS{5=zfqm?1y`!)}rdx{u@FZ@&+^I`H^@`CGP5Y$9^JWmUmbsJbfyj$Ue za~BFBCpegJQ(N9}R?0G@!r+JUOTLc%#q#U8jBVl)u_DYhC?dgM4uDFF01&MW0kDx+ ziRjYom~>tJJ~JDXs_(3AVz;XO3vqS5GUoC?K2HiL3yU9)_jNfa=fYMUP>{@+sN$w9 z*rkGbc(H)jD>svYq5$e53b+uVf#zOqMGfi;z0+S!^>u%$n)v1KE6vGNz78n&y`ozv zm7=Ea=k_y2p*lv83Zd!xgX#0$J;4M^hH?dRjOm>#XHVIr2&6J{H3uXPIoM{XeOCz7 zWr*#PW{vGxA@QKcf|m-*WQ+z9b}6wQ7@AOTkrx;{w9gAxzOSc>!*wRBr0x#7!*!jz z%hILa`$KQza!v5b_xSSy&_G#tLwIvh*Xk;3Q2~5QfOnTtN6k@Tsgx>7vad@&_{Y@s zJ5G;>)z3Fx-71qhy#{r&uvb*uHFDy2W{%#vOaw@&unMO!>pq?7lW3o%A2Bcl$dDWwC&@Yg5pGJGcQJ7PdU}U>FbzwGr1eKHw^19= zh(`yfd?@K~%!sTtCKwsNh{5P5zVV6|^k zki`?iMZ2y_hOP@vr5~|mGF3xpN(gvH<^1$eGde4CC|XjMvK4>dqDVkBbw1jOG&`GeI4*lk97EJP8Da>-JKJp)eHEeD_wZmKJsWgf(@Olsp za}7VRy?%dLk1F(fDp!ZX8d|1~)fXtRz8`k~Fmh~UWkEGB^;?n^Ig%D3w+`5N+uyby_cQwx9vv(oVo{! zn?5>wz&@hWiJ>$E$&jw@8%-xg@bUHPvk73n%(}P<-pV&LSJ^3Dd z*T;NdU>$RD5%KQVuN1tyFb;oQXBrSh3b_CK!(fTeaLR{K5Ab-1eW3@qSXh)T#XDsX zg2QfyX9FgH8)3kFv24I3-4pzZ+qmmW}tKstrM2h%{>t$+?cDv=#R<*Qe!yMYEW zoC4%jB!EEaQ2&BrfAe5ewA!Fb2%bqP=dKJ^+-7BZsqD&k)% z^FqWvlENNt*b*9{ogYEf9nt@{$~-tkG2E&*Iutok3PHl6man2Z^`cT;qFyCMwYEkP zPe!e_Mo+RwC%(XLN>$#4LF&39b>i_m*fDQfW9}AW?yq716tOp<_*v4}C!xxyZIIYa zrGHfBY&U%B6P(u?aim^xrVClLq();_;O1IOnf$8OoSe3RU)nPt} z#pJJg87cayCzu(*tQlC+8RcFXFXJ-IS~E%)GdkN+y7VJ@IIQ}@zylQNLwm#{_g*0- zi)m%onfVl1DX=VAoh%HOtmL#TwYn@ny_9cPS*x~@>usT%`sUlV;N9WW{bAxm5$_)q z8OIbkw{66K!oq%eMFX+3QOb$Y>>?gSGO=zlaX5+bIK9U9vL+~U1hC@muXAT8@;XKG zq+jHf&fwD;WYZgDFk%xkdn>bg=K<35C@Hh4y$J%=h=mzf8*?6v=T=WYL@JBH${4{kP(#t71$)A=h#aH%{=qdw8;^9mMAw zq3(zS1yIz_fGyyLAn03CNO-9OCt*Z8SbI$%Mwu;6wCsg`S+Xc$S~>V@9bc9xTTXjH z7khaDC1DYEiEP~4vUZk=k@B_FV)B!6_A6$Y*qt#%ph?G?XcOB)yRitWJh z43+vam96{bWG@It?83%4E4uc{kl`#-Bjq#RkTd5hyWNU(Z!q^{mF{Vkws&QR9pn@M z7`02?39r7dCD>1ouujkZr5xss4FGV}JWke)-;~_P*1YVg<~Jz21Ot${CDecl)QYNy z+A?y#+VR$!o3aYL1E3ct0g%3K@umdSP54zbEm5QhC!?6=wvzw=rT~EJK8x1x8q~4g zQj=%YFX>f^-#`H1;?jhYHE=z@N=>nMgOFh$dqpkfO%XZ};KERQMwywuPo~serBYER zk4;1m24Fasp{O*FOqMEB6&f5AW#!=r*%CnfAc5iaC(g}pun4mJ@EP`SXyWh_!dj>& z@x@15vR>eSL1G6Qwg&sOhGw*eN3_;y;M1Ame*xpfi?t;hwk7+trP{Z(9OKZr;CJQX zqu_?U(VM)5?H zf=_~iUyf2pjaKvpi=+;xoDmP)R8al3=u3MU1AEn1jvD4~^eo@Jwsw7E?TRpWOgFZv z(>EK?)}PVP*jAD{P<-}FUgSg$b}A1$Q4~8>es-cJbF2kF(pUd!X?XC)dei6KYpu%{gT6BYd@A^LYnbjF(cFCJ5&f5ITH z^t1naaHpUB%_(=mYz`-i{Jq@QyC#oulJghY=y(Z8dj$F%7GWB9Yrg>%pUHGg0D zPq=fTTy~*aexX)zpO!;XLhB!@FSM&KURGb|)cl3+-{{qxKcfE^|4Mue zYtD>n|H8QL%%tw@)!%WCS;K`zncDu@ z#=+Uvp_$JE6J3L2y@R7e!(-zk<1-^;OGCq}Lqi**qZ?n5t5egfb92j!-6C zEw5~@u5GPtY_D%_Z0xLT9(>z6TG&3F-oBjNxkm2XAa`$P_iumvyj?%OJv_g?yt=)) z{cEiMKdH_Cu=t;ZIPf}i*^lJ>2LEjyeHg;jLc*b0y6QebH~jB;bg7R^&#ASgzZQ-E zJ&%4fnS&j~^68rSuZKIilQ!C^|DH$BqRg$BuQ6!}pS4@-Z;d3+DL2Mx><<7ruhnOH znbCeLdV99N1!Hnr`pn0WDUZ`yyB7TPZseJ&rp)J#NG3&vl2(LeJe2;`a%D@+s|iLF zB$XOv<6a3NaSpnOW48T#g#`{;u7QvuS-Rsvw0_O0Qv|Q;11)~NhvPaVfJk8?v*6_G zI34Fa`RDe&osU)gnb|rW9>EJ__a7C9XpXMVPi5@-?{Z=FMff5&zf4A@V-4;GGyxA}AKa&sj!9 ze$LJEof2yyC;?MMNj;HYjlwty!zEx#lC>1fBrWU8k&rU(XB+z*rAi}4>cUyJM~XhS zfK}B2y2C2HYRX|Py|miall}A}Y$*pNOaz&XHXG0*mB1((pWnyFiHrwj@s>!3xZCZ) z&#sbliqX8hHA)`>bBp=!ec%iSm5p}0xEtXqxzObuzaLEy1W^y;ncE~;d^|PP*1v>+Z8> z?{nwQ+a z)fTs9*nm9p4~WfKEaF|mz zm~lZRL0n5Hjt={B=eEt`tCczhpG6ME%i&HYec^ZtYFj0u3Q2}H%Lo{j=Wz87o36+b z&`-(|I9cJD(#QdC&T%-EsE1WWiWBSG0NkWg0Q%uk0wCl$K17vS?~9JpeeDPWLmsdR z1HW8J<8yglli&ykt7I;cQXz`oVfHsL=yQ4E9}WkPb=BN5$gJ0{@I>lg-G2#Xr0b-ouai1%6fBLZ{iU9Q|WzR?UI9n+&*)FdXLCGpq9;;0yrY2MGF00(tR>qUb zScUFTM=1TiP$vxCDeZR*Q}rDElpA(J&1AiH5A6u{iLio-wr)JCrq^DY>@CxdMXIdU zB|K!XCNRd86DOh6gM;NNL_<|@L=NB-won}P_v-X{BBT{^Ov7C^z;%yGML))ybksCw>Pw5%mtxnq&lMsWxJyQJA(d^u?>nK{+?$#9cznUz&d-CtQicGx za%jj!x&hF)vOv|Q6d5x4#j~#`r6-y-POU#hf3w&&+FlV}QJ0FHJErAUN(u#iLs~tY z;3Z6)3W^#?j@VT?O_6!WhE$; z;xLp>F2PkTo--@TPwX=0Lrh6m{fO+;Uc*r|=?g|J&&)Bl5tj;z-|^(%4Bp=m)w!{r zJt{1raQ#ijhD+lW7lUqoxv&&d8@T)FiMlO8&WVj3RTcub^{hszbZAZ1$`bto6+GH^ zw>VIumpUpngqBL6^xn(dl^0nH(!Wj>2Ko2QA?>p*RPY${(8cGZis3TUHmxvY80mGN zwfyxEM9{AP%N^l`>;gbH#+%nA%wf3_U%b_YA`w18i3jZG`_dI&KU>-%JMKj1t*YJy z)>nH!&GhgrULL(ezuU-ZCk_L5B|+5PjLdr_)hK=< z^8BY}Xx#^`)+HsSZ$Hg4(yb9Z5Wt1FVeA|7mTK4Rw&tIaPO+CK)ha_P$nH-9*j`!@ zyz#7@4)?~kADQ!g#ZfBmivY%ulO&=Q*bkc5XAQvL>T2RKF)bz^%cy#KG$|$ZqlJR= z#aQ;^XMEq?ex%#hyuMEY04#c%;xVk9H^<)iWyxF839R;zSt}Dg?MX<|OKUuPw=eTK zbf4=xaPXXU0I)@fk;nBfEvsxJbR>5|02agh*FB}r3#;DI?gTdyEPP;*+YrWe*%O&2 z+U(ZhWc2%GANAX3B>-ANFe0wAjpsy<;~9M>U;Eg9yT!f~OP<8R-|%?J5@64V0zKDZ zH-zwfHaIJd2d*_ND+tVpQk9g|B^}lv+X(Did8-Hr@9VM4F?gXs?->{;9!&`m!5O=u{ zFR(v81XpG_gki(`E>Wn}@GTn$yr1?)S!JP`+^?RrGU{+s+e8pLOuB6}`F5v@Ls#`1Hj28m})Udk5f9td&Yx{uLBr_nbq z(bsO_Ne&TC)-hj0vE6jRaR)}h<(L;r9uIEE)^g#44x+|C;?52m&(8)2sk{Z_#0|5N zug+3Wo?B#YD1GOM`6>tSl#3BIj04cdKb?N$UB>)*GH$Ot9x)KFMUD4OCH`{)J?_O@ zJhVH(rs9KToUQWcvtg!vW6$+juLqMjG$ZslR)9H|1iA|ZFI@sY7v2L@A|El?%t4|M zJtj#+GD*-I+h0kN$ViexC&@%6eUMEOAtsN9L|-^0vJb>AaSQCDAR|x`t&3!B`V?Ks z6n&Evtxa-<#Dt921XWc&bw`M%V~UMrs%>NnO<_uISYqs13JoOH_9E5gBH50Z%|Z2< zlegy!Rmdy)G(VnHcQmxdDw%x%(lVLyF;Vvx9OREqH;haNPm$<>GZG~;l1(yFy))A3 zGj>oAis$LA^%=KxKygBu#U`1h-kIeYnMldZeATp|3^-yVqbV_ssxB?YJIg2|rIuJ% zg(s_FB)OG78||IiexcL3nbjblMQNSYJC_#d2z@)^ZN8Z?N)H*I%XYoU24E<2;_03a zXJmIr=EPLwT=(R>k;n-%$pO3Od^bsLGszyh$l1C8@66=}T;#UX=M78dk?Z80nxw2{ zu>On;tK-RAxyW;&&p#E;U-C$^AIc+J$s^)TA(3Kzf}cmO_7*$}rj#nsHYqr8Ex5=i z;Atr!{aC;vl?`SutgXoFax5f)7xIu4?)MZ1Z5GxO7ZI}+v8Wa8^yDw76ylc^5%m;N zZ53?*ihmmCUwP;AIHjogu&A}gZ_K4A`hb)8iH?^(&T8P7^SQ5)%&rV?<#}Jdl>&S6=6X9ZV|;y*{kN0?dBO0g zoM2PtP?D^#7dg6!@*7n7`?>OuhvgmKq!+Ac`T~h!NU2w2YILgHjI2cSrU|ZqO01IOP@v;(NT(^1>J74op_20u zG>`!rHO+1stvX$;`hcwD)FJ(nS#_(fsyZsI`w|Ooz?D|jM<~em(PBZ(mso%TPf;lDeQ)zzoNk6{_7DtvQdXUM#96tSr0*$00|d zfQPlU^eAd!q%We@s;w5qTS;_4L7P=a=3Co-Q3oEwNK;DJaq@w=t|%Dz(wU?oEYUF? z(28Y86ct|;lTN)zJ4)0!S)307l!i!;H6-!Ymoqc~UF(#b6CX1|RQVw4V-147C~d|j zDMUT)73x+(Q({}w!h9334(EY(E%_L7FSAJNs@Op~hy>NlxX{cYRYSqhaxW7_utIUH z-QrnU?|s$Wveod2kHr0of(}j|+NQ| zh2n^-2F~sF8yvvQGDVYg>wsD7&{fUIBxwWl3JwV$_}wpP!Lb7@L2 z4mk#=E8DkSnYiAmt=&|Las!3~vTE6t?yOSpx^(KYSEtmwLKu)jjJBU^EHq-A(HyRz zFKR)M0?@ZM$QbrD-8Fa|(W<3tz_CI;Fb87l>1p5WVO$~C7y~gKlGDBD6_g_zg@W#0 z_X;ufiOBTb=kFUh0I~Ft3z+xGEcQLn08JqJMkh%X&HI)8`c<^5h(+4>68c3BP#L(nkx0$S~0o?cBan^pE_$=d#c$7J$@0V;g&7ySs~@$DFPo7 z2p;1Po#cz0<%(J2j9cMM_<1{d=XUD;?bL(YX@{I?N7!)u_xbw|Zl@jnFG)Z8herKR zgXwQd_4g-t#?k+$!J;lKfx>D^*fGX?xySc&k45v2#s2>h2`ro{IC)TbB3pc-P;#PN zdZJqXk9mY$hD4tHEg${sAL&(}VDp!SgcXra4F5y0Qqo^u(veBc5f+7Dy`+EnlvUl~ zv%3A~sBNd(AFfsN-pCK|vcBlNIz%=yE32qDx3Dy~pd`Pru&^Yjq&&B@BCiaYUtaYm z6;%Zl)kVmf(yH3Zn!39B#^$D$cdc!M?H!|?UGKYlCi?o{4~={n9s4l$esbc&^yJ6s zsZXD$zs&rxmKUaHzfR4qd|3E7zPL5Kv^TtbJpBE1Wc7UP$Hn`fSZ;MWwRttYb@gTI zVt(uF>(4 zh<(T#_`g;b*?<2w)pqF-jpzPnWf9m=r?^3SXW|dl(%h{5cV)4>8K0z3EeDxz|Eba_ z9J{jkwxGin!Vh39!6kCWYz;e-+hKLcbn<>RQ@FC>5_4s!xv79{wz&j zv7H6)tFA%j`b^!g-Jye2FQF1D&)>!J)n3G%A4Lr&KFWJlfAMMyT*NgnVNv{RY>5@) z^q8SbW?(=1{XM2Y{Z8NT4f=PFhre!IUlFaw4?aQ#=wNV2iY;9MBx`w3@F&Erf^L|G zm;FiaY%B-wD;Y0`P$TWFVRUxJU&C;)Q;VL^Bd+fevndhZBDuB7zWehxw=PB>52z%{ ze3DqzxW6|XK^40{N2e>+rCrjEJ8?do?M|s?ubV)^^u|_3Z4|HASKd^=SYFRCaw=u( zx#~wjox5*})41S{x#^T>y;4~NrF-wy@OTiMnVc0SELo73Jd?QdV8wVryxov8PmQM= z#VTPK_gJ|TI;3oVcv!K$m)}F`4_Ty>?vpt;vnCZKk#4QrDsvsG8*;Ot;%-4qQBbm0 z1zYar$E=$wr^zB0F(jve#UykG)ql&Gzm9Q|MAwI4w^u{%ia2FcF^2_jyL^SIa<{qf zj&F`4fh-h`2fkKdg5wIWPPBc<+)fkim3796-_v$_b^m5s8r(psDGlkuA6VtftaEWj z)qM>TPrzf2Sw0|Qkac<0HZO7Yp&_7RTdM>2_W-Emi}AC)p`REI5xb94Yp)e_&o@=T5fhIB2)V@-c0rdOQ$c>Z}W1xcv(A&M0sVR6}I& z)?wDhUESj|sR^vP52&-8EkxgR)%=l(f-|P`&W-y;7Z+7Xt302y;+?d6S1MjB^DH%< z3IzNQapmZQctoe2^qx-s1V+ZRqjUD#eH03$PsEoCNSSIXCA@>tEBpR7gJm1!(8z@Mc*27WVd(!y0*q4VxLeY@x?h4zsOajd8smtj$?9NcBTa~S{#DelD1a7v)l&3seZxW z9zJ}>{!xVq!go6=j9e)d@@*Fp4merSgr&={DJ$YKZI}>nmZGjyCw$Ey1-E#5m8QLg z*;g25fK1=T?mH>PIwz|zlAbA3{Su15Jy$e)*;@Dr*Nro%gPzUWc32^dGeOMEHkM&? zI9}H61u2N~HlIm?I)g@H<~Tc-=Jye6*L+;6*#SHuS)jI!V^Y!dGg?L~1imaPrj+tI zKP0k^Bv}iP;a76k^J2Ky8s=3)VwY~Esu6BpuVX;Znw^ZkV<(oxhA767^J9yL%X08e zFD8lBR)AGRtf0UvGYMf)EjM<&#IT@2xm&1-y=7O?ZgN!2?+g!W$90);)-g^~VX~V;7B<55J>`1qlKQL_$N2KuL9d0`(M%1CJ zE2D}EXiKiyP4C}2g@%`C*wD7m4r<}S=kH^PfcIsAB+v!`ac7nOEhrDZgNHC{1Kps8 zha7IgxGk5j_3-Iw^L_#r7(W*E{yh;%X2w$p%lyUzT!O? zrGyekt46aDr66=(W6)tx)}Zwcy!Q z?bFx9j=|^%U(>%AIj4yaFzWk;!Tt3PTtQFh;0S*D#tK0gr&dO-K_Q-Ea32vpNDnYn z3Nk0RXltN7Q~N2s-u(DM`vJ;E?iyiei-I=1efGd}%;rggAfP{EDdC&pvmHm^Q06Ds zv-GTQIX2K=H}%nY4+Q>6D@uOwMMeF2m4ANh@G{lg9YC}wW*nRK|*i2_Dgb`=cO@6;k6l5~K zyd)9b^*V_q9>4cK#c6q0joqFjna!rUz3C@5Yr6b)gC|F7p;;RipM3;B$=h+C3BE2} z2Dx&B8Khc0l50-FT!S~wp1t`*HrHJEeq4KzXtvUk4pIvwH#WNpsv4p7Og#zpbGzTeG4MB9pxU6XoePcXs_=z&fA4H$n zNG|hHS-xps`XL}FB(#Lsmj1qTa`dLq+2~DgcA@eEmEPaZCoegca`DoTN?cI0&{bGJ zkqKDE!pY8pI zbt8}(#?(AA?TmRO<-3Fvj;2M)f74qa8JUfMv@P`11DCGDK8>*yNyI?RFL2a z90F*Ac13N?FyoV)kEE7}zxowkzL#Gx!zZFH7k*^pyPYD5n z!*!;|3BgSWwZOQe+n7;6kgY=f@ftqnAXgj zadBF^iLt%_CL9cF{t<-~T+3hCKR+#SEZKkTW8k{cSt~EkXhY3j)jv z;M4{HvPlb&5P(7Z4S|HO6djXHInBd#M}7zJ-EtWsV@)~-Ce2~{C&pkMV}2noKap}% z;Tc^M6|mXx%Ucqv26RkDbau}qz|UJ>+ef%RDs{IW)_uthe(m7yS{~>=9Qf8D@Uhn$ zRU#&J32J9lu){(6dNUE1xt{_VZ`h;1_BxC>kLc;jHpbT#M zEN+V&WB+_Q=-xpD;ynEPR>Y-;x-T6ISSYG^BZ~IzA8YAsh4Jcfc&l*$s{A!A%VKWfr)gdrgm;PEm1SSPCLZEP+# zKZ6V4)UHq+X&}Z%VQ?K~*^!Q)g|ENjC@h4vK3(IU9v!)WQar5%ztZbwf2M92I z0_9&Ti?=QitNEOSlD5PZh{0aOtrY~VWFn_YBK;-@qhrYXjRY}ZA`M&O?LSnDIDw0Y zBSSlu%7C18MTg(}9u$ytk3N}WMCV};u>_CK@&N?zbCMX45(Q1x_D=YgpYWL8k9j2d z{&FHUAX#TFg-$i)aYdZ5H$QfO&U`aP$0SK0F;QG1=9vlqa~_C&WU72cDtB+H{(9;@mV!-nHbu-sk??wTg(7|t;pUSVco`B6X>}8NbuoB)^Q~3FURn+&BzOH@Re%T zZ*SHc;s`!;Mk0OUx?`eMMh?K#ALsitvPsl1;GEPXW_qs+1I1rY-&9R`>_{;%Ab@ zxH`o!@8Xq@g`l%S_MzgN<>EKQB};52TR2GM~0GzxlF&%QAmn;zl6~4D_&+>MglG^0i@9i9DxfUcy%%u%6@F-=a6LIlOri&s4QqB zXLUtNAdpWlOSndn)uv@4fXaG?DwtYjsZSC5vLt)HvWpjjBSc09sOn{?_EoE*v98?Z zDR!SnvXS5rEmz?kvf=@%r+BNU)gWIo%NJ6sMxAoTFDaHTtCxAf-=%7LO>3xJk(w^m z>Y3F!ZPmDkHMlE~L#f&m-pW&6$T_k$Yqa*wR_)DJwGf~N&kR-MgMuWWHrkxG+G@zJ zP&dm|H^Oz)(v?k4RkbCRR&6QUYDv@p3=aOsY9d`~cIo;gr#i4}O{Pyeh_94c8jK?i z#t1dsXRHvr0!vgPnMW&`7U~IvDIW3FDmbHVXBDeNSF2T4J&*<;9yH1`HU*eAlDjqz zITbQSH)%M7=?)t#wwwG&n#tIjxuWaa8A|yU@J$#|Hz;x8wI>J_?)zej*e|mb59_tU-^o*r2`E$hlQR9sS7#$J@D$ zm9ai+3>~|Tj^`^YsH_%HZ@W3bnbK|_n`H5CZ-upkgGjC1q+58+TG*m+-t&S>_+W$w ztRn4giSz9whwW^)Izsu{*)WGVbITNCj3~M74#frZYDOK*u=6)B<*o}3g*Mr@w)Ozh zPGYuBin<75#V#^Fs-^ADz^yJKz`F^>&V;LixG3<>So5VX_<8|+RQd2^tl^#<>G@Sz zh!ceGZE}ezq!HY)bpYwsZP^r}LR@zHIaRPi$RG3c-eMznbMB?lA%9!hD||@S2>y#| znfHnL^@+=*umSq2Ci@;<_sKH#%ggl3fk^L~Lxeg=)H?b#7W=h!`m~q^s=E7YT>7a2 zeKm+bRLgvE;OX^%#f$#E`-8UTgLZy{4%vfF9fL0x2VY$ex-bp7$qcT=L#0&MWz@N3p9m@IOKX_OYMUu&o2lrSYCSPB(bBb4(|o3({Zd`aOHDmmO|?i> z3H?}ZT>0UmqV%eg^d|OziL&&*vecon)RB_pF*exmDl!Ke^7~JecXicv4Yihy4X4d4 z2c9~#Si4l&dK5VLrZ~gnUWJ6ag~C0;0=&ch{UiP1(Sc!c@W_OasHEV?1>fRIez zpjLph>fE@D_FVpKfh{r!j!{9zxt!ai~S$uvjUXZG+J_Q(bH z*cA@MPxizu_T)YGl!HG>J!DTk!sdUucJkMgzn}jXpZ`4+{FfL0O$Yy* z1o1!RUx@f`N%G$(|LM!W#YmpazfQ8`9ZTf@=Sb%N*9AqX0_^>kW9h#qW0GzmnT&x+SrQVKXA_QFBL4xEav29M$wC zv2h~1VW7MYUE9#s+|oYQ*gW6Vv{sK=Z)w_SYx&vz?)&iY!l!9$&wpzqCVj*d}j|s_LR!4LGx<=x)D?dvr7Zlb?cP`(JnCU~jeEymD zsh^mcRZkGT<%w)u)!JCPJ0%<>>8?Z^(c;6RnQ04|NKjXA)Yi(~o{ z_!4%$nzR3{``a#yR`&AdqHnbL{UHPN@f-_6!K+Ki%zbNC*dCF~Y@M*Z)Q2hS?6#1R zV_$w>`C5(T!Uw*g^e*p7qyOH;Vbjz%*6D{%*PDl2%NiJ0f_y*VopfDzPG_2>A&IgV zWpG9H8Pt%{PJ%MDO_DA@46562?Z(1R_dSv_R>C6kvS5Q^FXbHa z;-=>-anh&dUqg)mj%%{=nU9MNjuTejCw+}@w~hL7;b7yn%xwTBd!V_go%mhAB*pu} zVUtSosR*8(myPc8+zjFom|Z4u^_)ePUFghh1<^?bu6P6Tiy}8&%KHk*{5=;Rasw%C z?LE8#rkS%v`}M#@BIk4EMQ~n8Zr9@uS#3$e9^&az6%U4=Wqq*!_>jmUy)ao_WRtDvSyYOIsWe7lV_j8pWjnSE6KRILe z9?fySh!Y#BKK~$wdm%L`Mx3PfeUNf!Y|CY^Yi&#RaMAa>$ko=uejvrmNqh#Oz83>+ zglX=3k4ObUaLKthRk4GsF){9vzWCLQL(F`ff*xxTmq_vDMt#Hxq%hm9^$WYL(ztn% zHNM-bt$TwU_(g-}&`;{ayWpQVYzWDHOrIEdufFnRsE^Ie2@`8*DX=?AAeJmQWAPfX zATb|fp*;tt(8pWcm$zy_|3o;rFR5}hzVYyR=fo51fA#+L7lN0XUgMTUUk=1bX-~Yu z=gv*vh=Hg&ZD!M@8ztAZ(k>-83U4%h?!8fb^>a>V55ALp9y+z+>qj%@W*Y1s3k z71tu`yg8O9tKXt)+kjP8f@uf)uAf}^(dbO{;n$HJ9@i^C{dcC%Uih!gTJn6A`HnLr z-hbH69Q)z*&O)9%3i0s%8#$?UpKQ6OGY^M%pSw|NO#G-BdWU&WWV|A|{F&0BB_w^q zt77au`sbIsBsC7+U@Nn=sb<<{*O*|kIcA~?j^5-1A$JT>k1VhyIMY>j+5AxwM-;+&g++C!u%)vAAZ(0@BPh2b?y~sEelf5?#<+qmi&Fgg?Ni*K>!xsNvPVA~Zt}8^vj*RNCAYc;Yzr zu)jX3Ve$4$ZQ?NIT;Qax2!@?jM034?oX8NBj=!=DpiQ5GJd8PCsL=(N2hp;k3`S{ zDanWnhomp#aS8Ph8TJoRPT?Ufl6ehgcy%hZDoJ?6<$0O!?6?!mq0wlw;@| zJ53Ouf`pooqDX@RSa2{u8)(4RNp5e8=JhZ~@mH5jk|^%xL4k=E4tiOO^QXX7|8Tn%+KP5Lj>!TkAKC;OrqKVk)ui)FsCm;vm4S*h!}%l%ye5 z4%!x>{c+yXL$2o4D>hh^vgtR4*hup$I@v$NVR{OWkPV%;T7g=ei~SmP5xgI>5+!-= z5Il^IR?mM^B3KwKFiTlaB-vx+G`a5G&(TpRF9(S)kLAR*j!bm7VJtGf&zq_lWjxKR z_;iW;HgyPLI^wMoO_n|8RGhzsY^+SueeS+fYHZ`x5Yu+~D~X_x`9KkZXT(9kyAIN2 zv?is3IXpol0ioU56~#Soa9>M7Qi$>E0MvWTIEo{MiSM*+*-fBN0DRNjKzOxr z_jV-G-Lyy?xs7lMaweV%_U2P0nnsLi=~!8!pRFlvnrII(t7uL<^&nlQ z!Z#_`fp(|Mv$ED-!a-CIwDBuGk&JUwP+msyK^#~)p-)2`!A+ft3Qjusebf$jlJOa; zbd}h}&wiA!!J&3xK_7A~H3`ss`slrcMP%`Lz#*)mrTtT)y&*21LSGMn7@#Ra+E50kt`|5H9 znldm97h429$LrJ!yn#~K72@H|!f?~cuOWeyDY(D{-?1RDL^n_aHxbe&vc!;Yh8${Mh0`bx_`9*;$Fy39qYJ)~4K5Q0 z-^U3dn6|eDq-podTLEzX>EOjbTy;dKvTJJ+1XGG?#BoC zu0V4{IIeNnv1^!SI@pUa;&p^0G{W0GA|wmyht~t-%a0I50kf7P;#~>x3n=i3-KlCg0BW`nt z{EUd3jfi5i*V$`*{lS=VWfr!^4gTd2zZnsKF$+(defdpA?ISk~a6ti7MW~d=ZS}+% zHOIRW#gTcFEAAllM$#O#D{nMGC?)Tf&5 z;F#?*r@lpeci$c|1T>w>qwO-T$TV`OUN@zX6s5KK9}&Sm4YCpHVj3t zE-CEV@*LEdoqUX6_!PJ!!7dDC%u;1;4xmrUNHhQ3Y({+ZxFl5$4gaxt}_&@HBL zQ_G>bqJV~SqL1ZqQTYgl3f1#Wk&JR&WCdYQMUGQm9tpCKJHtyAx$TG~fFmo^@~{;? zab6?`ape|ICB9r`6K`HiRAmy9DJ9B!GqR#~tr8DV)kBikH;NoEWf~fdp(%Jh${;W< z1)jL9(w_$hOJ#pjWBPmVs{TlVT$N(_;S@O%Rb$jpjaygqVZJ8evZftU ztM65Daw%|nNpa3lbs1IM=7Z>%R|lG*ntV{knW&3aRP!|I>u3Skx0I66jk>*R%cm}$ zq^5NqIdFl*VMI;Y)Iql^*rhS`Xp&6Lxw@XBdcI1ez;^w$DI+H8IhJfaysQ&-ZU8}Q zsxulI>l)sQ)js4y$uc%J`!sMkH#WcsirHJzcGrskW@ zPMdx)G}|!d(mR*gRlan{5;1OX{wCFU_o}{zA@jj@gS&dmOZD>Ce9o@zg8uEzfqXS| z)?|Gyq%jMvaaXMfMsy-6xdkvTkWC@og2aDb)(x zLWhyIT_J1Aq}v;>T6MF~+yiYpn{76}txCR-aqaeA>GmBLtoQAVg=&wsbKgied-%5K zGIsPycP5#2+`_na+JC?GVy0$ZZ zZ{AsT?m8W7-B5>YNhhr%JKVmjg=K&*K~JZQvD zayV&xAhn}E(yx#jUcE6t!gn>ICrshIm{hnkSZqFO={I_3p(}fA6uLdCcSv3bN-X5( z>As*yc`+6nJpw8iiS8KH+Zi^9q1gqG<4F#`svj7P8859IC+!(;>uBuotLxIB`Dult zHaGYz=>1UD`^75o*Tr`}i)j1Bj`(YG!xuQ`FDB|^sAsMrp;hnQW5#^0-uqpR=Q6$D z*T$KL_QU-qt~JIn*Mr+J5FkPrK=wN^RO$|%@W(H4;V@6M7X zkbgP=rTWjM=gehx&Sh86O}WelYm$8unlHAPFZG`<&zUcOP;^Uf?)||$ig}^_!9t_O zLIW8Y8vs6zTIg6>==!~Y`n}M*1nT?^$`@!$S(+Q|TpS}K8|noAXa1@8hkvqS_elSm zBxU}KZ8F@&{*ALdiyD1vKGBvgf(KBk+P?=OySW|tpqw-)&U4H$E z%8G&ZqNT-`=XTRCUJtr>b-4#3J)@F*ll^=$90LmVVU>?Ux`e|rC?X3cweRDK(+Kpt?Wpx{205B_V*R*zq+)4PFQ0tMZKzHgX%vX zqDjr4WwgJ0vQJURmZ&4Ex+B~ABj={0x2<~t=&h)(4aB>jDet~#y<5ufSt{#WsOq1u z9hhwxm_`qO?i`*P92}n<99oKLM^eBQjA*}9tBxmw!0UOoK1bNc)E0&{kSxxB{w$1d#uE&rswTuA?q*O=iu z<0c3w9GAcyqxH``$p)S4Lk@T6z(d ze?F**&Awm{_RCiY-qUDnRB#Q|)WcgDn-O$AJ6O@vY;Tq&cYCR>uU+Dq;u!UobZC+7 z%q5)2?=08;qV>2tYvrMRy7@)>&rc2Fu^2<&-mR`$%+)Wg0B+BgA7nxM0uMW{^41r+ zSX;Z)t}f2)2ko=oVSZoZBsQ`Fe)HI~dI0W}XSg0;gy#o=P48R5zdWE@3594z(xv>(1)=Pzv8Pt zeJ-CnY!$^}Dv|SOJ3UwqpT;;JAjN#g1e`EWf3c{n%pB4qW#W{vnkXn{^3(mwJRgC# zUd6+iHs|e~{fJJ86E5ZUU1j}^2g&*eEugAZNirokL@rMpb77v}wtG*mAcQ1D3m?S8Kf*|HH!Yu_T#A~@ zHllKG*2yF3GD;g&bf-eLPL{!B~bO5%=;gfXwwER_+?mwC#c-w~ecq zB`>ai17Q=w1)WSu_dYrxIU$q2j=Q2D+}TivcD;)1+m`}DWN%3maq(MrOlcX()!(S( z%Qf9pExc-;4DgiigvNKziEl?-#lOR&>Lw?|CG&IZTa5`89685u-0Kl&k1_AJ6q5!J z=+$3+P~YuZU{>UWfsP(2kBO5L-jN1ZTzbj zizj{LJo#@radV(E65kYaj;Fc54aQ-{h=AEHBR_u1h<$kSG#Y{Lhg>?8JMJO_`nv-7 zwZ6W*umBU1k#gSqN&JY}YgXDwqUvR^t_ycQUyl{Ou z`7?uRS#nQG@3EH$V@45Rk|90maBx&yt>Wz_%Or7^vfC<^k();5Ly!+Gv~2Itrp8u5%p_(Kv~uU+3VVBaZ3 zJeJ*bjsKAGECE9_yh>EB9>QPjLY^@s#VZo+@2AhsYQm^|`7t5c+?Ml!=!izE%?Kr`Kau^NLEyCh%EC z$Dm-^$hh4W<*mL&TVW;i&@+kS%-O}~_j8N}Ig#Yi1H+{fwUQKx;3OyxwwCZ^69%xo z6GI7Fmsr0TbBkNczQN#h1C4v1q)K#q>+6%q9CJPKVbD)Ir6$HL&iFuda$G<`NB^#> ztR;Z0-wMP*qhl{#zbLF;Fs|2aib-6W#RKu53r}r(8As9ja`Uu|rYi#wg_G4$N|up^IRnJ2zmx z%m#$i9#Wl-SN!DwqL)?6nxD==^_S>YGya$tL67x3f!=OlB5D^CY8LG;8mHPeZZI*7 zmmTyY0pL7(-}9x^26h_)i(dPw20JBF^lc9|-4A#Sz7>#?>C03lN4fwpl7i*!IP3_| z3?%k7KldQ4!k8#G4C(9eQg-yIDaDLX$vssx`A1Fj z%{>3BO0P$#+>b5qZdXZ)R~V-X88*eI$l7ukwOsrdufIXkKP|9(iaRaXvV43;fH-Jr zN9tZHook7yi4EX$y&9il4 zU3nYk7^Vgj9YcHMhr5A^+U{I3b;L&H3rnUmag=shbEs7Tgp(*0j;r zx`Mj_DvG$9)DhD!QNfniy|W~?K!b=nL3{HAcaO6I;GD2e`RG9M+osxpUm`8(Oiy+o z{dl@RZ(~w;f}Z$4ysvWuf}&0R5(%I2W!te3Vb>-ncUhX)F8#1ea+4F&oQfkN^cxS0 zZ2?SKeO&U1Ttwu(_U1L-?C1JKHXkSl{T-Iy^Y`FL`RHp?8RtV8CE$W`lW?*ZFd*dC zdWmPB_KLYHGoKuhx=QC58QmJN9j~XBNFGj(GxH%UpvaH4KAwcA+QMcRCMO27<6ZNf zpSurlOo%nS18;`L3#g=MadGr$N%>;ma}Z=!yv(qj7dw{@pS+KXYo=7heb1X!I0kDB(a3byxHBpK z1kH65B89di*33nD>xaZpa=(yf%!~_GMqM`r6y7(!KqCrYvF{LQ^zqaiuLr~LA=n|= zZ|*AxhI%qqD^YC=zxUq0Q~F>q@yp5^XCGGEE_D3t)WXhhTg51qP;GLoRAFtibOkJm z%j(s56O8L;fAQ|N3+d?UZ(1DQj=M?^?`Kjd&a=)o#Gsd+zxHjQ%N@ERIAuAsGJu|X z<=qZY%o~%5-(sR3gL!oOuw!CxyE8{i`@ED3@`Lc5ALK4j!hJ)fgOsFkIlz zNlCw~4Ob7#_Fuy_U^X|+-6s`K&R_5bvN0h<&msOJheIs4iYAShbjG6dkP*_q%Y<@HQp%|YNE1cuhfz2E}h0y}>Thb?{4B;BAO zQ}M3Ffdl0LE!_Yr94AIA(pwuODC|+b0yyhBK>HKm>tn;?$Myxbfv~h7JRLyJI!WC! zfDr+pM*)~!LhgCNca0pWPJ^l0Lp&dc0CfN&bfLrc!9U=^r$4+X0Ny1%Y+UJ~yxd^( zjnHAEU_F&kJ-blG!aI(}o~FZLP0L}Q2*cLc!se91UIIOD+lPClg=22C0lvfGmUQ86 z<#unl*$b1xA{+qN3A5Jq@UMV~cef+f6(XeUBfMI}Zma+eut@)ni1-Z;cI&WWc-Y%B zn34)9Ru61%iHfC-tT75gd6H}vMl?A@e+iF9a0gYdvk+T_cNvGI(Z$r2Mb7s`7XFB= z0Y)Kv7z-6Z?`A_M(j$>7G1IMJH$A_va=1=M(b}`IAI@W2>EcLxq#SIagt}n<^0;0i zSbwYf-g(^GIX5>nen#%arbB!#VeA}RY;aTjbvkS!0p|`h{*(=Y=N(U<9$#fl$szQB zV}pkSC!tdg3=u+5sd^JgG80J}lFWhc2;uV2CEmUGtNkiaL8h;lB!+Fjnj}G?NiuUu zA||*jn~XqV0J~%&+$iybYodHgA~l=-p*B6X{mKX+lQT&%^iClV0V_Es!@`p%3X<6d zlGEf;j7?JQDwu$-;pX1SJFQVRJoL8SsczmWKsHdZOPW_knh!e7Z!RssJM9#~+G~}7 z#)EzkN{cW_2_^&u&ZWm)q!&+;UqC=1k?MO0)^S97CQp3Y1%(qj6+M$0f1Vl(Ny|cK zI1*=WdqtXBSfTTbpp{zwKZrCK_1)Gboe0t0A1QZ>J+uHe>Of&F0t4R2w-YGI>r-b3R& zs8hj`Wd2o#9kL(% zWv-VA&ZDKane=w^8V2*!M)SEC8#RP~6n$Wuk4R>j3A&8Vr#vm8+@Q5QhBrCxG9ST9 zpJ@8TE3+)rDc-h?qEHH1Y>F)PL6$oqS?Vg>RVq>#3e$XY>EL827s6(r%GS(E>|j|3 zveHkROlK5{-aw{YR%}HSFHBaBwpEQsRZhboy{0jimq?UUnV%12Y_e*;tr{Iw{1F+S z!%#LjAFJX7TJ))zXGp(wSWUah60DZHx)t*ys^$b)wPgy~iBi{~t#M?i?UAVc#ehQl z)KVwZ>Z5A=N6Rs$(Kvi4a&;7yHHv5y+jT{i&!Wf~QD8m@K{V>qB@)*Zhhw>j*1CqC z55>p`VP-7XIKv~c3S{_meHQe)QGA2cuw*P6rk{>n^Z&%bg zdE#q>ANW>1cW!?FXM(vkyUv0Yh_Gr51$339MfQSwMx=13KM zq$Yc)F2Ap@v1O>gU~DvCY+h{Zn&j#i;T;y>5#stj@TI+@L zE@%4LKXi^v()~9=a^{d8m_YWqaPB!WKqr}hE?w|ikFFe!uAhu-UJY;Gj_e@O z{kO9Rx64O2>))@pe_ZXITpgZXAD>e(maU$~)XsQ$H(mu_nTfzsO3eu-(?>^>=lqxH9wz(aa$2?h^@MY}US*1mY zUrPnPjefF^tnJcw`QHC*TYXIPGmUzcKz#n_&ExKF=Nre{6d1S{_FD0_*swvuTB^rF7oJ~@C zRmK`->SbFjZ%)O!o2r|Auq$s%-pH0A(q+3R=S=*RJ?k*Zb1w&DM{F+JCx4GUHynqH zG%tiMVm~JWbC4q^M%wO8Ay`B8O;K_i^gt`UZp60a^~XcKQmYu%e3=`c{?8SNy<>&) zGO4`sqH_9txj+bu5A#t$!45Er(p5+p}AIxluM8I_RYA@|&a^ z53n{COR4@;!~CbPs-|VS140piv)sJQ75@9@t*GLWZ@mVu_F{o&RCD-{ohk0T&T9eX zA{8`8{|P3%}n8570Iz$^c zF%E3>P=Bc|X@6Aj|Cmy!ukx$7Q~!*^V~CvWt|ar*(uZ(nO~^$d!xRGNqS8F>+r!EC z>j?~MhvKR4@ppv74+B#lmO1FHCxnRAxMId13c;~pNrkFg87YP6sWS99Y3+rnm{q#X z2N>vN^Au+e75=sQ_sz^Z`irw2h_B|9AloIW$VsmKZ}oac5pJISQRWB2!{}$NlZ)t% z<{Ow80dn3x1S=E51lXrp&00?-e!84U;@7yY>>PoXjvUYw3L)*uv+hAegds_ecz+s_ul4(b-r7?}_wnM~7z! z0s$}g!FP_M8VHUdkuFG#&$@OHKXLd{$8+?S5GN{ay&jwaqBiL1ce_pgu=(QN1fgo8 zKz{3Q#BqD_I-GC4FNu`_;=>Ig_5!oS11g;Dly8PM}hQm}ngT3N$Z@;$O=a >?&9_dK;AmPl#E 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%0Ayx+)WbtTJGE0Q%uOMcX8iS+57TT zqCxe@*eC6x>JNpi;S!VWmde?vd<#F?5fPI*cinX~WT?`%6L%yh?mks#toU6xp`p^G z-gB;>3pDxZeT(eo(p+vprFCnB?gl;DtmZ=pR+&LBF;LQ>e@#Qp$r2V6yv z-|X!FJwm%Mmw+ zpF1Xz@PZ}~m}a9@f_T&Su{dQiI1is>D|Fc__yWuQY)Isyi$v5YwTlTSDViIZ?Txa0 zWMA&zjdYPd?C`bO)xMO;cKOh!bc7NIc2MbAA9p$h?W9J!U_&+0 z7nMHku-rO7X`;@E4(UQLN)s?%4zv{Y>V5o@g%s8Ef^Ju|*M_q9+8{A6E-^?Hbam15 zPXyS6O@BH_ji4lTN=NkX9w#$V$lOkZE;5dFsc0M%A@!GxTuWo~gRuhLA}>V@z+Xa` zN8XVW4MyX}EkJ37Lf3>GNb^P~AN^3gv>09Fcsm`&TH)vrobpoa=whaASde2L38b;F z?3qg`#}sY|lf^kJd%NUYfBPwi(t0{~7wNi{; zqA-llk|_%n88L~Utz;>8XzZw{yAmkPrJ~s}DdIdKW+3*44ov+UTX9Y^Ix^YLun7Yj zxfiAk#QM&F{S@mcWrQhXj|}1#%WX?7X1z<{b%+$N6#MIL_TD9~974n0@injPJ;upp zt~X#HVG-81R|U*rw0 z&nmrY|JhB!@|JK+wf6#;s??Ok5?+D6URD0xw165)sTIStznKMR(Z{JJd!73?xeGAS z{~c~f!a4q-|L=~;DJB0~3Y>o^a{i&jDWk$Er@;x=;Z!!}Qn%#NwBtg#aG_iQT>&t} zC|B-NLV@#j9eZIN8!;Vg2_36H&=zuNb12#jhBk#FO`uvvFoYglRYyTdO9`%~0#i|g zDk0<)v}EPAPN~N*K*%$pWMDdHLd(GPWMKNTFhg0Gu`Jv|4(Y~2JtPyhbhF*`Q$#Xj^f~#}3w|BCyUxKec*6&V?-i5VK~!Byg_uic5I_ke79WETZxoe;k0G`^i7_#Gw%Pmy8h$65|C*C;zm6VDNyKr{&_)^9!@^CAr0qAC(dc2^D}V z1C|WJiCB#?xh3b;}^q4}d%bu;_nx8~-o*SgXeWiaxM4S(&lGa`ad7 z*uvKd)Ku>854Rx-mO-xAzn7zfj?MaZdlVNRvUd{ZHyvZ5=Ir{E5qd971|du)U7qf*(m@ z`QrNEauRwGS432(uv%B$LCU@&$LoaEvwCbx5QYdsfFaa+<6t zckr>XZurSzt&I%H?OB2N#Ir24lxR2g(gW@={)Gs>s`?^LAz#FzsKh)rBT2M;3}qB_ zY)n)(YRHO(n=T0~V>R@AmNk)TFjc8m>FK2ej;+afI4A$>mE0fCr%+i{bjYGi@VVND z5n(w&3Gl97ZN6|O6#J@jqg4}cG3;B`plIMm+_VMenBA5eWyHRijtb2h#|M3ybj@=y znsLp4cmuRjN&@41Q%k-0Cr~mQy-iMK9`p9)#mM^R@{;t9oYjgDh9WoK?7MK)@PPaM zo64@uG^-YV<;DWJ-J|`hR|ldtJ;PgOU_7NioZR?g$pzi{@~SR0J;~%96tbo9^6hm9 zhc-Y7Z7^?SnI63VI-_JCHO4t*DQI9d>x7QxFBK0}HoFcMfsL|i7fo%6m@BM@r7zs$ z1bb7W&~$v^GQ<4#yqRCIH)sS)BB~9%8(z$27SwS2g-pwYfY@&y)A?IGcuAJ}R!jez zIRY&wS{uk%DOo+vXT0^ABikxTrnAbYFrF6?w)HF!5Al$lVyK?0oblcZ66w3$V|jPZ zw=t=a6vp%6Wupsy=TAAe(0hu3e z$8H2>fu-$YG%uPjQYMTvc;f4n+a6pd7DU&-1Iw#oTC%}rdBPPOVn@lbsYdAIaX-`H zfOV!yGAd5bV+upC^NhJevh=$RhZ+UYxOhFyto6N*NJFwz(UbSZN~IV7^*R z+lsOvW^CYo$j+q*Oi&`~*|0~S4HMSw*3fQJ>3NTz)yfsdD`RKg<$rsk(4l({bP-0O zC|%SVT(Zb*5HX4e)#F6x){PV36UFySYwU@-K9|!w)aPqb$%KYzjR+ICTIO=?)D2S- z;nIyS1ftqN(l8c`?V$4@v~sMxK{p=FRSlo-Vqy5}PiD@7X#O2aY>j%v#yu*88ue>w zH;?%93E=!10Y*4I#!`Iw>O$7JR2qhzE0qz{;G5AxzPJ0VILQs0*_ukPJonJ?j4nL? z1fm!pq8_>sL4jZkY7hNhWCQkDET@zu!w8}y$B!JZ5vSS|-Am}bT$k0+ZagB^Xr5Lu zww?L1RFVnSp!Z&$;c-tY)}Y#0$j7`ty{$B31!jro0vSHEMx_psf0R@lOL!geayuC-1){1@W zx*;oL1$&fhieumPqb`i&Ddt?1)&)mmipmRVSzP7$%Jt$OjY%@mz6reqN=VeSr({sH z6;mj$#pp!{l7kT1hV_}u=LsdO)&s}n2y8Hyv|wEgE4OWMQ!h&@I<@J1^);>WqW|m@ z&M?HmCLDxooSLs +Go to the full tooltips article + + You can quickly change the position, the font, the text size or the background color: ## View From f63232f15c63b481a6fb9da654a97151c4d512f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 22:46:44 -0600 Subject: [PATCH 45/78] fix android selection zoom --- src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs | 4 ++-- .../Behaviours/ChartBehaviour.Android.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs index 9ad2112ac..1819e8ad1 100644 --- a/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs +++ b/src/LiveChartsCore.Behaviours/ChartBehaviour.Android.cs @@ -52,7 +52,7 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) if (e.Event is null) return; var p = new LvcPoint(e.Event.GetX() / Density, e.Event.GetY() / Density); - var isRightClick = false; // can we detect this? + var isRightClick = (DateTime.Now - _previousPress).TotalMilliseconds < 500; var isPinch = e.Event.PointerCount > 1; _scaleDetector ??= new ScaleGestureDetector( @@ -123,7 +123,7 @@ public CustomScaleListener(Action onSacaled) public override bool OnScale(ScaleGestureDetector? detector) { - if (detector is null || detector.ScaleFactor == 1) return false; + if (detector is null || detector.ScaleFactor == 1 || Paused) return false; _onScaled(detector.ScaleFactor); return true; } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs index b7a5f45dc..21383a463 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/Behaviours/ChartBehaviour.Android.cs @@ -52,7 +52,7 @@ protected void OnAndroidTouched(object? sender, View.TouchEventArgs e) if (e.Event is null) return; var p = new LvcPoint(e.Event.GetX() / Density, e.Event.GetY() / Density); - var isRightClick = false; // can we detect this? + var isRightClick = (DateTime.Now - _previousPress).TotalMilliseconds < 500; var isPinch = e.Event.PointerCount > 1; _scaleDetector ??= new ScaleGestureDetector( @@ -123,7 +123,7 @@ public CustomScaleListener(Action onSacaled) public override bool OnScale(ScaleGestureDetector? detector) { - if (detector is null || detector.ScaleFactor == 1) return false; + if (detector is null || detector.ScaleFactor == 1 || Paused) return false; _onScaled(detector.ScaleFactor); return true; } From bcbcf4cb29c01d17b3f8ac72213fef913ce95f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 23:31:50 -0600 Subject: [PATCH 46/78] fix xamarin pan --- src/LiveChartsCore/GeoMap.cs | 6 -- .../Kernel/Events/PanGestureEventArgs.cs | 56 ------------------- .../CartesianChart.xaml.cs | 5 -- .../GeoMap.xaml.cs | 5 +- 4 files changed, 1 insertion(+), 71 deletions(-) delete mode 100644 src/LiveChartsCore/Kernel/Events/PanGestureEventArgs.cs diff --git a/src/LiveChartsCore/GeoMap.cs b/src/LiveChartsCore/GeoMap.cs index eefd1a01d..7b141cc2c 100644 --- a/src/LiveChartsCore/GeoMap.cs +++ b/src/LiveChartsCore/GeoMap.cs @@ -77,7 +77,6 @@ public GeoMap(IGeoMapView mapView) internal event Action PointerMove; internal event Action PointerUp; internal event Action PointerLeft; - internal event Action? PanGesture; /// /// Gets the chart view. @@ -157,11 +156,6 @@ internal void InvokePointerLeft() PointerLeft?.Invoke(); } - internal void InvokePanGestrue(PanGestureEventArgs eventArgs) - { - PanGesture?.Invoke(eventArgs); - } - /// /// Called to measure the chart. /// diff --git a/src/LiveChartsCore/Kernel/Events/PanGestureEventArgs.cs b/src/LiveChartsCore/Kernel/Events/PanGestureEventArgs.cs deleted file mode 100644 index fbf39ce58..000000000 --- a/src/LiveChartsCore/Kernel/Events/PanGestureEventArgs.cs +++ /dev/null @@ -1,56 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using LiveChartsCore.Drawing; - -namespace LiveChartsCore.Kernel.Events; - -/// -/// The pan gesture event arguments. -/// -public class PanGestureEventArgs -{ - /// - /// Initializes a new instance of the class. - /// - public PanGestureEventArgs(LvcPoint delta) - { - Delta = delta; - Handled = false; - } - - /// - /// Gets or sets the delta. - /// - /// - /// The delta. - /// - public LvcPoint Delta { get; set; } - - /// - /// Gets or sets a value indicating whether this is handled. - /// - /// - /// true if handled; otherwise, false. - /// - public bool Handled { get; set; } -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/CartesianChart.xaml.cs index c70953d52..021f08400 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/CartesianChart.xaml.cs @@ -781,11 +781,6 @@ private void PanGestureRecognizer_PanUpdated(object? sender, PanUpdatedEventArgs (float)(e.TotalX - _lastPanX), (float)(e.TotalY - _lastPanY)); - var args = new PanGestureEventArgs(delta); - c.InvokePanGestrue(args); - - if (args.Handled) return; - c.Pan(delta, true); _lastPanX = e.TotalX; _lastPanY = e.TotalY; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/GeoMap.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/GeoMap.xaml.cs index 46977fc75..d47e359a1 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/GeoMap.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/GeoMap.xaml.cs @@ -248,10 +248,7 @@ private void PanGestureRecognizer_PanUpdated(object? sender, PanUpdatedEventArgs if (e.StatusType != GestureStatus.Running) return; var delta = new LvcPoint((float)e.TotalX, (float)e.TotalY); - var args = new PanGestureEventArgs(delta); - - _core.InvokePanGestrue(args); - if (!args.Handled) _core.Pan(delta); + _core.Pan(delta); } private void PinchGestureRecognizer_PinchUpdated(object? sender, PinchGestureUpdatedEventArgs e) From 8199de34293d9d3d441e3a163a93ccaddc982072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sat, 9 Sep 2023 23:36:39 -0600 Subject: [PATCH 47/78] remove obsolete gesture from maui --- .../LiveChartsCore.SkiaSharpView.Maui/GeoMap.xaml.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/GeoMap.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/GeoMap.xaml.cs index 3dd7b1bc8..53d6acadb 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/GeoMap.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/GeoMap.xaml.cs @@ -249,10 +249,7 @@ private void PanGestureRecognizer_PanUpdated(object? sender, PanUpdatedEventArgs if (e.StatusType != GestureStatus.Running) return; var delta = new LvcPoint((float)e.TotalX, (float)e.TotalY); - var args = new PanGestureEventArgs(delta); - - _core.InvokePanGestrue(args); - if (!args.Handled) _core.Pan(delta); + _core.Pan(delta); } private void PinchGestureRecognizer_PinchUpdated(object? sender, PinchGestureUpdatedEventArgs e) From ba128e2b5a691758bf14acfe6e0174e2da42deaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 08:38:25 -0600 Subject: [PATCH 48/78] typo and ignore dominterop.js --- .gitignore | 1 + .../wwwroot/domInterop.js | 27 ------------------- 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/wwwroot/domInterop.js diff --git a/.gitignore b/.gitignore index 60c112fae..db1be2d94 100644 --- a/.gitignore +++ b/.gitignore @@ -350,3 +350,4 @@ nuget.exe # https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/strong-naming#create-strong-named-net-libraries *LiveCharts.snk build/pack.singed.ps1 +/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/wwwroot/domInterop.js diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/wwwroot/domInterop.js b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/wwwroot/domInterop.js deleted file mode 100644 index 60ac8a0eb..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/wwwroot/domInterop.js +++ /dev/null @@ -1,27 +0,0 @@ -export var DOMInterop; -(function (DOMInterop) { - function getBoundingClientRect(element) { - return element.getBoundingClientRect(); - } - DOMInterop.getBoundingClientRect = getBoundingClientRect; - function registerResizeListener(element, elementId) { - var observer = new ResizeObserver(function () { - DotNet.invokeMethodAsync('LiveChartsCore.SkiaSharpView.Blazor', 'InvokeResize', elementId, element.getBoundingClientRect()); - }); - observer.observe(element); - } - DOMInterop.registerResizeListener = registerResizeListener; - function setPosition(element, x, y, relativeTo) { - var rx = 0; - var ry = 0; - if (relativeTo) { - var bounds = relativeTo.getBoundingClientRect(); - rx = bounds.left; - ry = bounds.top; - } - element.style.top = (y + ry) + 'px'; - element.style.left = (x + rx) + 'px'; - } - DOMInterop.setPosition = setPosition; -})(DOMInterop || (DOMInterop = {})); -//# sourceMappingURL=domInterop.js.map \ No newline at end of file From ff537496c3ca02519b1711df7bbd7441fae22076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 08:41:06 -0600 Subject: [PATCH 49/78] typo --- docs/samples/lines/zoom/template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/samples/lines/zoom/template.md b/docs/samples/lines/zoom/template.md index 7a4def3e6..694ee58e7 100644 --- a/docs/samples/lines/zoom/template.md +++ b/docs/samples/lines/zoom/template.md @@ -32,7 +32,7 @@ On **Android** or **iOS**, pinch the screen in/out to zoom, hold tap and drag to {{~ end ~}} -{{~ uno || avalonia || blazor ~}} +{{~ if uno || avalonia || blazor ~}} :::tip On the **Browser**, use the mouse wheel to zoom in/out, hold click and drag to move the view (panning) (no touch devices yet). From 4374665995d455cad854e1e35c6d82a89b2aa69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 08:42:37 -0600 Subject: [PATCH 50/78] more typos --- docs/samples/lines/zoom/template.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/samples/lines/zoom/template.md b/docs/samples/lines/zoom/template.md index 694ee58e7..5242112bb 100644 --- a/docs/samples/lines/zoom/template.md +++ b/docs/samples/lines/zoom/template.md @@ -15,7 +15,7 @@ Use the mouse wheel to zoom in/out, hold click and drag to move the view (pannin {{~ end ~}} -{{~ maui || uno || avalonia ~}} +{{~ if maui || uno || avalonia ~}} :::tip On **Windows**, use the mouse wheel to zoom in/out, hold click and drag to move the view (panning). @@ -48,7 +48,7 @@ On the **Browser**, use the mouse wheel to zoom in/out, hold click and drag to m ## Form code behind {{~ end ~}} -{{~ if blazor~}} +{{~ if blazor ~}} ## HTML {{~ end~}} @@ -75,7 +75,7 @@ Right click on the chart, hold and drag to select an area on the chart. {{~ end ~}} -{{~ maui || uno || avalonia ~}} +{{~ if maui || uno || avalonia ~}} :::tip On **Windows**, right click on the chart, hold and drag to select an area on the chart. @@ -88,7 +88,7 @@ On **MacOS**, **Android** or **iOS** double click/tap the chart, hold the last c {{~ end ~}} -{{~ uno || avalonia || blazor ~}} +{{~ if uno || avalonia || blazor ~}} :::tip On the **Browser**, right click on the chart, hold and drag to select an area on the chart (no touch devices yet). From 7d85049635b41e876d5145097b55f0a0702459a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 09:51:05 -0600 Subject: [PATCH 51/78] remove condition from docs --- docs/cartesianChart/tooltips.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/cartesianChart/tooltips.md b/docs/cartesianChart/tooltips.md index 356104177..f50f2c803 100644 --- a/docs/cartesianChart/tooltips.md +++ b/docs/cartesianChart/tooltips.md @@ -8,8 +8,6 @@ Tooltips are popups that help the user to read a chart as the pointer moves. ![tooltips]({{ assets_url }}/docs/_assets/tooltips.gif) -{{~if !xamarin ~}} - ## Behaviour On **Windows** or **MacOS** you can move the pointer over the chart to display the tooltip, tooltips will be closed when the @@ -18,8 +16,6 @@ pointer leaves the chart area. On **Android** or **iOS** slide your finger over the chart to display the tooltip, the tooltip will be closed when the finger goes up. -{{~ end ~}} - ## TooltipPosition property You can place a tooltip at `Top`, `Bottom`, `Left`, `Right`, `Center` or `Hidden` positions, for now From 44e88f2ce03b318cf84f284d0e4de815ac81b4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 11:28:34 -0600 Subject: [PATCH 52/78] update pie series docs --- docs/_assets/pieMaxRadialCW.png | Bin 0 -> 32048 bytes docs/_assets/pieOuterRadiusOffset.png | Bin 0 -> 52061 bytes docs/piechart/pieseries.md | 28 +++++++++++++----- .../Pies/Doughnut/ViewModel.cs | 2 +- .../Kernel/Sketches/IPieSeries.cs | 3 +- 5 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 docs/_assets/pieMaxRadialCW.png create mode 100644 docs/_assets/pieOuterRadiusOffset.png diff --git a/docs/_assets/pieMaxRadialCW.png b/docs/_assets/pieMaxRadialCW.png new file mode 100644 index 0000000000000000000000000000000000000000..a6dc197074abf5705d5478d3faddf2d376171f40 GIT binary patch literal 32048 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 p4R5lKJ*y#4C-E?h;Gi|nC3A5vGE;n$Vs3F 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 literal 0 HcmV?d00001 diff --git a/docs/_assets/pieOuterRadiusOffset.png b/docs/_assets/pieOuterRadiusOffset.png new file mode 100644 index 0000000000000000000000000000000000000000..7e6bda95fbef8ec814341b9b516c1899c33df6f1 GIT binary patch literal 52061 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 Pn}CUn%7|17>H7U2g&C3g literal 0 HcmV?d00001 diff --git a/docs/piechart/pieseries.md b/docs/piechart/pieseries.md index caaa23875..b7a2b4009 100644 --- a/docs/piechart/pieseries.md +++ b/docs/piechart/pieseries.md @@ -191,28 +191,42 @@ It is the distance in pixels between the center of the control and the pie slice ![image]({{ assets_url }}/docs/_assets/piepushout.png) +## MaxRadialColumnWidth + +Sets the maximum value a radial column can take in pixels. + +
var pieSeries = new PieSeries<int>
+{
+    Values = new [] { ... },
+    MaxRadialColumnWidth = 50 // mark
+};
+ +![image]({{ assets_url }}/docs/_assets/pieInnerRadius.png) + ## InnerRadius property -The inner radius of the slice in pixels. +The inner radius of the slice in pixels, it is similar to the `MaxRadialColumnWidth` property, +both are useful to create doughnut charts, the difference is that `MaxRadialColumnWidth` is more flexible +on different screen sizes.
var pieSeries = new PieSeries<int>
 {
     Values = new [] { ... },
-    InnerRadius = 50 // mark 
+    InnerRadius = 50 // mark
 };
![image]({{ assets_url }}/docs/_assets/pieInnerRadius.png) -## MaxOuterRadius property +## OuterRadiusOffset property -Specifies the max radius (in percentage) the slice can take, the value goes from 0 to 1, where 1 is the full available radius and 0 is none, default is 1. +It is the distance from the maximum radius available to the end of the slice in pixels.
var pieSeries = new PieSeries<int>
 {
     Values = new [] { ... },
-    MaxOuterRadius = 0.8 // mark
+    OuterRadiusOffset = 20 // mark
 };
-![image]({{ assets_url }}/docs/_assets/piemaxoutter.png) +![image]({{ assets_url }}/docs/_assets/pieOuterRadiusOffset.png) -{{ render this "~/shared/series2.md" }} \ No newline at end of file +{{ render this "~/shared/series2.md" }} diff --git a/samples/ViewModelsSamples/Pies/Doughnut/ViewModel.cs b/samples/ViewModelsSamples/Pies/Doughnut/ViewModel.cs index c190993b3..39520ad48 100644 --- a/samples/ViewModelsSamples/Pies/Doughnut/ViewModel.cs +++ b/samples/ViewModelsSamples/Pies/Doughnut/ViewModel.cs @@ -11,6 +11,6 @@ public partial class ViewModel : ObservableObject public IEnumerable Series { get; set; } = new[] { 2, 4, 1, 4, 3 }.AsPieSeries((value, series) => { - series.InnerRadius = 50; + series.InnerRadius = 70; }); } diff --git a/src/LiveChartsCore/Kernel/Sketches/IPieSeries.cs b/src/LiveChartsCore/Kernel/Sketches/IPieSeries.cs index 70780bf53..d7dffe1f4 100644 --- a/src/LiveChartsCore/Kernel/Sketches/IPieSeries.cs +++ b/src/LiveChartsCore/Kernel/Sketches/IPieSeries.cs @@ -43,7 +43,8 @@ public interface IPieSeries : IChartSeries, IS double Pushout { get; set; } /// - /// Gets or sets the inner radius of the slice in pixels. + /// Gets or sets the inner radius of the slice in pixels, in most cases the + /// is preferred, because it is more flexible on different chart sizes. /// /// /// The inner radius. From 0ed773731fa3b6b9d0f5eb5799eea225c3cf4240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 12:02:05 -0600 Subject: [PATCH 53/78] more docs updates --- docs/piechart/pieseries.md | 2 +- docs/samples/events/cartesian/template.md | 4 +- docs/shared/genericSampleSimpleHeader.md | 4 +- docs/shared/series2.md | 157 ++-------------------- 4 files changed, 13 insertions(+), 154 deletions(-) diff --git a/docs/piechart/pieseries.md b/docs/piechart/pieseries.md index b7a2b4009..137a4ebe2 100644 --- a/docs/piechart/pieseries.md +++ b/docs/piechart/pieseries.md @@ -201,7 +201,7 @@ Sets the maximum value a radial column can take in pixels. MaxRadialColumnWidth = 50 // mark }; -![image]({{ assets_url }}/docs/_assets/pieInnerRadius.png) +![image]({{ assets_url }}/docs/_assets/pieMaxRadialCW.png) ## InnerRadius property diff --git a/docs/samples/events/cartesian/template.md b/docs/samples/events/cartesian/template.md index 412ef452b..6ed80e316 100644 --- a/docs/samples/events/cartesian/template.md +++ b/docs/samples/events/cartesian/template.md @@ -3,7 +3,7 @@ {{~ if xaml ~}} :::info -The `[ObservableObject]`, `[ObservableProperty]` and `[ICommand]` attributes come from the +The `[ObservableObject]`, `[ObservableProperty]` and `[RelayCommand]` attributes come from the [CommunityToolkit.Mvvm](https://www.nuget.org/packages/CommunityToolkit.Mvvm/) package, you can read more about it [here]({{ website_url }}/docs/{{ platform }}/{{ version }}/About.About%20this%20samples). ::: @@ -113,4 +113,4 @@ You could also detect the pointer down events/commands at the chart level but si {{~ end ~}} -{{~ end ~}} \ No newline at end of file +{{~ end ~}} diff --git a/docs/shared/genericSampleSimpleHeader.md b/docs/shared/genericSampleSimpleHeader.md index 7dd9f7f77..6b01a90a3 100644 --- a/docs/shared/genericSampleSimpleHeader.md +++ b/docs/shared/genericSampleSimpleHeader.md @@ -3,7 +3,7 @@ {{~ if xaml ~}} :::info -The `[ObservableObject]`, `[ObservableProperty]` and `[ICommand]` attributes come from the +The `[ObservableObject]`, `[ObservableProperty]` and `[RelayCommand]` attributes come from the [CommunityToolkit.Mvvm](https://www.nuget.org/packages/CommunityToolkit.Mvvm/) package, you can read more about it [here]({{ website_url }}/docs/{{ platform }}/{{ version }}/About.About%20this%20samples). ::: @@ -39,4 +39,4 @@ this sample also uses a ViewModel to populate the properties of the control(s) i
sample image -
\ No newline at end of file + diff --git a/docs/shared/series2.md b/docs/shared/series2.md index 472cd8cbd..a83aad6e6 100644 --- a/docs/shared/series2.md +++ b/docs/shared/series2.md @@ -1,153 +1,12 @@ ## Plotting custom types -You can teach LiveCharts to plot any type as soon as you let the library how to handle that object, there are -two ways of doing so: *Mappers* or *implementing `IChartEntity`*, mappers are quick to setup, implementing -`IChartEntity` is more performant and is the recommended way. - -**Mappers** - -```c# -public record TempSample(int Time, double Temperature, string Unit); - -var chart = new SKCartesianChart -{ - Width = 900, - Height = 600, - Series = new[] - { - new {{ name | to_title_case_no_spaces }} - { - Mapping = (sample, chartPoint) => - { - // use temperature as primary value (normally Y) - chartPoint.PrimaryValue = sample.Temperature; - // use time as secondary value (normally X) - chartPoint.SecondaryValue = sample.Time; - }, - Values = samples - } - }, - XAxes = new[] { new Axis { Labeler = value => $"{value} seconds" } }, - YAxes = new[] { new Axis { Labeler = value => $"{value} °C" } } -}; - -// ------------------------------------------------------------------- -// IMPORTANT NOTE -// ------------------------------------------------------------------- -// There are 2 special plots that use more than X and Y coordinates. - -// Weighted plots: HeatMaps and Bubble charts use 3 coordinates, X, Y and Weight. -// Mapping = (sample, chartPoint) => -// { -// chartPoint.PrimaryValue = sample.X; -// chartPoint.SecondaryValue = sample.Y; -// chartPoint.TertiaryValue = sample.Weigth; -// } - -// While financial Points use 5. -// Coordinate = new Coordinate(High, X, Open, Close, Low); -// Mapping = (sample, chartPoint) => -// { -// chartPoint.PrimaryValue = sample.High; -// chartPoint.SecondaryValue = sample.X; -// chartPoint.TertiaryValue = sample.Open; -// chartPoint.QuaternaryValue = sample.Close; -// chartPoint.QuinaryValue = sample.Low; -//} -``` - -**Implementing IChartEntity** -```c# -var chart = new SKCartesianChart -{ - Width = 900, - Height = 600, - Series = new[] - { - new LineSeries - { - Values = samples - } - }, - XAxes = new[] { new Axis { Labeler = value => $"{value} seconds" } }, - YAxes = new[] { new Axis { Labeler = value => $"{value} °C" } } -}; - -// this object uses the CommunityToolkit.Mvvm to implement INotifyPropertyChanged also -public partial class TempSample : ObservableObject, IChartEntity -{ - [ObservableProperty] - private int _time; - - [ObservableProperty] - private double _temperature; - - // Use the coordinate property to let LiveCharts know the position of the point. - public Coordinate Coordinate { get; protected set; } - - // The meta data property is used by LiveCharts to store info about the plot. - public ChartEntityMetaData? MetaData { get; set; } - - protected override void OnPropertyChanged(PropertyChangedEventArgs e) - { - Coordinate = new(Time, Temperature); - base.OnPropertyChanged(e); - } -} - -// ------------------------------------------------------------------- -// IMPORTANT NOTE -// ------------------------------------------------------------------- -// There are 2 special plots that use more than X and Y coordinates. - -// Weited plots: HeatMaps and Bubble charts use 3 coordinates, X, Y and Weight. -// Coordinate = new Coordinate(X, Y, Weight); -// https://github.com/beto-rodriguez/LiveCharts2/blob/master/src/LiveChartsCore/Defaults/WeightedPoint.cs - -// While financial Points use 5. -// Coordinate = new Coordinate(High, X, Open, Close, Low); -// https://github.com/beto-rodriguez/LiveCharts2/blob/master/src/LiveChartsCore/Defaults/FinancialPoint.cs -``` - - -See the full custom types article - +You can plot any type of data, please see the [mappers article]({{ website_url }}/docs/{{ platform }}/{{ version }}/Overview.Mappers) for more information. ## Custom geometries -You can use any geometry to represent a point in a series. - -
Series = new List<ISeries>
-{
-    // use the second argument type to specify the geometry to draw for every point
-    // there are already many predefined geometries in the
-    // LiveChartsCore.SkiaSharpView.Drawing.Geometries namespace
-    new {{ name  | to_title_case_no_spaces }}<double, RectangleGeometry>
-    {
-        Values = new double[] { 3, 3, -3, -2, -4, -3, -1 }
-    },
-
-    // you can also define your own SVG geometry
-    // MyGeometry class let us change the Path at runtime
-    // Click on the on any point to change the path.
-    // You can find the MyGeometry.cs file below
-    new {{ name  | to_title_case_no_spaces }}<double, MyGeometry>
-    {
-        Values = new double[] { -2, 2, 1, 3, -1, 4, 3 }
-    }
-
-    // Note: Depending on the series type, the geometry could require to satisfy some constrains
-};
-
-public class MyGeometry : LiveChartsCore.SkiaSharpView.Drawing.Geometries.SVGPathGeometry
-{
-    public MyGeometry()
-        : base(SVGPoints.Star)
-    { 
-        // the LiveChartsCore.SkiaSharpView.SVGPoints contains many predefined SVG paths
-        // you can also pass your own path there.
-    }
-}
+You can also customize the geometry for each point in a series, you can use the geometries defined on LiveCharts, SVG geometries +or draw your own using the SkiaSharp API, if you want to learn more please take a look at +[this article]({{ website_url }}/docs/{{ platform }}/{{ version }}/samples.lines.custom). ## ZIndex property @@ -167,7 +26,7 @@ If this property is not set, the library will set it according to the series typ
new LineSeries<double>
 {
-    DataPadding = new System.Drawing.PointF(0, 0),
+    DataPadding = new LvcPoint(0, 0),
     Values = new ObservableCollection { 2, 1, 3, 5, 3, 4, 6 },
     GeometryStroke = null,
     GeometryFill = null,
@@ -182,7 +41,7 @@ But you can remove the padding only from an axis, for example:
 
 
new LineSeries<double>
 {
-    DataPadding = new System.Drawing.PointF(0.5f, 0),
+    DataPadding = new LvcPoint(0.5f, 0),
     Values = new ObservableCollection<double> { 2, 1, 3, 5, 3, 4, 6 },
     GeometryStroke = null,
     GeometryFill = null,
@@ -195,11 +54,11 @@ Or you can increase the distance:
 
 
new LineSeries<double>
 {
-    DataPadding = new System.Drawing.PointF(2, 2),
+    DataPadding = new LvcPoint(2, 2),
     Values = new ObservableCollection<double> { 2, 1, 3, 5, 3, 4, 6 },
     GeometryStroke = null,
     GeometryFill = null,
     Fill = null
 }
-![image]({{ assets_url }}/docs/_assets/1.8.padding22.png) \ No newline at end of file +![image]({{ assets_url }}/docs/_assets/1.8.padding22.png) From 7ac7b71907d28856547e4c29a55dca300c9afa47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 12:07:26 -0600 Subject: [PATCH 54/78] 2.0.0-rc1 --- src/LiveChartsCore/LiveChartsCore.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.Avalonia.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.WPF.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.WinForms.csproj | 2 +- ...LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.Blazor.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.Eto.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.Maui.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.Maui.nuspec | 12 ++++++------ .../LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.Uno.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.WinUI.csproj | 2 +- .../LiveChartsCore.SkiaSharpView.WinUI.nuspec | 6 +++--- 14 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/LiveChartsCore/LiveChartsCore.csproj b/src/LiveChartsCore/LiveChartsCore.csproj index e9c55136e..b01a6cf90 100644 --- a/src/LiveChartsCore/LiveChartsCore.csproj +++ b/src/LiveChartsCore/LiveChartsCore.csproj @@ -17,7 +17,7 @@ LiveChartsCore LiveChartsCore - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for .Net, this is the core package probably you need another package also unless you are building your own backed. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj index 565d708e1..5ef6b2303 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj @@ -6,7 +6,7 @@ netcoreapp2.0;netstandard2.0;net462;net6.0 LiveChartsCore.SkiaSharpView.Avalonia LiveChartsCore.SkiaSharpView.Avalonia - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for AvaloniaUI. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsCore.SkiaSharpView.WPF.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsCore.SkiaSharpView.WPF.csproj index 59ed74409..b36a524c7 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsCore.SkiaSharpView.WPF.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsCore.SkiaSharpView.WPF.csproj @@ -7,7 +7,7 @@ net462;netcoreapp3.1 LiveChartsCore.SkiaSharpView.WPF LiveChartsCore.SkiaSharpView.WPF - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for WPF. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsCore.SkiaSharpView.WinForms.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsCore.SkiaSharpView.WinForms.csproj index 684b6e01f..a9a1e299e 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsCore.SkiaSharpView.WinForms.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsCore.SkiaSharpView.WinForms.csproj @@ -9,7 +9,7 @@ net462;netcoreapp3.1 LiveChartsCore.SkiaSharpView.WinForms LiveChartsCore.SkiaSharpView.WinForms - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for WindowsForms. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj index 1c82ada4f..2565daf40 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj @@ -6,7 +6,7 @@ netstandard2.0; LiveChartsCore.SkiaSharpView.XamarinForms LiveChartsCore.SkiaSharpView.XamarinForms - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for XamarinForms. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/LiveChartsCore.SkiaSharpView.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp/LiveChartsCore.SkiaSharpView.csproj index 28eeb2fec..d3a51224c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/LiveChartsCore.SkiaSharpView.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/LiveChartsCore.SkiaSharpView.csproj @@ -17,7 +17,7 @@ LiveChartsCore.SkiaSharpView LiveChartsCore.SkiaSharpView - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for .Net, this package contains the SkiaSharp backend. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveChartsCore.SkiaSharpView.Blazor.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveChartsCore.SkiaSharpView.Blazor.csproj index 5901fd489..8823523ca 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveChartsCore.SkiaSharpView.Blazor.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveChartsCore.SkiaSharpView.Blazor.csproj @@ -17,7 +17,7 @@ net6.0 enable enable - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for Blazor. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsCore.SkiaSharpView.Eto.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsCore.SkiaSharpView.Eto.csproj index 14dd4a3f8..b612c43a0 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsCore.SkiaSharpView.Eto.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsCore.SkiaSharpView.Eto.csproj @@ -7,7 +7,7 @@ netstandard2.0 LiveChartsCore.SkiaSharpView.Eto LiveChartsCore.SkiaSharpView.Eto - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for Eto.Forms. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj index 85da52d91..ad7e6f5d8 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj @@ -15,7 +15,7 @@ 10.0.17763.0 6.5 - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for Maui. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.nuspec b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.nuspec index b0e3873c1..1acd685e2 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.nuspec +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.nuspec @@ -2,7 +2,7 @@ LiveChartsCore.SkiaSharpView.Maui - 2.0.0-beta.950 + 2.0.0-rc1 LiveChartsCore.SkiaSharpView.Maui BetoRodriguez true @@ -17,23 +17,23 @@ - + - + - + - + - + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj index 917c395f4..f76bbd54e 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj @@ -7,7 +7,7 @@ enable 11.0 - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for Uno.WinUI. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/LiveChartsCore.SkiaSharpView.Uno.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/LiveChartsCore.SkiaSharpView.Uno.csproj index 44a36c1c6..ff6aa7054 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/LiveChartsCore.SkiaSharpView.Uno.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/LiveChartsCore.SkiaSharpView.Uno.csproj @@ -17,7 +17,7 @@ enable 11.0 - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for Uno. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/LiveChartsCore.SkiaSharpView.WinUI.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/LiveChartsCore.SkiaSharpView.WinUI.csproj index ebfb7dca4..fdf7959b0 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/LiveChartsCore.SkiaSharpView.WinUI.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/LiveChartsCore.SkiaSharpView.WinUI.csproj @@ -9,7 +9,7 @@ win10-x86;win10-x64;win10-arm64 true - 2.0.0-beta.950 + 2.0.0-rc1 icon.png Simple, flexible, interactive and powerful data visualization for WindowsAppSDK. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/LiveChartsCore.SkiaSharpView.WinUI.nuspec b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/LiveChartsCore.SkiaSharpView.WinUI.nuspec index 3a5360a45..dffa44e9c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/LiveChartsCore.SkiaSharpView.WinUI.nuspec +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/LiveChartsCore.SkiaSharpView.WinUI.nuspec @@ -2,7 +2,7 @@ LiveChartsCore.SkiaSharpView.WinUI - 2.0.0-beta.950 + 2.0.0-rc1 LiveChartsCore.SkiaSharpView.WinUI BetoRodriguez true @@ -18,8 +18,8 @@ - - + + From 59fe119ae86823b0cff835d455a22c6ba147d7e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 15:40:54 -0600 Subject: [PATCH 55/78] improves multi-line labels --- .../Drawing/Geometries/LabelGeometry.cs | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index 9f36764b8..bf9bbc28c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -34,6 +34,8 @@ public class LabelGeometry : Geometry, ILabelGeometry { private readonly FloatMotionProperty _textSizeProperty; private readonly ColorMotionProperty _backgroundProperty; + private float _maxTextHeight = 0f; + private int _lines; /// /// Initializes a new instance of the class. @@ -75,7 +77,7 @@ public LabelGeometry() public Padding Padding { get; set; } = new(); /// - public float LineHeight { get; set; } = 1.75f; + public float LineHeight { get; set; } = 1.45f; #if DEBUG /// @@ -87,30 +89,37 @@ public LabelGeometry() /// public override void OnDraw(SkiaSharpDrawingContext context, SKPaint paint) { - // it seems that skia allocates a lot of memory when drawing text - // for now we are not focused on performance, but this should be improved in the future - - // for a reason the text size is not set on the InitializeTask() method. context.Paint.TextSize = TextSize; var p = Padding; var bg = Background; + var size = OnMeasure(context.PaintTask); + var isFirstLine = true; - var verticalPos = 0f; + var verticalPos = + _lines > 1 + ? VerticalAlign switch // respect alignment on multiline labels + { + Align.Start => 0, + Align.Middle => -_lines * _maxTextHeight * 0.5f, + Align.End => -_lines * _maxTextHeight, + _ => 0 + } + : 0; + + var textBounds = new SKRect(); var shaper = paint.Typeface is not null ? new SKShaper(paint.Typeface) : null; foreach (var line in Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) { - var textBounds = new SKRect(); _ = context.Paint.MeasureText(line, ref textBounds); - var lhd = (textBounds.Height * LineHeight - textBounds.Height) * 0.5f; + var lhd = (textBounds.Height * LineHeight - _maxTextHeight) * 0.5f; var ao = GetAlignmentOffset(textBounds); if (isFirstLine && bg != LvcColor.Empty) { - var size = OnMeasure(context.PaintTask); var c = new SKColor(bg.R, bg.G, bg.B, (byte)(bg.A * Opacity)); using var bgPaint = new SKPaint { Color = c }; @@ -152,7 +161,7 @@ public override void OnDraw(SkiaSharpDrawingContext context, SKPaint paint) } #endif - verticalPos += textBounds.Height * LineHeight; + verticalPos += _maxTextHeight * LineHeight; isFirstLine = false; } @@ -178,15 +187,20 @@ protected override LvcSize OnMeasure(IPaint paint) var w = 0f; var h = 0f; + var bounds = new SKRect(); + _maxTextHeight = 0f; + _lines = 0; + foreach (var line in Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) { - var bounds = new SKRect(); _ = p.MeasureText(line, ref bounds); - if (bounds.Width > w) w = bounds.Width; - h += bounds.Height * LineHeight; + if (bounds.Height > _maxTextHeight) _maxTextHeight = bounds.Height; + _lines++; } + h = _maxTextHeight * _lines * LineHeight; + // Note #301222 // Disposing typefaces could cause render issues (Blazor) at least on SkiaSharp (2.88.3) // Could this cause memory leaks? From 19e4c4931f87d7e65bf4d87b40728683c65b91a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 20:43:03 -0600 Subject: [PATCH 56/78] complete label animations before measure --- src/LiveChartsCore/CartesianChart.cs | 3 ++- src/LiveChartsCore/Chart.cs | 3 ++- src/LiveChartsCore/ChartSeries.cs | 3 --- src/LiveChartsCore/ColumnSeries.cs | 5 +++++ src/LiveChartsCore/FinancialSeries.cs | 5 +++++ src/LiveChartsCore/HeatSeries.cs | 5 +++++ src/LiveChartsCore/Kernel/SeriesContext.cs | 9 ++++++++- .../Kernel/Sketches/IChartSeries.cs | 5 ----- src/LiveChartsCore/LineSeries.cs | 12 ++++++++---- src/LiveChartsCore/PieChart.cs | 3 ++- src/LiveChartsCore/PieSeries.cs | 18 +++++++----------- src/LiveChartsCore/PolarChart.cs | 3 ++- src/LiveChartsCore/PolarLineSeries.cs | 4 ++++ src/LiveChartsCore/RowSeries.cs | 5 +++++ src/LiveChartsCore/ScatterSeries.cs | 5 +++++ src/LiveChartsCore/StepLineSeries.cs | 15 ++++++++++----- 16 files changed, 70 insertions(+), 33 deletions(-) diff --git a/src/LiveChartsCore/CartesianChart.cs b/src/LiveChartsCore/CartesianChart.cs index ffc8caebe..5adf5a8cc 100644 --- a/src/LiveChartsCore/CartesianChart.cs +++ b/src/LiveChartsCore/CartesianChart.cs @@ -426,7 +426,7 @@ protected internal override void Measure() #endregion - SeriesContext = new SeriesContext(VisibleSeries); + SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw); var isNewTheme = LiveCharts.DefaultSettings.CurrentThemeId != ThemeId; // restart axes bounds and meta data @@ -840,6 +840,7 @@ protected internal override void Measure() ThemeId = LiveCharts.DefaultSettings.CurrentThemeId; Canvas.Invalidate(); + _isFirstDraw = false; } /// diff --git a/src/LiveChartsCore/Chart.cs b/src/LiveChartsCore/Chart.cs index 3918f3f5d..fdf625137 100644 --- a/src/LiveChartsCore/Chart.cs +++ b/src/LiveChartsCore/Chart.cs @@ -63,6 +63,7 @@ public abstract class Chart : IChart private readonly Dictionary _activePoints = new(); private LvcSize _previousSize = new(); private readonly bool _isMobile; + internal bool _isFirstDraw = true; #endregion @@ -184,7 +185,7 @@ protected Chart( /// /// The series context /// - public SeriesContext SeriesContext { get; protected set; } = new(Enumerable.Empty>()); + public SeriesContext SeriesContext { get; protected set; } = new(Enumerable.Empty>(), true); /// /// Gets the size of the control. diff --git a/src/LiveChartsCore/ChartSeries.cs b/src/LiveChartsCore/ChartSeries.cs index 6e9ebae86..80924cd9d 100644 --- a/src/LiveChartsCore/ChartSeries.cs +++ b/src/LiveChartsCore/ChartSeries.cs @@ -69,9 +69,6 @@ public IPaint? DataLabelsPaint /// public Padding DataLabelsPadding { get => _dataLabelsPadding; set => SetProperty(ref _dataLabelsPadding, value); } - /// - public bool IsFirstDraw { get; protected set; } = true; - void IChartSeries.OnDataPointerDown(IChartView chart, IEnumerable points, LvcPoint pointer) { OnDataPointerDown(chart, points, pointer); diff --git a/src/LiveChartsCore/ColumnSeries.cs b/src/LiveChartsCore/ColumnSeries.cs index 8fedf2e14..5c942a9a1 100644 --- a/src/LiveChartsCore/ColumnSeries.cs +++ b/src/LiveChartsCore/ColumnSeries.cs @@ -298,6 +298,11 @@ public override void Invalidate(Chart chart) label.Text = DataLabelsFormatter(new ChartPoint(point)); label.TextSize = dls; label.Padding = DataLabelsPadding; + + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var m = label.Measure(DataLabelsPaint); var labelPosition = GetLabelPosition( x, cy, helper.uw, b, m, diff --git a/src/LiveChartsCore/FinancialSeries.cs b/src/LiveChartsCore/FinancialSeries.cs index db808db66..ccd8f9d52 100644 --- a/src/LiveChartsCore/FinancialSeries.cs +++ b/src/LiveChartsCore/FinancialSeries.cs @@ -301,6 +301,11 @@ public override void Invalidate(Chart chart) label.Text = DataLabelsFormatter(new ChartPoint(point)); label.TextSize = dls; label.Padding = DataLabelsPadding; + + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var m = label.Measure(DataLabelsPaint); var labelPosition = GetLabelPosition( x, high, uw, Math.Abs(low - high), m, DataLabelsPosition, diff --git a/src/LiveChartsCore/HeatSeries.cs b/src/LiveChartsCore/HeatSeries.cs index 7f6f762be..5a321b24a 100644 --- a/src/LiveChartsCore/HeatSeries.cs +++ b/src/LiveChartsCore/HeatSeries.cs @@ -245,6 +245,11 @@ public override void Invalidate(Chart chart) label.Text = DataLabelsFormatter(new ChartPoint(point)); label.TextSize = dls; label.Padding = DataLabelsPadding; + + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var labelPosition = GetLabelPosition( secondary - uws * 0.5f + p.Left, primary - uwp * 0.5f + p.Top, uws - p.Left - p.Right, uwp - p.Top - p.Bottom, label.Measure(DataLabelsPaint), DataLabelsPosition, SeriesProperties, coordinate.PrimaryValue > Pivot, drawLocation, drawMarginSize); diff --git a/src/LiveChartsCore/Kernel/SeriesContext.cs b/src/LiveChartsCore/Kernel/SeriesContext.cs index 0e15e3411..44341d975 100644 --- a/src/LiveChartsCore/Kernel/SeriesContext.cs +++ b/src/LiveChartsCore/Kernel/SeriesContext.cs @@ -55,9 +55,11 @@ public class SeriesContext /// Initializes a new instance of the class. /// /// The series. - public SeriesContext(IEnumerable> series) + /// Indicates wether is the first timet he chart is drawn. + public SeriesContext(IEnumerable> series, bool isFirstDraw) { _series = series; + IsFirstDraw = isFirstDraw; } #region columns and rows @@ -265,4 +267,9 @@ private Stacker GetStacker(IChartSeries series } #endregion + + /// + /// Gets or sets a value indicating whether is first draw of the chart. + /// + public bool IsFirstDraw { get; set; } = true; } diff --git a/src/LiveChartsCore/Kernel/Sketches/IChartSeries.cs b/src/LiveChartsCore/Kernel/Sketches/IChartSeries.cs index 624cec34d..428c66eef 100644 --- a/src/LiveChartsCore/Kernel/Sketches/IChartSeries.cs +++ b/src/LiveChartsCore/Kernel/Sketches/IChartSeries.cs @@ -74,11 +74,6 @@ public interface IChartSeries : ISeries, IChartElement Sketch CanvasSchedule { get; } - /// - /// Gets a value indicating if this is the first time the series is drawn. - /// - bool IsFirstDraw { get; } - /// /// Gets the stack group, normally used internally to handled the stacked series. /// diff --git a/src/LiveChartsCore/LineSeries.cs b/src/LiveChartsCore/LineSeries.cs index f959f44a7..fb47d42ca 100644 --- a/src/LiveChartsCore/LineSeries.cs +++ b/src/LiveChartsCore/LineSeries.cs @@ -281,7 +281,7 @@ public override void Invalidate(Chart chart) visual = v; - if (IsFirstDraw) + if (chart.SeriesContext.IsFirstDraw) { v.Geometry.X = secondaryScale.ToPixels(coordinate.SecondaryValue); v.Geometry.Y = p; @@ -317,8 +317,8 @@ public override void Invalidate(Chart chart) visual.Bezier.Id = data.TargetPoint.Context.Entity.MetaData!.EntityIndex; - if (Fill is not null) fillVector!.AddConsecutiveSegment(visual.Bezier, !IsFirstDraw); - if (Stroke is not null) strokeVector!.AddConsecutiveSegment(visual.Bezier, !IsFirstDraw); + if (Fill is not null) fillVector!.AddConsecutiveSegment(visual.Bezier, !chart.SeriesContext.IsFirstDraw); + if (Stroke is not null) strokeVector!.AddConsecutiveSegment(visual.Bezier, !chart.SeriesContext.IsFirstDraw); visual.Bezier.Xi = secondaryScale.ToPixels(data.X0); visual.Bezier.Xm = secondaryScale.ToPixels(data.X1); @@ -391,6 +391,11 @@ public override void Invalidate(Chart chart) label.Text = DataLabelsFormatter(new ChartPoint(data.TargetPoint)); label.TextSize = dls; label.Padding = DataLabelsPadding; + + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var m = label.Measure(DataLabelsPaint); var labelPosition = GetLabelPosition( x - hgs, y - hgs, gs, gs, m, DataLabelsPosition, @@ -463,7 +468,6 @@ public override void Invalidate(Chart chart) pointsCleanup.CollectPoints( everFetched, cartesianChart.View, primaryScale, secondaryScale, SoftDeleteOrDisposePoint); - IsFirstDraw = false; _geometrySvgChanged = false; } diff --git a/src/LiveChartsCore/PieChart.cs b/src/LiveChartsCore/PieChart.cs index aff0af8ef..30607309f 100644 --- a/src/LiveChartsCore/PieChart.cs +++ b/src/LiveChartsCore/PieChart.cs @@ -156,7 +156,7 @@ protected internal override void Measure() AnimationsSpeed = _chartView.AnimationsSpeed; EasingFunction = _chartView.EasingFunction; - SeriesContext = new SeriesContext(VisibleSeries); + SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw); var isNewTheme = LiveCharts.DefaultSettings.CurrentThemeId != ThemeId; var theme = LiveCharts.DefaultSettings.GetTheme(); @@ -244,6 +244,7 @@ protected internal override void Measure() ThemeId = LiveCharts.DefaultSettings.CurrentThemeId; Canvas.Invalidate(); + _isFirstDraw = false; } /// diff --git a/src/LiveChartsCore/PieSeries.cs b/src/LiveChartsCore/PieSeries.cs index 1139b93e3..31750da90 100644 --- a/src/LiveChartsCore/PieSeries.cs +++ b/src/LiveChartsCore/PieSeries.cs @@ -198,7 +198,8 @@ public override void Invalidate(Chart chart) if (DataLabelsPaint is not null) { DataLabelsPaint.ZIndex = 1000 + actualZIndex + 0.3; - DataLabelsPaint.SetClipRectangle(pieChart.Canvas, new LvcRectangle(drawLocation, drawMarginSize)); + // this does not require clipping... + //DataLabelsPaint.SetClipRectangle(pieChart.Canvas, new LvcRectangle(drawLocation, drawMarginSize)); pieChart.Canvas.AddDrawableTask(DataLabelsPaint); } @@ -424,6 +425,10 @@ public override void Invalidate(Chart chart) AlignLabel(label, (float)start, initialRotation, sweep); + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var labelPosition = GetLabelPolarPosition( cx, cy, @@ -436,10 +441,6 @@ public override void Invalidate(Chart chart) label.X = labelPosition.X; label.Y = labelPosition.Y; - - if (IsFirstDraw) - label.CompleteTransition( - nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); } OnPointMeasured(point); @@ -450,7 +451,6 @@ public override void Invalidate(Chart chart) var u = new Scaler(); // dummy scaler, this is not used in the SoftDeleteOrDisposePoint method. pointsCleanup.CollectPoints(everFetched, pieChart.View, u, u, SoftDeleteOrDisposePoint); - IsFirstDraw = false; } /// @@ -664,6 +664,7 @@ private void AlignLabel(TLabel label, double start, double initialRotation, doub { case PolarLabelsPosition.Middle: case PolarLabelsPosition.ChartCenter: + case PolarLabelsPosition.Outer: label.HorizontalAlign = Align.Middle; label.VerticalAlign = Align.Middle; break; @@ -685,11 +686,6 @@ private void AlignLabel(TLabel label, double start, double initialRotation, doub label.HorizontalAlign = a1 > 180 ? Align.End : Align.Start; label.RotateTransform = (float)(a1 - c1); break; - case PolarLabelsPosition.Outer: - var a2 = start + initialRotation + sweep * 0.5; - var isStart = a2 % 360 is < 90 or (> 270 and < 360); - label.HorizontalAlign = label.HorizontalAlign = isStart ? Align.Start : Align.End; - break; default: break; } diff --git a/src/LiveChartsCore/PolarChart.cs b/src/LiveChartsCore/PolarChart.cs index ef43b3f9a..a047f763d 100644 --- a/src/LiveChartsCore/PolarChart.cs +++ b/src/LiveChartsCore/PolarChart.cs @@ -189,7 +189,7 @@ protected internal override void Measure() #endregion - SeriesContext = new SeriesContext(VisibleSeries); + SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw); var isNewTheme = LiveCharts.DefaultSettings.CurrentThemeId != ThemeId; // restart axes bounds and meta data @@ -516,6 +516,7 @@ protected internal override void Measure() ThemeId = LiveCharts.DefaultSettings.CurrentThemeId; Canvas.Invalidate(); + _isFirstDraw = false; } /// diff --git a/src/LiveChartsCore/PolarLineSeries.cs b/src/LiveChartsCore/PolarLineSeries.cs index 4aeddf5cf..e083a1cd9 100644 --- a/src/LiveChartsCore/PolarLineSeries.cs +++ b/src/LiveChartsCore/PolarLineSeries.cs @@ -395,6 +395,10 @@ public override void Invalidate(Chart chart) var rad = Math.Sqrt(Math.Pow(cp.X - scaler.CenterX, 2) + Math.Pow(cp.Y - scaler.CenterY, 2)); + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var labelPosition = GetLabelPolarPosition( scaler.CenterX, scaler.CenterY, (float)rad, scaler.GetAngle(coordinate.SecondaryValue), label.Measure(DataLabelsPaint), (float)GeometrySize, DataLabelsPosition); diff --git a/src/LiveChartsCore/RowSeries.cs b/src/LiveChartsCore/RowSeries.cs index e7b55e32e..3f527b9a1 100644 --- a/src/LiveChartsCore/RowSeries.cs +++ b/src/LiveChartsCore/RowSeries.cs @@ -301,6 +301,11 @@ public override void Invalidate(Chart chart) label.Text = DataLabelsFormatter(new ChartPoint(point)); label.TextSize = dls; label.Padding = DataLabelsPadding; + + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var m = label.Measure(DataLabelsPaint); var labelPosition = GetLabelPosition( cx, y, b, helper.uw, label.Measure(DataLabelsPaint), diff --git a/src/LiveChartsCore/ScatterSeries.cs b/src/LiveChartsCore/ScatterSeries.cs index dbc7da9fa..b222a7c8b 100644 --- a/src/LiveChartsCore/ScatterSeries.cs +++ b/src/LiveChartsCore/ScatterSeries.cs @@ -280,6 +280,11 @@ public override void Invalidate(Chart chart) label.Text = DataLabelsFormatter(new ChartPoint(point)); label.TextSize = dls; label.Padding = DataLabelsPadding; + + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var m = label.Measure(DataLabelsPaint); var labelPosition = GetLabelPosition( x - hgs, y - hgs, gs, gs, m, DataLabelsPosition, diff --git a/src/LiveChartsCore/StepLineSeries.cs b/src/LiveChartsCore/StepLineSeries.cs index bc989c58f..31bb3a578 100644 --- a/src/LiveChartsCore/StepLineSeries.cs +++ b/src/LiveChartsCore/StepLineSeries.cs @@ -1,4 +1,5 @@ -// The MIT License(MIT) + +// The MIT License(MIT) // // Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors // @@ -212,7 +213,7 @@ public override void Invalidate(Chart chart) var v = new StepLineVisualPoint(); visual = v; - if (IsFirstDraw) + if (chart.SeriesContext.IsFirstDraw) { v.Geometry.X = secondaryScale.ToPixels(coordinate.SecondaryValue); v.Geometry.Y = p; @@ -244,8 +245,8 @@ public override void Invalidate(Chart chart) visual.StepSegment.Id = point.Context.Entity.MetaData!.EntityIndex; - if (Fill is not null) fillVector.AddConsecutiveSegment(visual.StepSegment, !IsFirstDraw); - if (Stroke is not null) strokeVector.AddConsecutiveSegment(visual.StepSegment, !IsFirstDraw); + if (Fill is not null) fillVector.AddConsecutiveSegment(visual.StepSegment, !chart.SeriesContext.IsFirstDraw); + if (Stroke is not null) strokeVector.AddConsecutiveSegment(visual.StepSegment, !chart.SeriesContext.IsFirstDraw); visual.StepSegment.Xi = secondaryScale.ToPixels(coordinate.SecondaryValue - ds); visual.StepSegment.Xj = secondaryScale.ToPixels(coordinate.SecondaryValue); @@ -297,6 +298,11 @@ public override void Invalidate(Chart chart) label.Text = DataLabelsFormatter(new ChartPoint(point)); label.TextSize = dls; label.Padding = DataLabelsPadding; + + if (chart.SeriesContext.IsFirstDraw) + label.CompleteTransition( + nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform)); + var m = label.Measure(DataLabelsPaint); var labelPosition = GetLabelPosition( x - hgs, y - hgs, gs, gs, m, DataLabelsPosition, @@ -354,7 +360,6 @@ public override void Invalidate(Chart chart) pointsCleanup.CollectPoints( everFetched, cartesianChart.View, primaryScale, secondaryScale, SoftDeleteOrDisposePoint); - IsFirstDraw = false; _geometrySvgChanged = false; } From 1abd22bb67aa13247b802423fa069aaa3e1d1310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Sun, 10 Sep 2023 22:27:06 -0600 Subject: [PATCH 57/78] autocalculate pie outer labels space --- src/LiveChartsCore/BarSeries.cs | 2 +- src/LiveChartsCore/BoxSeries.cs | 2 +- src/LiveChartsCore/CartesianChart.cs | 7 +-- src/LiveChartsCore/Chart.cs | 17 ++---- src/LiveChartsCore/Kernel/Extensions.cs | 9 +++ src/LiveChartsCore/Kernel/SeriesContext.cs | 68 ++++++++++++++++++++-- src/LiveChartsCore/PieChart.cs | 8 +-- src/LiveChartsCore/PieSeries.cs | 8 ++- src/LiveChartsCore/PolarChart.cs | 8 +-- 9 files changed, 93 insertions(+), 36 deletions(-) diff --git a/src/LiveChartsCore/BarSeries.cs b/src/LiveChartsCore/BarSeries.cs index 8bbaf7bf5..3dc1c2f57 100644 --- a/src/LiveChartsCore/BarSeries.cs +++ b/src/LiveChartsCore/BarSeries.cs @@ -156,7 +156,7 @@ public MeasureHelper( else { pos = isRow - ? cartesianChart.SeriesContext.GetRowPostion(barSeries) + ? cartesianChart.SeriesContext.GetRowPosition(barSeries) : cartesianChart.SeriesContext.GetColumnPostion(barSeries); count = isRow ? cartesianChart.SeriesContext.GetRowSeriesCount() diff --git a/src/LiveChartsCore/BoxSeries.cs b/src/LiveChartsCore/BoxSeries.cs index a9b2029a3..0da676f93 100644 --- a/src/LiveChartsCore/BoxSeries.cs +++ b/src/LiveChartsCore/BoxSeries.cs @@ -475,7 +475,7 @@ public MeasureHelper( int pos, count; - pos = cartesianChart.SeriesContext.GetBoxPostion(boxSeries); + pos = cartesianChart.SeriesContext.GetBoxPosition(boxSeries); count = cartesianChart.SeriesContext.GetBoxSeriesCount(); cp = 0f; diff --git a/src/LiveChartsCore/CartesianChart.cs b/src/LiveChartsCore/CartesianChart.cs index 5adf5a8cc..de4581d44 100644 --- a/src/LiveChartsCore/CartesianChart.cs +++ b/src/LiveChartsCore/CartesianChart.cs @@ -392,7 +392,7 @@ protected internal override void Measure() if (_preserveFirstDraw) { - IsFirstDraw = true; + _isFirstDraw = true; _preserveFirstDraw = false; } @@ -426,7 +426,7 @@ protected internal override void Measure() #endregion - SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw); + SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw, this); var isNewTheme = LiveCharts.DefaultSettings.CurrentThemeId != ThemeId; // restart axes bounds and meta data @@ -836,7 +836,6 @@ protected internal override void Measure() InvokeOnUpdateStarted(); if (_isToolTipOpen) DrawToolTip(); - IsFirstDraw = false; ThemeId = LiveCharts.DefaultSettings.CurrentThemeId; Canvas.Invalidate(); @@ -848,7 +847,7 @@ public override void Unload() { base.Unload(); _crosshair = new(); - IsFirstDraw = true; + _isFirstDraw = true; } private LvcPoint? _sectionZoomingStart = null; diff --git a/src/LiveChartsCore/Chart.cs b/src/LiveChartsCore/Chart.cs index fdf625137..76049e0f2 100644 --- a/src/LiveChartsCore/Chart.cs +++ b/src/LiveChartsCore/Chart.cs @@ -140,14 +140,6 @@ protected Chart( /// public bool IsLoaded { get; internal set; } = false; - /// - /// Gets or sets a value indicating whether this it is the first draw of this instance. - /// - /// - /// true if this it is the first draw; otherwise, false. - /// - public bool IsFirstDraw { get; internal set; } = true; - /// /// Gets the canvas. /// @@ -185,7 +177,7 @@ protected Chart( /// /// The series context /// - public SeriesContext SeriesContext { get; protected set; } = new(Enumerable.Empty>(), true); + public SeriesContext SeriesContext { get; protected set; } = new(Enumerable.Empty>(), true, null!); /// /// Gets the size of the control. @@ -311,7 +303,7 @@ public virtual void Update(ChartUpdateParams? chartUpdateParams = null) public virtual void Load() { IsLoaded = true; - IsFirstDraw = true; + _isFirstDraw = true; Update(); } @@ -496,7 +488,7 @@ protected void UpdateBounds() ActualBounds.Location = DrawMarginLocation; ActualBounds.Size = DrawMarginSize; - if (IsFirstDraw) + if (_isFirstDraw) { ActualBounds.Animate(EasingFunction, AnimationsSpeed); _ = Canvas.Trackers.Add(ActualBounds); @@ -613,8 +605,7 @@ protected void DrawLegend(ref float ts, ref float bs, ref float ls, ref float rs } Legend.Draw(this); - - _preserveFirstDraw = IsFirstDraw; + _preserveFirstDraw = _isFirstDraw; } /// diff --git a/src/LiveChartsCore/Kernel/Extensions.cs b/src/LiveChartsCore/Kernel/Extensions.cs index e6f84bff4..f9513293f 100644 --- a/src/LiveChartsCore/Kernel/Extensions.cs +++ b/src/LiveChartsCore/Kernel/Extensions.cs @@ -454,6 +454,15 @@ public static bool IsFinancialSeries(this ISeries series) return (series.SeriesProperties & SeriesProperties.Financial) != 0; } + /// + /// Determines whether is a pie series. + /// + /// The series. + public static bool IsPieSeries(this ISeries series) + { + return (series.SeriesProperties & SeriesProperties.PieSeries) != 0; + } + /// /// Determines whether is bar series. /// diff --git a/src/LiveChartsCore/Kernel/SeriesContext.cs b/src/LiveChartsCore/Kernel/SeriesContext.cs index 44341d975..74786af66 100644 --- a/src/LiveChartsCore/Kernel/SeriesContext.cs +++ b/src/LiveChartsCore/Kernel/SeriesContext.cs @@ -20,7 +20,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System; using System.Collections.Generic; +using System.Linq; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel.Sketches; using LiveChartsCore.Measure; @@ -42,6 +44,8 @@ public class SeriesContext private int _stackedColumnsCount = 0; private int _stackedRowsCount = 0; private bool _areBarsIndexed = false; + private bool _arePieLabeleMeasured = false; + private float _pieLabelsSize = 0f; private readonly Dictionary, int> _columnPositions = new(); private readonly Dictionary, int> _rowPositions = new(); @@ -51,15 +55,19 @@ public class SeriesContext private readonly Dictionary> _stackers = new(); + private readonly IChart _chart; + /// /// Initializes a new instance of the class. /// /// The series. - /// Indicates wether is the first timet he chart is drawn. - public SeriesContext(IEnumerable> series, bool isFirstDraw) + /// Indicates whether is the first time the chart is drawn. + /// The chart + public SeriesContext(IEnumerable> series, bool isFirstDraw, IChart chart) { _series = series; IsFirstDraw = isFirstDraw; + _chart = chart; } #region columns and rows @@ -68,7 +76,6 @@ public SeriesContext(IEnumerable> series, bool isF /// Gets the column position. /// /// The series. - /// public int GetColumnPostion(IChartSeries series) { if (_areBarsIndexed) return _columnPositions[series]; @@ -79,7 +86,6 @@ public int GetColumnPostion(IChartSeries series) /// /// Gets the column series count. /// - /// public int GetColumnSeriesCount() { if (_areBarsIndexed) return _columnsCount; @@ -87,12 +93,23 @@ public int GetColumnSeriesCount() return _columnsCount; } + /// + /// Gets the required space by the labels to the outer side of the pie chart. + /// + public float GetPieOuterLabelsSpace() + where TLabel : class, ILabelGeometry, new() + { + if (_arePieLabeleMeasured) return _pieLabelsSize; + CalculatePieLabelsOuterSpace(); + return _pieLabelsSize; + } + /// /// Gets the row position. /// /// The series. /// - public int GetRowPostion(IChartSeries series) + public int GetRowPosition(IChartSeries series) { if (_areBarsIndexed) return _rowPositions[series]; IndexBars(); @@ -115,7 +132,7 @@ public int GetRowSeriesCount() /// /// The series. /// - public int GetBoxPostion(IChartSeries series) + public int GetBoxPosition(IChartSeries series) { if (_areBarsIndexed) return _boxPositions[series]; IndexBars(); @@ -268,6 +285,45 @@ private Stacker GetStacker(IChartSeries series #endregion + #region Pie + + private void CalculatePieLabelsOuterSpace() + where TLabel : class, ILabelGeometry, new() + { + foreach (var series in _series) + { + if (!series.IsPieSeries()) continue; + var pieSeries = (IPieSeries)series; + if (pieSeries.DataLabelsPosition != PolarLabelsPosition.Outer) continue; + if (series.DataLabelsPaint is null) continue; + + var r = (float)series.DataLabelsRotation; + var label = new TLabel { RotateTransform = r }; + // TODO: what about with tangent and cotangent angles? + + var stacker = GetStackPosition(series, series.GetStackGroup()) + ?? throw new NullReferenceException("Unexpected null stacker"); + + foreach (var point in pieSeries.Fetch(_chart)) + { + _ = stacker.GetStack(point); // builds the stacked value for the point. + + label.Text = pieSeries.GetDataLabelText(point) ?? string.Empty; + label.TextSize = (float)series.DataLabelsSize; + label.Padding = series.DataLabelsPadding; + label.RotateTransform = r; + var labelSize = label.Measure(series.DataLabelsPaint); + + var h = 1.5f * (float)Math.Sqrt(Math.Pow(labelSize.Width, 2) + Math.Pow(labelSize.Height, 2)); + if (h > _pieLabelsSize) _pieLabelsSize = h; + } + } + + _arePieLabeleMeasured = true; + } + + #endregion + /// /// Gets or sets a value indicating whether is first draw of the chart. /// diff --git a/src/LiveChartsCore/PieChart.cs b/src/LiveChartsCore/PieChart.cs index 30607309f..75f8de307 100644 --- a/src/LiveChartsCore/PieChart.cs +++ b/src/LiveChartsCore/PieChart.cs @@ -136,7 +136,7 @@ protected internal override void Measure() if (_preserveFirstDraw) { - IsFirstDraw = true; + _isFirstDraw = true; _preserveFirstDraw = false; } @@ -156,7 +156,7 @@ protected internal override void Measure() AnimationsSpeed = _chartView.AnimationsSpeed; EasingFunction = _chartView.EasingFunction; - SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw); + SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw, this); var isNewTheme = LiveCharts.DefaultSettings.CurrentThemeId != ThemeId; var theme = LiveCharts.DefaultSettings.GetTheme(); @@ -240,7 +240,7 @@ protected internal override void Measure() if (_isToolTipOpen) DrawToolTip(); InvokeOnUpdateStarted(); - IsFirstDraw = false; + _isFirstDraw = false; ThemeId = LiveCharts.DefaultSettings.CurrentThemeId; Canvas.Invalidate(); @@ -251,6 +251,6 @@ protected internal override void Measure() public override void Unload() { base.Unload(); - IsFirstDraw = true; + _isFirstDraw = true; } } diff --git a/src/LiveChartsCore/PieSeries.cs b/src/LiveChartsCore/PieSeries.cs index 31750da90..b34011011 100644 --- a/src/LiveChartsCore/PieSeries.cs +++ b/src/LiveChartsCore/PieSeries.cs @@ -172,6 +172,9 @@ public override void Invalidate(Chart chart) var maxOuterRadius = (float)MaxOuterRadius; minDimension *= maxOuterRadius; + var pieLabelsCorrection = chart.SeriesContext.GetPieOuterLabelsSpace(); + minDimension -= pieLabelsCorrection; + var outerRadiusOffset = (float)OuterRadiusOffset; minDimension -= outerRadiusOffset; @@ -345,7 +348,7 @@ public override void Invalidate(Chart chart) Y = cy, Width = 0, Height = 0, - StartAngle = (float)(pieChart.IsFirstDraw ? initialRotation : start + initialRotation), + StartAngle = (float)(chart.SeriesContext.IsFirstDraw ? initialRotation : start + initialRotation), SweepAngle = 0, PushOut = 0, InnerRadius = 0, @@ -608,8 +611,7 @@ protected virtual LvcPoint GetLabelPolarPosition( break; case PolarLabelsPosition.Outer: angle = startAngle + sweepAngle * 0.5f; - radius = outerRadius - + 0.5f * (float)Math.Sqrt(Math.Pow(labelSize.Width, 2) + Math.Pow(labelSize.Height, 2)); + radius = outerRadius + 0.45f * (float)Math.Sqrt(Math.Pow(labelSize.Width, 2) + Math.Pow(labelSize.Height, 2)); break; case PolarLabelsPosition.Middle: var f = (SeriesProperties & SeriesProperties.Gauge) != 0 ? 0.5f : 0.65f; diff --git a/src/LiveChartsCore/PolarChart.cs b/src/LiveChartsCore/PolarChart.cs index a047f763d..c18af232b 100644 --- a/src/LiveChartsCore/PolarChart.cs +++ b/src/LiveChartsCore/PolarChart.cs @@ -155,7 +155,7 @@ protected internal override void Measure() if (_preserveFirstDraw) { - IsFirstDraw = true; + _isFirstDraw = true; _preserveFirstDraw = false; } @@ -189,7 +189,7 @@ protected internal override void Measure() #endregion - SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw); + SeriesContext = new SeriesContext(VisibleSeries, _isFirstDraw, this); var isNewTheme = LiveCharts.DefaultSettings.CurrentThemeId != ThemeId; // restart axes bounds and meta data @@ -512,7 +512,7 @@ protected internal override void Measure() InvokeOnUpdateStarted(); if (_isToolTipOpen) DrawToolTip(); - IsFirstDraw = false; + _isFirstDraw = false; ThemeId = LiveCharts.DefaultSettings.CurrentThemeId; Canvas.Invalidate(); @@ -544,6 +544,6 @@ public double[] ScaleUIPoint(LvcPoint point, int angleAxisIndex = 0, int radiusA public override void Unload() { base.Unload(); - IsFirstDraw = true; + _isFirstDraw = true; } } From 9a60f5b7690ebb61bd4b6ab7253eb14441c70018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 11 Sep 2023 18:19:43 -0600 Subject: [PATCH 58/78] fixes an issue where labelvisual was not measured properly --- src/LiveChartsCore/VisualElements/LabelVisual.cs | 3 ++- .../Drawing/Geometries/LabelGeometry.cs | 7 +++---- .../SKCharts/InMemorySkiaSharpChart.cs | 2 +- .../OtherTests/VisualElementsTests.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/LiveChartsCore/VisualElements/LabelVisual.cs b/src/LiveChartsCore/VisualElements/LabelVisual.cs index d6195ad7d..3d30f75fc 100644 --- a/src/LiveChartsCore/VisualElements/LabelVisual.cs +++ b/src/LiveChartsCore/VisualElements/LabelVisual.cs @@ -44,7 +44,7 @@ public class LabelVisual : VisualElement /// Gets or sets the fill paint. @@ -163,6 +163,7 @@ public override LvcSize Measure(Chart chart) _labelGeometry.HorizontalAlign = HorizontalAlignment; _labelGeometry.Background = BackgroundColor; _labelGeometry.Padding = Padding; + _labelGeometry.LineHeight = LineHeight; return _paint is null ? new LvcSize() diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index bf9bbc28c..0c90f405e 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -185,21 +185,20 @@ protected override LvcSize OnMeasure(IPaint paint) }; var w = 0f; - var h = 0f; - - var bounds = new SKRect(); _maxTextHeight = 0f; _lines = 0; foreach (var line in Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) { + var bounds = new SKRect(); _ = p.MeasureText(line, ref bounds); + if (bounds.Width > w) w = bounds.Width; if (bounds.Height > _maxTextHeight) _maxTextHeight = bounds.Height; _lines++; } - h = _maxTextHeight * _lines * LineHeight; + var h = _maxTextHeight * _lines * LineHeight; // Note #301222 // Disposing typefaces could cause render issues (Blazor) at least on SkiaSharp (2.88.3) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs index 73e800da2..f0da04fe1 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs @@ -126,7 +126,7 @@ public virtual void DrawOnCanvas(SKCanvas canvas, SKSurface? surface = null, boo skiaChart.Canvas.DisableAnimations = true; skiaChart.IsLoaded = true; - skiaChart.IsFirstDraw = true; + skiaChart._isFirstDraw = true; skiaChart.Measure(); skiaChart.Canvas.DrawFrame( diff --git a/tests/LiveChartsCore.UnitTesting/OtherTests/VisualElementsTests.cs b/tests/LiveChartsCore.UnitTesting/OtherTests/VisualElementsTests.cs index 0e125cca0..fcebc9ab7 100644 --- a/tests/LiveChartsCore.UnitTesting/OtherTests/VisualElementsTests.cs +++ b/tests/LiveChartsCore.UnitTesting/OtherTests/VisualElementsTests.cs @@ -69,7 +69,7 @@ void Draw() chart.CoreCanvas.DisableAnimations = true; coreChart.IsLoaded = true; - coreChart.IsFirstDraw = true; + coreChart._isFirstDraw = true; coreChart.Measure(); using var surface = SKSurface.Create(new SKImageInfo(chart.Width, chart.Height)); From 982cb8c813f5032c80a3144536012d89363b1c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 11 Sep 2023 18:36:17 -0600 Subject: [PATCH 59/78] fixes test --- .../LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs index c690d763b..823a0c1de 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs @@ -130,6 +130,7 @@ public void ShouldPlaceToolTips() YToolTipLabelFormatter = x => $"{x.Coordinate.PrimaryValue}" + $"{Environment.NewLine}{x.Coordinate.PrimaryValue}" + + $"{Environment.NewLine}{x.Coordinate.PrimaryValue}" + $"{Environment.NewLine}{x.Coordinate.PrimaryValue}", }; @@ -196,7 +197,6 @@ public void ShouldPlaceToolTips() chart.Core._pointerPosition = new(300 * 4 / 5d, 300 * 1 / 5d); _ = chart.GetImage(); - chart.SaveImage("testme.png"); Assert.IsTrue( Math.Abs(tp.X - (300 * 3 / 4d - tp.Width * 0.5f)) < 0.1 && Math.Abs(tp.Y - 300 * 1 / 4d) < 0.1 && From c90b43e96c59e4cabd3b65376b18fbcda276b965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 11 Sep 2023 20:43:05 -0600 Subject: [PATCH 60/78] typo --- samples/ViewModelsSamples/Pies/Basic/ViewModel.cs | 2 +- samples/ViewModelsSamples/Pies/Custom/ViewModel.cs | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/samples/ViewModelsSamples/Pies/Basic/ViewModel.cs b/samples/ViewModelsSamples/Pies/Basic/ViewModel.cs index a8965d308..29999b414 100644 --- a/samples/ViewModelsSamples/Pies/Basic/ViewModel.cs +++ b/samples/ViewModelsSamples/Pies/Basic/ViewModel.cs @@ -11,7 +11,7 @@ namespace ViewModelsSamples.Pies.Basic; public partial class ViewModel : ObservableObject { - // you can convert any array, list or IEnnumerable to a pie series collection: + // you can convert any array, list or IEnumerable to a pie series collection: public IEnumerable Series { get; set; } = new[] { 2, 4, 1, 4, 3 }.AsPieSeries(); diff --git a/samples/ViewModelsSamples/Pies/Custom/ViewModel.cs b/samples/ViewModelsSamples/Pies/Custom/ViewModel.cs index 6f645fcdf..6e07a9aa9 100644 --- a/samples/ViewModelsSamples/Pies/Custom/ViewModel.cs +++ b/samples/ViewModelsSamples/Pies/Custom/ViewModel.cs @@ -20,13 +20,10 @@ public ViewModel() { // this method is called once per element in the array, so: - // for the series with the value 6, we set the outer radius to 1 - // for the series with the value 5, the outer radius is 0.9 - // for the series with the value 4, the outer radius is 0.8 - // for the series with the value 3, the outer radius is 0.7 - - // The MaxOuterRadius property sets the maximum outer, the value goes from - // 0 to 1, where 1 is the full available radius and 0 is none. + // for the series with the value 6, we set the OuterRadiusOffset to 0 + // for the series with the value 5, the OuterRadiusOffset is 50 + // for the series with the value 4, the OuterRadiusOffset is 100 + // for the series with the value 3, the OuterRadiusOffset is 150 series.OuterRadiusOffset = outer; outer += 50; From fa19edd2d249e25828c1a0d216ac7705e69f970e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 11 Sep 2023 21:51:18 -0600 Subject: [PATCH 61/78] add outlabels sample --- .../AvaloniaSample/Pies/OutLabels/View.axaml | 16 +++++ .../Pies/OutLabels/View.axaml.cs | 17 ++++++ .../BlazorSample/Pages/Pies/OutLabels.razor | 13 ++++ samples/EtoFormsSample/Pies/OutLabels/View.cs | 24 ++++++++ samples/MauiSample/Pies/OutLabels/View.xaml | 16 +++++ .../MauiSample/Pies/OutLabels/View.xaml.cs | 10 ++++ samples/UWPSample/Pies/OutLabels/View.xaml | 17 ++++++ samples/UWPSample/Pies/OutLabels/View.xaml.cs | 12 ++++ samples/UWPSample/UWPSample.csproj | 7 +++ .../Pies/OutLabels/View.xaml | 17 ++++++ .../Pies/OutLabels/View.xaml.cs | 11 ++++ samples/ViewModelsSamples/Index.cs | 1 + .../Pies/OutLabels/ViewModel.cs | 28 +++++++++ samples/WPFSample/Pies/OutLabels/View.xaml | 14 +++++ samples/WPFSample/Pies/OutLabels/View.xaml.cs | 14 +++++ .../Pies/OutLabels/View.Designer.cs | 46 ++++++++++++++ samples/WinFormsSample/Pies/OutLabels/View.cs | 32 ++++++++++ .../WinFormsSample/Pies/OutLabels/View.resx | 60 +++++++++++++++++++ .../WinUISample/Pies/OutLabels/View.xaml | 22 +++++++ .../WinUISample/Pies/OutLabels/View.xaml.cs | 11 ++++ .../XamarinSample/Pies/OutLabels/View.xaml | 15 +++++ .../XamarinSample/Pies/OutLabels/View.xaml.cs | 13 ++++ 22 files changed, 416 insertions(+) create mode 100644 samples/AvaloniaSample/Pies/OutLabels/View.axaml create mode 100644 samples/AvaloniaSample/Pies/OutLabels/View.axaml.cs create mode 100644 samples/BlazorSample/Pages/Pies/OutLabels.razor create mode 100644 samples/EtoFormsSample/Pies/OutLabels/View.cs create mode 100644 samples/MauiSample/Pies/OutLabels/View.xaml create mode 100644 samples/MauiSample/Pies/OutLabels/View.xaml.cs create mode 100644 samples/UWPSample/Pies/OutLabels/View.xaml create mode 100644 samples/UWPSample/Pies/OutLabels/View.xaml.cs create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/OutLabels/View.xaml create mode 100644 samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/OutLabels/View.xaml.cs create mode 100644 samples/ViewModelsSamples/Pies/OutLabels/ViewModel.cs create mode 100644 samples/WPFSample/Pies/OutLabels/View.xaml create mode 100644 samples/WPFSample/Pies/OutLabels/View.xaml.cs create mode 100644 samples/WinFormsSample/Pies/OutLabels/View.Designer.cs create mode 100644 samples/WinFormsSample/Pies/OutLabels/View.cs create mode 100644 samples/WinFormsSample/Pies/OutLabels/View.resx create mode 100644 samples/WinUISample/WinUISample/Pies/OutLabels/View.xaml create mode 100644 samples/WinUISample/WinUISample/Pies/OutLabels/View.xaml.cs create mode 100644 samples/XamarinSample/XamarinSample/XamarinSample/Pies/OutLabels/View.xaml create mode 100644 samples/XamarinSample/XamarinSample/XamarinSample/Pies/OutLabels/View.xaml.cs diff --git a/samples/AvaloniaSample/Pies/OutLabels/View.axaml b/samples/AvaloniaSample/Pies/OutLabels/View.axaml new file mode 100644 index 000000000..ebdad9302 --- /dev/null +++ b/samples/AvaloniaSample/Pies/OutLabels/View.axaml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/samples/AvaloniaSample/Pies/OutLabels/View.axaml.cs b/samples/AvaloniaSample/Pies/OutLabels/View.axaml.cs new file mode 100644 index 000000000..dd264229d --- /dev/null +++ b/samples/AvaloniaSample/Pies/OutLabels/View.axaml.cs @@ -0,0 +1,17 @@ +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace AvaloniaSample.Pies.OutLabels; + +public partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } +} diff --git a/samples/BlazorSample/Pages/Pies/OutLabels.razor b/samples/BlazorSample/Pages/Pies/OutLabels.razor new file mode 100644 index 000000000..7052ae4a1 --- /dev/null +++ b/samples/BlazorSample/Pages/Pies/OutLabels.razor @@ -0,0 +1,13 @@ +@page "/Pies/OutLabels" +@using LiveChartsCore.SkiaSharpView.Blazor +@using ViewModelsSamples.Pies.OutLabels + + + + +@code { + public ViewModel ViewModel { get; set; } = new(); +} diff --git a/samples/EtoFormsSample/Pies/OutLabels/View.cs b/samples/EtoFormsSample/Pies/OutLabels/View.cs new file mode 100644 index 000000000..67e77bc4d --- /dev/null +++ b/samples/EtoFormsSample/Pies/OutLabels/View.cs @@ -0,0 +1,24 @@ +using Eto.Forms; +using LiveChartsCore.SkiaSharpView.Eto; +using ViewModelsSamples.Pies.OutLabels; + +namespace EtoFormsSample.Pies.OutLabels; + +public class View : Panel +{ + private readonly PieChart pieChart; + + public View() + { + var viewModel = new ViewModel(); + + pieChart = new PieChart + { + Series = viewModel.Series, + IsClockwise = false, + InitialRotation = -90 + }; + + Content = pieChart; + } +} diff --git a/samples/MauiSample/Pies/OutLabels/View.xaml b/samples/MauiSample/Pies/OutLabels/View.xaml new file mode 100644 index 000000000..7405de3fa --- /dev/null +++ b/samples/MauiSample/Pies/OutLabels/View.xaml @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/samples/MauiSample/Pies/OutLabels/View.xaml.cs b/samples/MauiSample/Pies/OutLabels/View.xaml.cs new file mode 100644 index 000000000..2c47872a3 --- /dev/null +++ b/samples/MauiSample/Pies/OutLabels/View.xaml.cs @@ -0,0 +1,10 @@ +namespace MauiSample.Pies.OutLabels; + +[XamlCompilation(XamlCompilationOptions.Compile)] +public partial class View : ContentPage +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/UWPSample/Pies/OutLabels/View.xaml b/samples/UWPSample/Pies/OutLabels/View.xaml new file mode 100644 index 000000000..de71ca8f8 --- /dev/null +++ b/samples/UWPSample/Pies/OutLabels/View.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/samples/UWPSample/Pies/OutLabels/View.xaml.cs b/samples/UWPSample/Pies/OutLabels/View.xaml.cs new file mode 100644 index 000000000..d2e45f45d --- /dev/null +++ b/samples/UWPSample/Pies/OutLabels/View.xaml.cs @@ -0,0 +1,12 @@ +using Windows.UI.Xaml.Controls; + +namespace UWPSample.Pies.OutLabels +{ + public sealed partial class View : UserControl + { + public View() + { + InitializeComponent(); + } + } +} diff --git a/samples/UWPSample/UWPSample.csproj b/samples/UWPSample/UWPSample.csproj index 89b42906a..69a922a11 100644 --- a/samples/UWPSample/UWPSample.csproj +++ b/samples/UWPSample/UWPSample.csproj @@ -310,6 +310,9 @@ View.xaml + + View.xaml + View.xaml @@ -686,6 +689,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/OutLabels/View.xaml b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/OutLabels/View.xaml new file mode 100644 index 000000000..57526cd20 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/OutLabels/View.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/OutLabels/View.xaml.cs b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/OutLabels/View.xaml.cs new file mode 100644 index 000000000..44a3ff4d0 --- /dev/null +++ b/samples/UnoPlatformSample/UnoPlatformSample/LiveChartsSamples/Pies/OutLabels/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace UnoWinUISample.Pies.OutLabels; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/ViewModelsSamples/Index.cs b/samples/ViewModelsSamples/Index.cs index fee75eeaf..1c11e98aa 100644 --- a/samples/ViewModelsSamples/Index.cs +++ b/samples/ViewModelsSamples/Index.cs @@ -46,6 +46,7 @@ public static class Index "Pies/Doughnut", "Pies/Pushout", "Pies/Custom", + "Pies/OutLabels", "Pies/NightingaleRose", "Pies/Gauges", //"Pies/Gauge", diff --git a/samples/ViewModelsSamples/Pies/OutLabels/ViewModel.cs b/samples/ViewModelsSamples/Pies/OutLabels/ViewModel.cs new file mode 100644 index 000000000..3454a6079 --- /dev/null +++ b/samples/ViewModelsSamples/Pies/OutLabels/ViewModel.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using LiveChartsCore; +using CommunityToolkit.Mvvm.ComponentModel; +using LiveChartsCore.SkiaSharpView.Painting; +using SkiaSharp; +using LiveChartsCore.SkiaSharpView.Extensions; +using System; + +namespace ViewModelsSamples.Pies.OutLabels; + +public partial class ViewModel : ObservableObject +{ + public IEnumerable Series { get; set; } = + new[] { 8, 6, 5, 3, 3 }.AsPieSeries((value, series) => + { + series.DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.Outer; // mark + series.DataLabelsSize = 15; + series.DataLabelsPaint = new SolidColorPaint(new SKColor(30, 30, 30)); + series.DataLabelsFormatter = + point => + $"This slide takes{Environment.NewLine}" + + $"{point.Coordinate.PrimaryValue} out of {point.StackedValue!.Total} parts"; + }); + + // add some margin to the chart so the labels can be drawn // mark + public LiveChartsCore.Measure.Margin DrawMargin { get; set; } = + new LiveChartsCore.Measure.Margin(0); +} diff --git a/samples/WPFSample/Pies/OutLabels/View.xaml b/samples/WPFSample/Pies/OutLabels/View.xaml new file mode 100644 index 000000000..b7b9f2483 --- /dev/null +++ b/samples/WPFSample/Pies/OutLabels/View.xaml @@ -0,0 +1,14 @@ + + + + + + + diff --git a/samples/WPFSample/Pies/OutLabels/View.xaml.cs b/samples/WPFSample/Pies/OutLabels/View.xaml.cs new file mode 100644 index 000000000..8efa67b2a --- /dev/null +++ b/samples/WPFSample/Pies/OutLabels/View.xaml.cs @@ -0,0 +1,14 @@ +using System.Windows.Controls; + +namespace WPFSample.Pies.OutLabels; + +/// +/// Interaction logic for View.xaml +/// +public partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/WinFormsSample/Pies/OutLabels/View.Designer.cs b/samples/WinFormsSample/Pies/OutLabels/View.Designer.cs new file mode 100644 index 000000000..1d661bdab --- /dev/null +++ b/samples/WinFormsSample/Pies/OutLabels/View.Designer.cs @@ -0,0 +1,46 @@ + +namespace WinFormsSample.Pies.OutLabels +{ + partial class View + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // View + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Name = "View"; + this.Size = new System.Drawing.Size(427, 375); + this.ResumeLayout(false); + + } + + #endregion + } +} diff --git a/samples/WinFormsSample/Pies/OutLabels/View.cs b/samples/WinFormsSample/Pies/OutLabels/View.cs new file mode 100644 index 000000000..6ce916cde --- /dev/null +++ b/samples/WinFormsSample/Pies/OutLabels/View.cs @@ -0,0 +1,32 @@ +using System.Windows.Forms; +using LiveChartsCore.SkiaSharpView.WinForms; +using ViewModelsSamples.Pies.OutLabels; + +namespace WinFormsSample.Pies.OutLabels; + +public partial class View : UserControl +{ + private readonly PieChart pieChart; + + public View() + { + InitializeComponent(); + Size = new System.Drawing.Size(50, 50); + + var viewModel = new ViewModel(); + + pieChart = new PieChart + { + Series = viewModel.Series, + IsClockwise = false, + InitialRotation = -90, + + // out of livecharts properties... + Location = new System.Drawing.Point(0, 0), + Size = new System.Drawing.Size(50, 50), + Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom + }; + + Controls.Add(pieChart); + } +} diff --git a/samples/WinFormsSample/Pies/OutLabels/View.resx b/samples/WinFormsSample/Pies/OutLabels/View.resx new file mode 100644 index 000000000..f298a7be8 --- /dev/null +++ b/samples/WinFormsSample/Pies/OutLabels/View.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/samples/WinUISample/WinUISample/Pies/OutLabels/View.xaml b/samples/WinUISample/WinUISample/Pies/OutLabels/View.xaml new file mode 100644 index 000000000..d331c0cd4 --- /dev/null +++ b/samples/WinUISample/WinUISample/Pies/OutLabels/View.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/samples/WinUISample/WinUISample/Pies/OutLabels/View.xaml.cs b/samples/WinUISample/WinUISample/Pies/OutLabels/View.xaml.cs new file mode 100644 index 000000000..07cc88bad --- /dev/null +++ b/samples/WinUISample/WinUISample/Pies/OutLabels/View.xaml.cs @@ -0,0 +1,11 @@ +using Microsoft.UI.Xaml.Controls; + +namespace WinUISample.Pies.OutLabels; + +public sealed partial class View : UserControl +{ + public View() + { + InitializeComponent(); + } +} diff --git a/samples/XamarinSample/XamarinSample/XamarinSample/Pies/OutLabels/View.xaml b/samples/XamarinSample/XamarinSample/XamarinSample/Pies/OutLabels/View.xaml new file mode 100644 index 000000000..32fddb0a3 --- /dev/null +++ b/samples/XamarinSample/XamarinSample/XamarinSample/Pies/OutLabels/View.xaml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/samples/XamarinSample/XamarinSample/XamarinSample/Pies/OutLabels/View.xaml.cs b/samples/XamarinSample/XamarinSample/XamarinSample/Pies/OutLabels/View.xaml.cs new file mode 100644 index 000000000..d7a498433 --- /dev/null +++ b/samples/XamarinSample/XamarinSample/XamarinSample/Pies/OutLabels/View.xaml.cs @@ -0,0 +1,13 @@ +using Xamarin.Forms; +using Xamarin.Forms.Xaml; + +namespace XamarinSample.Pies.OutLabels; + +[XamlCompilation(XamlCompilationOptions.Compile)] +public partial class View : ContentPage +{ + public View() + { + InitializeComponent(); + } +} From 0244501c494c970a0094386ea639dd8fa2531f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Mon, 11 Sep 2023 22:16:56 -0600 Subject: [PATCH 62/78] remove wait.... --- src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs | 2 +- src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/Chart.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs index 68a4f19b9..e5bf591e9 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/Chart.cs @@ -281,7 +281,7 @@ internal Point GetCanvasPosition() void IChartView.InvokeOnUIThread(Action action) { if (!IsHandleCreated) return; - _ = BeginInvoke(action).AsyncWaitHandle.WaitOne(); + _ = BeginInvoke(action); } /// diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/Chart.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/Chart.cs index 6eb1e328d..d423bed4c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/Chart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/Chart.cs @@ -267,7 +267,7 @@ internal Point GetCanvasPosition() void IChartView.InvokeOnUIThread(Action action) { - Application.Instance.InvokeAsync(action).Wait(); + _ = Application.Instance.InvokeAsync(action); } /// From 4eaab5ff142e502d05e38fb9d329274fb8f91979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 12 Sep 2023 11:14:58 -0600 Subject: [PATCH 63/78] add label maxwidth --- src/LiveChartsCore/Drawing/ILabelGeometry.cs | 5 +++++ .../Drawing/Geometries/LabelGeometry.cs | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/LiveChartsCore/Drawing/ILabelGeometry.cs b/src/LiveChartsCore/Drawing/ILabelGeometry.cs index 5892f2a2f..58f9161f1 100644 --- a/src/LiveChartsCore/Drawing/ILabelGeometry.cs +++ b/src/LiveChartsCore/Drawing/ILabelGeometry.cs @@ -78,6 +78,11 @@ public interface ILabelGeometry : IGeometry /// float TextSize { get; set; } + /// + /// Gets or sets the maximum width. + /// + float MaxWidth { get; set; } + /// /// Gets or sets the background color. /// diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index 0c90f405e..7a0a43223 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -21,6 +21,8 @@ // SOFTWARE. using System; +using System.Collections.Generic; +using System.Linq; using LiveChartsCore.Drawing; using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Painting; @@ -79,6 +81,9 @@ public LabelGeometry() /// public float LineHeight { get; set; } = 1.45f; + /// + public float MaxWidth { get; set; } = float.MaxValue; + #if DEBUG /// /// This property is only available on debug mode, it indicates if the debug lines should be shown. @@ -188,7 +193,7 @@ protected override LvcSize OnMeasure(IPaint paint) _maxTextHeight = 0f; _lines = 0; - foreach (var line in Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) + foreach (var line in GetLines(p)) { var bounds = new SKRect(); _ = p.MeasureText(line, ref bounds); @@ -211,6 +216,11 @@ protected override LvcSize OnMeasure(IPaint paint) h + Padding.Top + Padding.Bottom); } + private string[] GetLines(SKPaint paint) + { + return Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + } + private LvcPoint GetAlignmentOffset(SKRect bounds) { var p = Padding; From 9b65a4c74be745260d3dbae27cb5afbd159dfd4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 12 Sep 2023 17:36:26 -0600 Subject: [PATCH 64/78] labels max width --- src/LiveChartsCore/BoxSeries.cs | 5 +-- src/LiveChartsCore/ChartSeries.cs | 4 ++ src/LiveChartsCore/ColumnSeries.cs | 2 +- src/LiveChartsCore/FinancialSeries.cs | 2 +- src/LiveChartsCore/HeatSeries.cs | 2 +- .../Kernel/LiveChartsSettings.cs | 5 +++ .../Kernel/Sketches/IChartSeries.cs | 8 ++++ src/LiveChartsCore/LineSeries.cs | 2 +- src/LiveChartsCore/PieSeries.cs | 2 +- src/LiveChartsCore/PolarLineSeries.cs | 2 +- src/LiveChartsCore/RowSeries.cs | 2 +- src/LiveChartsCore/ScatterSeries.cs | 2 +- src/LiveChartsCore/StepLineSeries.cs | 2 +- .../VisualElements/LabelVisual.cs | 8 ++++ .../Drawing/Geometries/LabelGeometry.cs | 43 +++++++++++++++++-- .../SKCharts/SKDefaultLegend.cs | 1 + .../SKCharts/SKDefaultTooltip.cs | 5 +++ 17 files changed, 81 insertions(+), 16 deletions(-) diff --git a/src/LiveChartsCore/BoxSeries.cs b/src/LiveChartsCore/BoxSeries.cs index 0da676f93..762d996c4 100644 --- a/src/LiveChartsCore/BoxSeries.cs +++ b/src/LiveChartsCore/BoxSeries.cs @@ -1,5 +1,4 @@ - -// The MIT License(MIT) +// The MIT License(MIT) // // Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors // @@ -247,7 +246,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = secondary - helper.uwm + helper.cp, Y = high, RotateTransform = (float)DataLabelsRotation }; + var l = new TLabel { X = secondary - helper.uwm + helper.cp, Y = high, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed); label = l; point.Context.Label = l; diff --git a/src/LiveChartsCore/ChartSeries.cs b/src/LiveChartsCore/ChartSeries.cs index 80924cd9d..5946b4fbc 100644 --- a/src/LiveChartsCore/ChartSeries.cs +++ b/src/LiveChartsCore/ChartSeries.cs @@ -46,6 +46,7 @@ public abstract class ChartSeries private double _dataLabelsSize = 16; private double _dataLabelsRotation = 0; private Padding _dataLabelsPadding = new() { Left = 6, Top = 8, Right = 6, Bottom = 8 }; + private double _dataLabelsMaxWidth = LiveCharts.DefaultSettings.MaxTooltipsAndLegendsLabelsWidth; /// /// Initializes a new instance of the class. @@ -69,6 +70,9 @@ public IPaint? DataLabelsPaint /// public Padding DataLabelsPadding { get => _dataLabelsPadding; set => SetProperty(ref _dataLabelsPadding, value); } + /// + public double DataLabelsMaxWidth { get => _dataLabelsMaxWidth; set => SetProperty(ref _dataLabelsMaxWidth, value); } + void IChartSeries.OnDataPointerDown(IChartView chart, IEnumerable points, LvcPoint pointer) { OnDataPointerDown(chart, points, pointer); diff --git a/src/LiveChartsCore/ColumnSeries.cs b/src/LiveChartsCore/ColumnSeries.cs index 5c942a9a1..f0d1f0b6c 100644 --- a/src/LiveChartsCore/ColumnSeries.cs +++ b/src/LiveChartsCore/ColumnSeries.cs @@ -287,7 +287,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = secondary - helper.uwm + helper.cp, Y = helper.p, RotateTransform = (float)DataLabelsRotation }; + var l = new TLabel { X = secondary - helper.uwm + helper.cp, Y = helper.p, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed); label = l; point.Context.Label = l; diff --git a/src/LiveChartsCore/FinancialSeries.cs b/src/LiveChartsCore/FinancialSeries.cs index ccd8f9d52..7e6f2ebb8 100644 --- a/src/LiveChartsCore/FinancialSeries.cs +++ b/src/LiveChartsCore/FinancialSeries.cs @@ -290,7 +290,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = secondary - uwm, Y = high, RotateTransform = (float)DataLabelsRotation }; + var l = new TLabel { X = secondary - uwm, Y = high, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed); label = l; point.Context.Label = l; diff --git a/src/LiveChartsCore/HeatSeries.cs b/src/LiveChartsCore/HeatSeries.cs index 5a321b24a..7de693c57 100644 --- a/src/LiveChartsCore/HeatSeries.cs +++ b/src/LiveChartsCore/HeatSeries.cs @@ -234,7 +234,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = secondary - uws * 0.5f, Y = primary - uws * 0.5f, RotateTransform = (float)DataLabelsRotation }; + var l = new TLabel { X = secondary - uws * 0.5f, Y = primary - uws * 0.5f, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed); label = l; point.Context.Label = l; diff --git a/src/LiveChartsCore/Kernel/LiveChartsSettings.cs b/src/LiveChartsCore/Kernel/LiveChartsSettings.cs index a3b4588e3..915549f8e 100644 --- a/src/LiveChartsCore/Kernel/LiveChartsSettings.cs +++ b/src/LiveChartsCore/Kernel/LiveChartsSettings.cs @@ -127,6 +127,11 @@ public class LiveChartsSettings /// public double? TooltipTextSize { get; set; } + /// + /// Gets or sets the default max with for labels inside tooltips and legends. + /// + public double MaxTooltipsAndLegendsLabelsWidth { get; set; } = 170; + /// /// Gets or sets the default tooltip finding strategy. /// diff --git a/src/LiveChartsCore/Kernel/Sketches/IChartSeries.cs b/src/LiveChartsCore/Kernel/Sketches/IChartSeries.cs index 428c66eef..5d9a8ff58 100644 --- a/src/LiveChartsCore/Kernel/Sketches/IChartSeries.cs +++ b/src/LiveChartsCore/Kernel/Sketches/IChartSeries.cs @@ -66,6 +66,14 @@ public interface IChartSeries : ISeries, IChartElement Padding DataLabelsPadding { get; set; } + /// + /// Gets or sets the max width of the data labels. + /// + /// + /// The max with of the data labels. + /// + double DataLabelsMaxWidth { get; set; } + /// /// Gets the paint schedule, normally handled internally to display tool tips and legends. /// diff --git a/src/LiveChartsCore/LineSeries.cs b/src/LiveChartsCore/LineSeries.cs index fb47d42ca..ea72504ba 100644 --- a/src/LiveChartsCore/LineSeries.cs +++ b/src/LiveChartsCore/LineSeries.cs @@ -381,7 +381,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = x - hgs, Y = p - hgs, RotateTransform = (float)DataLabelsRotation }; + var l = new TLabel { X = x - hgs, Y = p - hgs, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed); label = l; data.TargetPoint.Context.Label = l; diff --git a/src/LiveChartsCore/PieSeries.cs b/src/LiveChartsCore/PieSeries.cs index b34011011..059aa4d9c 100644 --- a/src/LiveChartsCore/PieSeries.cs +++ b/src/LiveChartsCore/PieSeries.cs @@ -413,7 +413,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = cx, Y = cy, RotateTransform = actualRotation }; + var l = new TLabel { X = cx, Y = cy, RotateTransform = actualRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? chart.EasingFunction, AnimationsSpeed ?? chart.AnimationsSpeed); label = l; point.Context.Label = l; diff --git a/src/LiveChartsCore/PolarLineSeries.cs b/src/LiveChartsCore/PolarLineSeries.cs index e083a1cd9..0e9c02e4f 100644 --- a/src/LiveChartsCore/PolarLineSeries.cs +++ b/src/LiveChartsCore/PolarLineSeries.cs @@ -381,7 +381,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = x - hgs, Y = scaler.CenterY - hgs, RotateTransform = (float)actualRotation }; + var l = new TLabel { X = x - hgs, Y = scaler.CenterY - hgs, RotateTransform = (float)actualRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? chart.EasingFunction, AnimationsSpeed ?? chart.AnimationsSpeed); label = l; data.TargetPoint.Context.Label = l; diff --git a/src/LiveChartsCore/RowSeries.cs b/src/LiveChartsCore/RowSeries.cs index 3f527b9a1..d2bd6f089 100644 --- a/src/LiveChartsCore/RowSeries.cs +++ b/src/LiveChartsCore/RowSeries.cs @@ -290,7 +290,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = helper.p, Y = secondary - helper.uwm + helper.cp, RotateTransform = (float)DataLabelsRotation }; + var l = new TLabel { X = helper.p, Y = secondary - helper.uwm + helper.cp, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed); label = l; point.Context.Label = l; diff --git a/src/LiveChartsCore/ScatterSeries.cs b/src/LiveChartsCore/ScatterSeries.cs index b222a7c8b..f59242075 100644 --- a/src/LiveChartsCore/ScatterSeries.cs +++ b/src/LiveChartsCore/ScatterSeries.cs @@ -270,7 +270,7 @@ public override void Invalidate(Chart chart) { if (point.Context.Label is not TLabel label) { - var l = new TLabel { X = x - hgs, Y = y - hgs, RotateTransform = (float)DataLabelsRotation }; + var l = new TLabel { X = x - hgs, Y = y - hgs, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed); label = l; point.Context.Label = l; diff --git a/src/LiveChartsCore/StepLineSeries.cs b/src/LiveChartsCore/StepLineSeries.cs index 31bb3a578..bcd1e29c5 100644 --- a/src/LiveChartsCore/StepLineSeries.cs +++ b/src/LiveChartsCore/StepLineSeries.cs @@ -288,7 +288,7 @@ public override void Invalidate(Chart chart) if (label is null) { - var l = new TLabel { X = x - hgs, Y = p - hgs, RotateTransform = (float)DataLabelsRotation }; + var l = new TLabel { X = x - hgs, Y = p - hgs, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth }; l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed); label = l; point.Context.Label = l; diff --git a/src/LiveChartsCore/VisualElements/LabelVisual.cs b/src/LiveChartsCore/VisualElements/LabelVisual.cs index 3d30f75fc..9e8c4432e 100644 --- a/src/LiveChartsCore/VisualElements/LabelVisual.cs +++ b/src/LiveChartsCore/VisualElements/LabelVisual.cs @@ -45,6 +45,7 @@ public class LabelVisual : VisualElement /// Gets or sets the fill paint. @@ -90,6 +91,11 @@ public IPaint? Paint /// public float LineHeight { get => _lineHeight; set => SetProperty(ref _lineHeight, value); } + /// + /// Gets or sets the maximum width. + /// + public float MaxWidth { get => _maxWidth; set => SetProperty(ref _maxWidth, value); } + internal override IPaint?[] GetPaintTasks() { return new[] { _paint }; @@ -135,6 +141,7 @@ protected internal override void OnInvalidated(Chart chart) _labelGeometry.Background = BackgroundColor; _labelGeometry.Padding = Padding; _labelGeometry.LineHeight = LineHeight; + _labelGeometry.MaxWidth = MaxWidth; if (Paint is not null) { @@ -164,6 +171,7 @@ public override LvcSize Measure(Chart chart) _labelGeometry.Background = BackgroundColor; _labelGeometry.Padding = Padding; _labelGeometry.LineHeight = LineHeight; + _labelGeometry.MaxWidth = MaxWidth; return _paint is null ? new LvcSize() diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index 7a0a43223..10a47e448 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -22,7 +22,7 @@ using System; using System.Collections.Generic; -using System.Linq; +using System.Text; using LiveChartsCore.Drawing; using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Painting; @@ -116,7 +116,7 @@ public override void OnDraw(SkiaSharpDrawingContext context, SKPaint paint) var textBounds = new SKRect(); var shaper = paint.Typeface is not null ? new SKShaper(paint.Typeface) : null; - foreach (var line in Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) + foreach (var line in GetLines(context.Paint)) { _ = context.Paint.MeasureText(line, ref textBounds); @@ -216,9 +216,44 @@ protected override LvcSize OnMeasure(IPaint paint) h + Padding.Top + Padding.Bottom); } - private string[] GetLines(SKPaint paint) + private IEnumerable GetLines(SKPaint paint) { - return Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + return MaxWidth == float.MaxValue + ? Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None) + : GetLinesByMaxWidth(paint); + } + + private IEnumerable GetLinesByMaxWidth(SKPaint paint) + { + var sb = new StringBuilder(); + var lineWidth = 0.0f; + var words = Text.Split(new[] { " ", Environment.NewLine }, StringSplitOptions.None); + var spaceSize = paint.MeasureText(" "); + var bounds = new SKRect(); + var mw = MaxWidth; + + foreach (var word in words) + { + _ = paint.MeasureText(word, ref bounds); + + if (lineWidth + spaceSize + bounds.Width > mw) + { + yield return sb.ToString(); + _ = sb.Clear(); + lineWidth = 0.0f; + } + + if (sb.Length > 0) + { + _ = sb.Append(' '); + lineWidth += spaceSize; + } + + _ = sb.Append(word); + lineWidth += bounds.Width; + } + + yield return sb.ToString(); } private LvcPoint GetAlignmentOffset(SKRect bounds) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs index c212fdde6..750855d7d 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs @@ -129,6 +129,7 @@ private void BuildLayout(Chart chart) Paint = FontPaint, TextSize = TextSize, Padding = new Padding(8, 0, 0, 0), + MaxWidth = (float)LiveCharts.DefaultSettings.MaxTooltipsAndLegendsLabelsWidth, VerticalAlignment = Align.Start, HorizontalAlignment = Align.Start } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs index 5d6979982..bdac0334c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs @@ -126,6 +126,8 @@ public void Show(IEnumerable foundPoints, Chart foundPoints, Chart foundPoints, Chart foundPoints, Chart Date: Tue, 12 Sep 2023 19:09:48 -0600 Subject: [PATCH 65/78] fixes to maxwidth --- .../Drawing/Geometries/LabelGeometry.cs | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index 10a47e448..05521b9e8 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -36,8 +36,8 @@ public class LabelGeometry : Geometry, ILabelGeometry { private readonly FloatMotionProperty _textSizeProperty; private readonly ColorMotionProperty _backgroundProperty; - private float _maxTextHeight = 0f; - private int _lines; + internal float _maxTextHeight = 0f; + internal int _lines; /// /// Initializes a new instance of the class. @@ -216,41 +216,56 @@ protected override LvcSize OnMeasure(IPaint paint) h + Padding.Top + Padding.Bottom); } - private IEnumerable GetLines(SKPaint paint) + internal IEnumerable GetLines(SKPaint paint) { return MaxWidth == float.MaxValue ? Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None) : GetLinesByMaxWidth(paint); } - private IEnumerable GetLinesByMaxWidth(SKPaint paint) + internal IEnumerable GetLinesByMaxWidth(SKPaint paint) { + // DISCLAIM + // WE ARE USING A DOUBLE STRING BUILDER, AND MEASURE THE REAL STRING EVERY TIME + // BECAUSE IT SEEMS THAT THE SKIA MEASURE TEXT IS INCONSISTENT, FOR EXAMPLE: + + //using var p = new SKPaint() { Color = SKColors.Black, TextSize = 15 }; + //var b = new SKRect(); + //_ = p.MeasureText("nullam. Ut tellus", ref b); + + //var w1 = b.Width; + + //var w2 = 0f; + //_ = p.MeasureText("nullam.", ref b); + //w2 += b.Width; + //_ = p.MeasureText(" Ut", ref b); + //w2 += b.Width; + //_ = p.MeasureText(" tellus", ref b); + //w2 += b.Width; + + //Assert.IsTrue(w1 == w2); + var sb = new StringBuilder(); - var lineWidth = 0.0f; + var sb2 = new StringBuilder(); var words = Text.Split(new[] { " ", Environment.NewLine }, StringSplitOptions.None); - var spaceSize = paint.MeasureText(" "); var bounds = new SKRect(); var mw = MaxWidth; foreach (var word in words) { - _ = paint.MeasureText(word, ref bounds); + _ = sb2.Append(sb.ToString()); + _ = sb2.Append(" "); + _ = sb2.Append(word); + _ = paint.MeasureText(sb2.ToString(), ref bounds); - if (lineWidth + spaceSize + bounds.Width > mw) + if (bounds.Width > mw) { yield return sb.ToString(); _ = sb.Clear(); - lineWidth = 0.0f; - } - - if (sb.Length > 0) - { - _ = sb.Append(' '); - lineWidth += spaceSize; } + if (sb.Length > 0) _ = sb.Append(' '); _ = sb.Append(word); - lineWidth += bounds.Width; } yield return sb.ToString(); From f1cd60d25b15befd92ae46e595b94c0228540349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 12 Sep 2023 19:20:30 -0600 Subject: [PATCH 66/78] consider padding --- .../Drawing/Geometries/LabelGeometry.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index 05521b9e8..221c7f203 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -249,10 +249,11 @@ internal IEnumerable GetLinesByMaxWidth(SKPaint paint) var sb2 = new StringBuilder(); var words = Text.Split(new[] { " ", Environment.NewLine }, StringSplitOptions.None); var bounds = new SKRect(); - var mw = MaxWidth; + var mw = MaxWidth - Padding.Left - Padding.Right; foreach (var word in words) { + _ = sb2.Clear(); _ = sb2.Append(sb.ToString()); _ = sb2.Append(" "); _ = sb2.Append(word); From a936a7a32673f133f086eb34213d144405154e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 12 Sep 2023 19:29:05 -0600 Subject: [PATCH 67/78] add maxlabels width test --- .../OtherTests/LabelsMeasureTest.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/LiveChartsCore.UnitTesting/OtherTests/LabelsMeasureTest.cs b/tests/LiveChartsCore.UnitTesting/OtherTests/LabelsMeasureTest.cs index dffe564f0..0235acd5e 100644 --- a/tests/LiveChartsCore.UnitTesting/OtherTests/LabelsMeasureTest.cs +++ b/tests/LiveChartsCore.UnitTesting/OtherTests/LabelsMeasureTest.cs @@ -22,9 +22,12 @@ using System; using System.Collections.Generic; +using System.Linq; using LiveChartsCore.Kernel; +using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; using LiveChartsCore.SkiaSharpView.Painting; using LiveChartsCore.SkiaSharpView.SKCharts; using LiveChartsCore.SkiaSharpView.VisualElements; @@ -125,4 +128,57 @@ public void MultiLine() _ = chart.GetImage(); //chart.SaveImage("multi line labels test.png"); // use this method to see the actual tested image } + + [TestMethod] + public void MaxWidth() + { + var maxWidth = 400f; + var text = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Magnis dis parturient montes nascetur ridiculus mus mauris vitae. Dolor sed viverra ipsum nunc aliquet bibendum. At lectus urna duis convallis convallis. Rutrum quisque non tellus orci ac auctor augue mauris. Id aliquet lectus proin nibh nisl condimentum id. Viverra aliquet eget sit amet tellus cras adipiscing. Volutpat ac tincidunt vitae semper quis. Convallis a cras semper auctor neque. Imperdiet nulla malesuada pellentesque elit.\r\n\r\nViverra nam libero justo laoreet sit amet cursus sit. Sem integer vitae justo eget magna fermentum iaculis. Nulla facilisi etiam dignissim diam quis enim lobortis. At ultrices mi tempus imperdiet nulla. Tellus rutrum tellus pellentesque eu tincidunt tortor. Lacus luctus accumsan tortor posuere ac ut. Viverra nam libero justo laoreet sit amet. In dictum non consectetur a. Odio ut sem nulla pharetra diam sit amet nisl. Porttitor massa id neque aliquam vestibulum morbi blandit. Cras sed felis eget velit aliquet sagittis id consectetur. Mi bibendum neque egestas congue. Massa massa ultricies mi quis hendrerit dolor magna eget est. Leo urna molestie at elementum eu facilisis sed odio. Justo eget magna fermentum iaculis eu non diam. Vitae aliquet nec ullamcorper sit amet risus nullam. Ut tellus elementum sagittis vitae et leo duis ut. Eget nunc scelerisque viverra mauris. Egestas purus viverra accumsan in nisl nisi.\r\n\r\nNisl condimentum id venenatis a condimentum vitae sapien. Ut pharetra sit amet aliquam id diam maecenas ultricies. Hac habitasse platea dictumst quisque sagittis purus. Maecenas pharetra convallis posuere morbi leo urna molestie. Suspendisse ultrices gravida dictum fusce. In est ante in nibh mauris cursus mattis molestie a. Volutpat lacus laoreet non curabitur gravida arcu ac tortor dignissim. Eget lorem dolor sed viverra ipsum nunc aliquet bibendum enim. Sed odio morbi quis commodo odio aenean sed adipiscing. Aliquam eleifend mi in nulla posuere sollicitudin aliquam. Eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Tellus rutrum tellus pellentesque eu tincidunt tortor aliquam nulla facilisi. Dolor sit amet consectetur adipiscing elit ut.\r\n\r\nEst ultricies integer quis auctor elit sed vulputate mi sit. Enim ut tellus elementum sagittis. Donec pretium vulputate sapien nec sagittis aliquam malesuada bibendum arcu. Integer malesuada nunc vel risus commodo viverra maecenas. Praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam phasellus vestibulum. Netus et malesuada fames ac turpis egestas sed tempus urna. Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Donec ac odio tempor orci dapibus. Netus et malesuada fames ac turpis. Ultrices in iaculis nunc sed augue lacus viverra. Vulputate mi sit amet mauris. Scelerisque felis imperdiet proin fermentum leo vel orci porta non. Malesuada bibendum arcu vitae elementum curabitur vitae nunc sed.\r\n\r\nQuam viverra orci sagittis eu volutpat odio. Quis ipsum suspendisse ultrices gravida. Ac placerat vestibulum lectus mauris ultrices eros in cursus turpis. Aliquam vestibulum morbi blandit cursus. Mauris cursus mattis molestie a iaculis at erat pellentesque adipiscing. Enim nunc faucibus a pellentesque sit amet porttitor. Urna et pharetra pharetra massa massa. Nisi vitae suscipit tellus mauris a diam maecenas sed. Sit amet purus gravida quis blandit turpis cursus in. Felis eget nunc lobortis mattis aliquam faucibus purus in massa. Consequat id porta nibh venenatis. Tincidunt arcu non sodales neque sodales ut etiam. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Tortor at risus viverra adipiscing. Dis parturient montes nascetur ridiculus mus."; + + var canvas = new MotionCanvas(); + var drawingContext = new SkiaSharpDrawingContext(canvas, SKImageInfo.Empty, SKSurface.CreateNull(100, 100), null!); + + var paint = new SolidColorPaint { Color = SKColors.Red }; + paint.InitializeTask(drawingContext); + paint._skiaPaint.TextSize = 15; + + var label = new LabelGeometry + { + Text = text, + TextSize = 15, + MaxWidth = maxWidth, + Padding = new(10, 0), + }; + + var lines = label.GetLinesByMaxWidth(paint._skiaPaint).ToArray(); + var b = new SKRect(); + var l = 0; + foreach (var line in lines) + { + _ = paint._skiaPaint.MeasureText(line, ref b); + Assert.IsTrue(b.Width <= maxWidth); + l++; + } + + var size = label.Measure(paint); + Assert.IsTrue(size.Width <= maxWidth); + Assert.IsTrue(l == label._lines); + + var label2 = new LabelGeometry + { + Text = + "short " + + "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong " + + "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong " + + "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong " + + "short", + TextSize = 15, + MaxWidth = 100 + }; + var size2 = label2.Measure(paint); + + Assert.IsTrue(label2._lines == 5); + Assert.IsTrue(size2.Width > label2.MaxWidth); // the text is too long, this is allowed. + } } From 06d16705ba2e9c2bf999f6a76932f1982d3ecdb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 12 Sep 2023 21:41:06 -0600 Subject: [PATCH 68/78] test newline with max width --- .../Drawing/Geometries/LabelGeometry.cs | 18 +++++++++++------- .../OtherTests/LabelsMeasureTest.cs | 13 ++++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index 221c7f203..620f80e65 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using LiveChartsCore.Drawing; using LiveChartsCore.Motion; @@ -218,14 +219,17 @@ protected override LvcSize OnMeasure(IPaint paint) internal IEnumerable GetLines(SKPaint paint) { - return MaxWidth == float.MaxValue - ? Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None) - : GetLinesByMaxWidth(paint); + IEnumerable lines = Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + + if (MaxWidth != float.MaxValue) + lines = lines.SelectMany(x => GetLinesByMaxWidth(x, paint)); + + return lines; } - internal IEnumerable GetLinesByMaxWidth(SKPaint paint) + private IEnumerable GetLinesByMaxWidth(string source, SKPaint paint) { - // DISCLAIM + // DISCLAIM ==================================================================== // WE ARE USING A DOUBLE STRING BUILDER, AND MEASURE THE REAL STRING EVERY TIME // BECAUSE IT SEEMS THAT THE SKIA MEASURE TEXT IS INCONSISTENT, FOR EXAMPLE: @@ -243,11 +247,11 @@ internal IEnumerable GetLinesByMaxWidth(SKPaint paint) //_ = p.MeasureText(" tellus", ref b); //w2 += b.Width; - //Assert.IsTrue(w1 == w2); + //Assert.IsTrue(w1 == w2); THIS IS FALSE!!!! var sb = new StringBuilder(); var sb2 = new StringBuilder(); - var words = Text.Split(new[] { " ", Environment.NewLine }, StringSplitOptions.None); + var words = source.Split(new[] { " ", Environment.NewLine }, StringSplitOptions.None); var bounds = new SKRect(); var mw = MaxWidth - Padding.Left - Padding.Right; diff --git a/tests/LiveChartsCore.UnitTesting/OtherTests/LabelsMeasureTest.cs b/tests/LiveChartsCore.UnitTesting/OtherTests/LabelsMeasureTest.cs index 0235acd5e..d75bb5f33 100644 --- a/tests/LiveChartsCore.UnitTesting/OtherTests/LabelsMeasureTest.cs +++ b/tests/LiveChartsCore.UnitTesting/OtherTests/LabelsMeasureTest.cs @@ -151,7 +151,7 @@ public void MaxWidth() Padding = new(10, 0), }; - var lines = label.GetLinesByMaxWidth(paint._skiaPaint).ToArray(); + var lines = label.GetLines(paint._skiaPaint).ToArray(); var b = new SKRect(); var l = 0; foreach (var line in lines) @@ -180,5 +180,16 @@ public void MaxWidth() Assert.IsTrue(label2._lines == 5); Assert.IsTrue(size2.Width > label2.MaxWidth); // the text is too long, this is allowed. + + var label3 = new LabelGeometry + { + Text = $"hello hello hello hello hello {Environment.NewLine} hello hello hello hello hello", + TextSize = 15, + MaxWidth = 100 + }; + var size3 = label3.Measure(paint); + var lines3 = label3.GetLines(paint._skiaPaint).ToArray(); + + Assert.IsTrue(label3._lines == 6); } } From 7d873db0cd2f12caae3a44e70b32eb12ede24ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 12 Sep 2023 22:13:17 -0600 Subject: [PATCH 69/78] force tooltip to stay inside --- src/LiveChartsCore/Kernel/Extensions.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/LiveChartsCore/Kernel/Extensions.cs b/src/LiveChartsCore/Kernel/Extensions.cs index f9513293f..a356b975a 100644 --- a/src/LiveChartsCore/Kernel/Extensions.cs +++ b/src/LiveChartsCore/Kernel/Extensions.cs @@ -57,9 +57,18 @@ public static LvcPoint GetTooltipLocation( Chart chart) where TDrawingContext : DrawingContext { - return chart is CartesianChart or PolarChart + var location = chart is CartesianChart or PolarChart ? _getCartesianTooltipLocation(foundPoints, chart, tooltipSize) : _getPieTooltipLocation(foundPoints, chart, tooltipSize); + + var controlSize = chart.ControlSize; + + if (location.Y < 0) location.Y = 0; + if (location.X < 0) location.X = 0; + if (location.Y + tooltipSize.Height > controlSize.Height) location.Y = controlSize.Height - tooltipSize.Height; + if (location.X + tooltipSize.Width > controlSize.Width) location.X = controlSize.Width - tooltipSize.Width; + + return location; } private static LvcPoint _getCartesianTooltipLocation( From 02e4aace34e0340d7fc080d7282a7e4239d4de29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Tue, 12 Sep 2023 22:21:29 -0600 Subject: [PATCH 70/78] outlabels sample update --- .../ViewModelsSamples/Pies/OutLabels/ViewModel.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/samples/ViewModelsSamples/Pies/OutLabels/ViewModel.cs b/samples/ViewModelsSamples/Pies/OutLabels/ViewModel.cs index 3454a6079..20101b1bc 100644 --- a/samples/ViewModelsSamples/Pies/OutLabels/ViewModel.cs +++ b/samples/ViewModelsSamples/Pies/OutLabels/ViewModel.cs @@ -4,25 +4,25 @@ using LiveChartsCore.SkiaSharpView.Painting; using SkiaSharp; using LiveChartsCore.SkiaSharpView.Extensions; -using System; namespace ViewModelsSamples.Pies.OutLabels; public partial class ViewModel : ObservableObject { + private static int _index = 0; + private static string[] _names = new[] { "Maria", "Susan", "Charles", "Fiona", "George" }; + public IEnumerable Series { get; set; } = new[] { 8, 6, 5, 3, 3 }.AsPieSeries((value, series) => { + series.Name = _names[_index++ % _names.Length]; series.DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.Outer; // mark series.DataLabelsSize = 15; series.DataLabelsPaint = new SolidColorPaint(new SKColor(30, 30, 30)); series.DataLabelsFormatter = point => - $"This slide takes{Environment.NewLine}" + - $"{point.Coordinate.PrimaryValue} out of {point.StackedValue!.Total} parts"; + $"This slide takes {point.Coordinate.PrimaryValue} " + + $"out of {point.StackedValue!.Total} parts"; + series.ToolTipLabelFormatter = point => $"{point.StackedValue!.Share:P2}"; }); - - // add some margin to the chart so the labels can be drawn // mark - public LiveChartsCore.Measure.Margin DrawMargin { get; set; } = - new LiveChartsCore.Measure.Margin(0); } From 278d3fa5daa01d602a859ab3cb6297d063c57b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Wed, 13 Sep 2023 07:42:18 -0600 Subject: [PATCH 71/78] remove check y on x tooltips --- .../LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs | 4 ++-- .../SeriesTests/ColumnSeriesTest.cs | 4 ++-- .../SeriesTests/FinancialSeriesTest.cs | 4 ++-- .../LiveChartsCore.UnitTesting/SeriesTests/LineSeriesTest.cs | 4 ++-- .../SeriesTests/ScatterSeriesTest.cs | 4 ++-- .../SeriesTests/StepLineSeriesTest.cs | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs index 9f131e34d..4d497287a 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs @@ -197,7 +197,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X - (300 - 300 * (1 / 5d) * 0.5 - tp.Width)) < 0.0001 && - Math.Abs(tp.Y - -tp.Height * 0.5f) < 0.1 && + //Math.Abs(tp.Y - -tp.Height * 0.5f) < 0.1 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Left, "Tool tip on left failed [AUTO]"); @@ -205,7 +205,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X - 300 * (1 / 5d) * 0.5) < 0.0001 && - Math.Abs(tp.Y - (300 - tp.Height * 0.5f - 300 * (1 / 5d))) < 0.1 && + //Math.Abs(tp.Y - (300 - tp.Height * 0.5f - 300 * (1 / 5d))) < 0.1 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Right, "Tool tip on left failed [AUTO]"); } diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/ColumnSeriesTest.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/ColumnSeriesTest.cs index 70d432869..046afd303 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/ColumnSeriesTest.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/ColumnSeriesTest.cs @@ -184,7 +184,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X - (300 - 300 * (1 / 5d) * 0.5 - tp.Width)) < 0.0001 && - Math.Abs(tp.Y - -tp.Height * 0.5f) < 0.1 && + //Math.Abs(tp.Y - -tp.Height * 0.5f) < 0.1 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Left, "Tool tip on left failed [AUTO]"); @@ -192,7 +192,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X - 300 * (1 / 5d) * 0.5) < 0.0001 && - Math.Abs(tp.Y - (300 - tp.Height * 0.5f)) < 0.1 && + //Math.Abs(tp.Y - (300 - tp.Height * 0.5f)) < 0.1 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Right, "Tool tip on right failed [AUTO]"); } diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/FinancialSeriesTest.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/FinancialSeriesTest.cs index 47eab1754..a1b8c2756 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/FinancialSeriesTest.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/FinancialSeriesTest.cs @@ -219,7 +219,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X - (300 - 300 * (1 / 5d) * 0.5 - tp.Width)) < 0.0001 && - Math.Abs(tp.Y - -tp.Height * 0.5f) < 0.1 && + //Math.Abs(tp.Y - -tp.Height * 0.5f) < 0.1 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Left, "Tool tip on left failed [AUTO]"); @@ -227,7 +227,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X - 300 * (1 / 5d) * 0.5) < 0.0001 && - Math.Abs(tp.Y - (300 - tp.Height * 0.5f - 300 * (1 / 5d))) < 0.1 && + //Math.Abs(tp.Y - (300 - tp.Height * 0.5f - 300 * (1 / 5d))) < 0.1 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Right, "Tool tip on left failed [AUTO]"); } diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/LineSeriesTest.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/LineSeriesTest.cs index 140682a80..6e50c3bc7 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/LineSeriesTest.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/LineSeriesTest.cs @@ -191,7 +191,7 @@ public void ShouldPlaceToolTips() Assert.IsTrue( // that 2... it seems that the lineseries.DataPadding takes more space than expected Math.Abs(tp.X - (300 - tp.Width)) < 2 && - Math.Abs(tp.Y - -tp.Height * 0.5f) < 2 && + //Math.Abs(tp.Y - -tp.Height * 0.5f) < 2 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Left, "Tool tip on left failed [AUTO]"); @@ -199,7 +199,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X) < 2 && - Math.Abs(tp.Y - (300 - tp.Height * 0.5f)) < 2 && + //Math.Abs(tp.Y - (300 - tp.Height * 0.5f)) < 2 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Right, "Tool tip on left failed [AUTO]"); } diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs index 823a0c1de..334a660d1 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/ScatterSeriesTest.cs @@ -207,7 +207,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X - (300 - tp.Width)) < 0.1 && - Math.Abs(tp.Y - -tp.Height * 0.5f) < 0.1 && + //Math.Abs(tp.Y - -tp.Height * 0.5f) < 0.1 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Left, "Tool tip on left failed [AUTO]"); @@ -215,7 +215,7 @@ public void ShouldPlaceToolTips() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X) < 0.1 && - Math.Abs(tp.Y - (300 - tp.Height * 0.5f)) < 0.1 && + //Math.Abs(tp.Y - (300 - tp.Height * 0.5f)) < 0.1 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Right, "Tool tip on left failed [AUTO]"); } diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/StepLineSeriesTest.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/StepLineSeriesTest.cs index a1c2ba567..b19f7da9a 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/StepLineSeriesTest.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/StepLineSeriesTest.cs @@ -189,7 +189,7 @@ public void ShouldPlaceToolTipsCorrectly() Assert.IsTrue( // that 2... it seems that the lineseries.DataPadding takes more space than expected Math.Abs(tp.X - (300 - tp.Width)) < 2 && - Math.Abs(tp.Y - -tp.Height * 0.5f) < 2 && + //Math.Abs(tp.Y - -tp.Height * 0.5f) < 2 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Left, "Tool tip on left failed [AUTO]"); @@ -197,7 +197,7 @@ public void ShouldPlaceToolTipsCorrectly() _ = chart.GetImage(); Assert.IsTrue( Math.Abs(tp.X) < 2 && - Math.Abs(tp.Y - (300 - tp.Height * 0.5f)) < 2 && + //Math.Abs(tp.Y - (300 - tp.Height * 0.5f)) < 2 && chart.Core.AutoToolTipsInfo.ToolTipPlacement == PopUpPlacement.Right, "Tool tip on left failed [AUTO]"); } From fda0bf5dfb1b76a70e6331c5e6c29f27029a7bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Wed, 13 Sep 2023 10:46:10 -0600 Subject: [PATCH 72/78] return last line only if has content. --- .../Drawing/Geometries/LabelGeometry.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index 620f80e65..66a71ee8d 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -273,7 +273,7 @@ private IEnumerable GetLinesByMaxWidth(string source, SKPaint paint) _ = sb.Append(word); } - yield return sb.ToString(); + if (sb.Length > 0) yield return sb.ToString(); } private LvcPoint GetAlignmentOffset(SKRect bounds) From d6228908e585058e8a2a9b97321ffc30329e4517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Wed, 13 Sep 2023 10:46:45 -0600 Subject: [PATCH 73/78] improve append --- .../Drawing/Geometries/LabelGeometry.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs index 66a71ee8d..350eef609 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/LabelGeometry.cs @@ -258,8 +258,8 @@ private IEnumerable GetLinesByMaxWidth(string source, SKPaint paint) foreach (var word in words) { _ = sb2.Clear(); - _ = sb2.Append(sb.ToString()); - _ = sb2.Append(" "); + _ = sb2.Append(sb); + _ = sb2.Append(' '); _ = sb2.Append(word); _ = paint.MeasureText(sb2.ToString(), ref bounds); From 04ecf917e373926c88a6972eee8f54af00928cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Wed, 13 Sep 2023 14:04:42 -0600 Subject: [PATCH 74/78] fixes #1242 --- .../General/TemplatedLegends/CustomLegend.cs | 2 + .../TemplatedTooltips/CustomTooltip.cs | 2 + src/LiveChartsCore/CartesianSeries.cs | 18 +----- src/LiveChartsCore/Measure/ClipMode.cs | 8 +-- src/LiveChartsCore/Measure/Clipping.cs | 63 +++++++++++++++++++ .../VisualElements/GeometryVisual.cs | 8 +-- .../VisualElements/LabelVisual.cs | 2 + .../VisualElements/RelativePanel.cs | 12 ++++ .../VisualElements/StackPanel.cs | 12 ++++ .../VisualElements/TableLayout.cs | 12 ++++ .../VisualElements/VariableGeometryVisual.cs | 3 + .../VisualElements/VisualElement.cs | 7 +++ .../SKCharts/SKDefaultLegend.cs | 3 +- .../SKCharts/SKDefaultTooltip.cs | 9 ++- .../VisualElementsExtensions.cs | 1 + 15 files changed, 133 insertions(+), 29 deletions(-) create mode 100644 src/LiveChartsCore/Measure/Clipping.cs diff --git a/samples/ViewModelsSamples/General/TemplatedLegends/CustomLegend.cs b/samples/ViewModelsSamples/General/TemplatedLegends/CustomLegend.cs index 6fac1b9a0..498eaeb27 100644 --- a/samples/ViewModelsSamples/General/TemplatedLegends/CustomLegend.cs +++ b/samples/ViewModelsSamples/General/TemplatedLegends/CustomLegend.cs @@ -64,6 +64,7 @@ public LvcSize Measure(Chart chart) Path = SKPath.ParseSvgPathData(SVGPoints.Star), Width = 25, Height = 25, + ClippingMode = ClipMode.None, // required on legends // mark Fill = new SolidColorPaint(theme.GetSeriesColor(series).AsSKColor()) { ZIndex = s_zIndex + 1 @@ -74,6 +75,7 @@ public LvcSize Measure(Chart chart) Text = series.Name ?? string.Empty, Paint = _fontPaint, TextSize = 15, + ClippingMode = ClipMode.None, // required on legends // mark Padding = new Padding(8, 0, 0, 0), VerticalAlignment = Align.Start, HorizontalAlignment = Align.Start diff --git a/samples/ViewModelsSamples/General/TemplatedTooltips/CustomTooltip.cs b/samples/ViewModelsSamples/General/TemplatedTooltips/CustomTooltip.cs index 299aa395e..fb499d8f6 100644 --- a/samples/ViewModelsSamples/General/TemplatedTooltips/CustomTooltip.cs +++ b/samples/ViewModelsSamples/General/TemplatedTooltips/CustomTooltip.cs @@ -4,6 +4,7 @@ using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Measure; using LiveChartsCore.SkiaSharpView.Drawing; using LiveChartsCore.SkiaSharpView.Drawing.Geometries; using LiveChartsCore.SkiaSharpView.Painting; @@ -58,6 +59,7 @@ public void Show(IEnumerable foundPoints, Chart protected virtual LvcRectangle GetClipRectangle(CartesianChart cartesianChart) { - return ClippingMode switch - { - ClipMode.None => - new LvcRectangle(new LvcPoint(), cartesianChart.ControlSize), - ClipMode.X => - new LvcRectangle( - new LvcPoint(cartesianChart.DrawMarginLocation.X, 0), - new LvcSize(cartesianChart.DrawMarginSize.Width, cartesianChart.ControlSize.Height)), - ClipMode.Y => - new LvcRectangle( - new LvcPoint(0, cartesianChart.DrawMarginLocation.Y), - new LvcSize(cartesianChart.ControlSize.Width, cartesianChart.DrawMarginSize.Height)), - ClipMode.XY => - new LvcRectangle(cartesianChart.DrawMarginLocation, cartesianChart.DrawMarginSize), - - _ => throw new NotImplementedException(), - }; + return Clipping.GetClipRectangle(ClippingMode, cartesianChart); } /// diff --git a/src/LiveChartsCore/Measure/ClipMode.cs b/src/LiveChartsCore/Measure/ClipMode.cs index 87cf6e39b..56a770738 100644 --- a/src/LiveChartsCore/Measure/ClipMode.cs +++ b/src/LiveChartsCore/Measure/ClipMode.cs @@ -25,7 +25,7 @@ namespace LiveChartsCore.Measure; /// -/// Defines the clip mode in the draw margin of a cartesian chart. +/// Defines the clip mode in the draw margin of a chart. /// [Flags] public enum ClipMode @@ -36,19 +36,19 @@ public enum ClipMode None = 0, /// - /// Enables clipping in the x axis, it meas that anthing outside the DrawMargin + /// Enables clipping in the x axis, it means that anything outside the DrawMargin /// in the X axis will no be rendered. /// X = 1 << 0, /// - /// Enables clipping in the y axis, it meas that anthing outside the DrawMargin + /// Enables clipping in the y axis, it means that anything outside the DrawMargin /// in the Y axis will not be rendered. /// Y = 1 << 1, /// - /// Enables clipping in the x and y axis, it meas that anthing outside the DrawMargin + /// Enables clipping in the x and y axis, it means that anything outside the DrawMargin /// will not be rendered. /// XY = X | Y diff --git a/src/LiveChartsCore/Measure/Clipping.cs b/src/LiveChartsCore/Measure/Clipping.cs new file mode 100644 index 000000000..3584d0a60 --- /dev/null +++ b/src/LiveChartsCore/Measure/Clipping.cs @@ -0,0 +1,63 @@ +// The MIT License(MIT) +// +// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using LiveChartsCore.Drawing; + +namespace LiveChartsCore.Measure; + +/// +/// A helper class to get the clipping rectangle. +/// +public static class Clipping +{ + /// + /// Calculates the clipping rectangle based on a clipping mode. + /// + /// The type of the drawing context. + /// The mode. + /// The chart. + /// + /// + public static LvcRectangle GetClipRectangle( + ClipMode mode, Chart chart) + where TDrawingContext : DrawingContext + { + return mode switch + { + ClipMode.None => + new LvcRectangle(new LvcPoint(), chart.ControlSize), + ClipMode.X => + new LvcRectangle( + new LvcPoint(chart.DrawMarginLocation.X, 0), + new LvcSize(chart.DrawMarginSize.Width, chart.ControlSize.Height)), + ClipMode.Y => + new LvcRectangle( + new LvcPoint(0, chart.DrawMarginLocation.Y), + new LvcSize(chart.ControlSize.Width, chart.DrawMarginSize.Height)), + ClipMode.XY => + new LvcRectangle(chart.DrawMarginLocation, chart.DrawMarginSize), + + _ => throw new NotImplementedException(), + }; + } +} diff --git a/src/LiveChartsCore/VisualElements/GeometryVisual.cs b/src/LiveChartsCore/VisualElements/GeometryVisual.cs index 3204f9ed7..e76908249 100644 --- a/src/LiveChartsCore/VisualElements/GeometryVisual.cs +++ b/src/LiveChartsCore/VisualElements/GeometryVisual.cs @@ -76,7 +76,7 @@ protected internal override void OnInvalidated(Chart chart) { var l = GetActualCoordinate(); var size = Measure(chart); - var clipArea = new LvcRectangle(chart.DrawMarginLocation, chart.DrawMarginSize); + var clipping = Clipping.GetClipRectangle(ClippingMode, chart); if (_geometry is null) { @@ -101,14 +101,14 @@ protected internal override void OnInvalidated(Chart chart) { chart.Canvas.AddDrawableTask(Fill); Fill.AddGeometryToPaintTask(chart.Canvas, _geometry); - Fill.SetClipRectangle(chart.Canvas, clipArea); + Fill.SetClipRectangle(chart.Canvas, clipping); } if (Stroke is not null) { chart.Canvas.AddDrawableTask(Stroke); Stroke.AddGeometryToPaintTask(chart.Canvas, _geometry); - Stroke.SetClipRectangle(chart.Canvas, clipArea); + Stroke.SetClipRectangle(chart.Canvas, clipping); } if (LabelPaint is not null) @@ -140,7 +140,7 @@ protected internal override void OnInvalidated(Chart chart) chart.Canvas.AddDrawableTask(LabelPaint); LabelPaint.AddGeometryToPaintTask(chart.Canvas, _labelGeometry); - LabelPaint.SetClipRectangle(chart.Canvas, clipArea); + LabelPaint.SetClipRectangle(chart.Canvas, clipping); } } diff --git a/src/LiveChartsCore/VisualElements/LabelVisual.cs b/src/LiveChartsCore/VisualElements/LabelVisual.cs index 9e8c4432e..37d917245 100644 --- a/src/LiveChartsCore/VisualElements/LabelVisual.cs +++ b/src/LiveChartsCore/VisualElements/LabelVisual.cs @@ -117,6 +117,7 @@ protected internal override void OnInvalidated(Chart chart) { var x = (float)X; var y = (float)Y; + var clipping = Clipping.GetClipRectangle(ClippingMode, chart); if (LocationUnit == MeasureUnit.ChartValues) { @@ -146,6 +147,7 @@ protected internal override void OnInvalidated(Chart chart) if (Paint is not null) { chart.Canvas.AddDrawableTask(Paint); + Paint.SetClipRectangle(chart.Canvas, clipping); Paint.AddGeometryToPaintTask(chart.Canvas, _labelGeometry); } } diff --git a/src/LiveChartsCore/VisualElements/RelativePanel.cs b/src/LiveChartsCore/VisualElements/RelativePanel.cs index b9611846b..cb9c4c301 100644 --- a/src/LiveChartsCore/VisualElements/RelativePanel.cs +++ b/src/LiveChartsCore/VisualElements/RelativePanel.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; +using LiveChartsCore.Measure; namespace LiveChartsCore.VisualElements; @@ -33,6 +34,14 @@ public class RelativePanel : VisualElement where TDrawingContext : DrawingContext where TBackgroundGeometry : ISizedGeometry, new() { + /// + /// Initializes a new instance of the class. + /// + public RelativePanel() + { + ClippingMode = ClipMode.None; + } + private IPaint? _backgroundPaint; /// @@ -80,6 +89,8 @@ protected internal override void OnInvalidated(Chart chart) .GetProvider() .GetSolidColorPaint(new LvcColor(0, 0, 0, 0)); + var clipping = Clipping.GetClipRectangle(ClippingMode, chart); + chart.Canvas.AddDrawableTask(BackgroundPaint); BackgroundGeometry.X = (float)X; BackgroundGeometry.Y = (float)Y; @@ -88,6 +99,7 @@ protected internal override void OnInvalidated(Chart chart) BackgroundGeometry.RotateTransform = (float)Rotation; BackgroundGeometry.TranslateTransform = Translate; BackgroundPaint.AddGeometryToPaintTask(chart.Canvas, BackgroundGeometry); + BackgroundPaint.SetClipRectangle(chart.Canvas, clipping); foreach (var child in Children) { diff --git a/src/LiveChartsCore/VisualElements/StackPanel.cs b/src/LiveChartsCore/VisualElements/StackPanel.cs index d7ca4dcbe..a32f7c3e5 100644 --- a/src/LiveChartsCore/VisualElements/StackPanel.cs +++ b/src/LiveChartsCore/VisualElements/StackPanel.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; +using LiveChartsCore.Measure; namespace LiveChartsCore.VisualElements; @@ -43,6 +44,14 @@ public class StackPanel : VisualElement + /// Initializes a new instance of the class. + /// + public StackPanel() + { + ClippingMode = ClipMode.None; + } + /// /// Gets the children collection. /// @@ -137,6 +146,8 @@ protected internal override void OnInvalidated(Chart chart) .GetProvider() .GetSolidColorPaint(new LvcColor(0, 0, 0, 0)); + var clipping = Clipping.GetClipRectangle(ClippingMode, chart); + chart.Canvas.AddDrawableTask(BackgroundPaint); BackgroundGeometry.X = (float)X; BackgroundGeometry.Y = (float)Y; @@ -145,6 +156,7 @@ protected internal override void OnInvalidated(Chart chart) BackgroundGeometry.RotateTransform = (float)Rotation; BackgroundGeometry.TranslateTransform = Translate; BackgroundPaint.AddGeometryToPaintTask(chart.Canvas, BackgroundGeometry); + BackgroundPaint.SetClipRectangle(chart.Canvas, clipping); } /// diff --git a/src/LiveChartsCore/VisualElements/TableLayout.cs b/src/LiveChartsCore/VisualElements/TableLayout.cs index 175fb2286..2c32bc074 100644 --- a/src/LiveChartsCore/VisualElements/TableLayout.cs +++ b/src/LiveChartsCore/VisualElements/TableLayout.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; +using LiveChartsCore.Measure; namespace LiveChartsCore.VisualElements; @@ -44,6 +45,14 @@ public class TableLayout : VisualElement + /// Initializes a new instance of the class. + /// + public TableLayout() + { + ClippingMode = ClipMode.None; + } + /// /// Gets or sets the padding. /// @@ -173,6 +182,8 @@ public IEnumerable EnumerateChildren() protected internal override void OnInvalidated(Chart chart) { var controlSize = Measure(chart); + var clipping = Clipping.GetClipRectangle(ClippingMode, chart); + float w, h = Padding.Top; for (var r = 0; r <= _maxRow; r++) @@ -231,6 +242,7 @@ protected internal override void OnInvalidated(Chart chart) BackgroundGeometry.TranslateTransform = Translate; BackgroundPaint.AddGeometryToPaintTask(chart.Canvas, BackgroundGeometry); + BackgroundPaint.SetClipRectangle(chart.Canvas, clipping); } /// diff --git a/src/LiveChartsCore/VisualElements/VariableGeometryVisual.cs b/src/LiveChartsCore/VisualElements/VariableGeometryVisual.cs index cb62c6136..5324a7ab3 100644 --- a/src/LiveChartsCore/VisualElements/VariableGeometryVisual.cs +++ b/src/LiveChartsCore/VisualElements/VariableGeometryVisual.cs @@ -76,6 +76,7 @@ protected internal override void OnInvalidated(Chart chart) { var x = (float)X; var y = (float)Y; + var clipping = Clipping.GetClipRectangle(ClippingMode, chart); if (LocationUnit == MeasureUnit.ChartValues) { @@ -112,12 +113,14 @@ protected internal override void OnInvalidated(Chart chart) { chart.Canvas.AddDrawableTask(Fill); Fill.AddGeometryToPaintTask(chart.Canvas, Geometry); + Fill.SetClipRectangle(chart.Canvas, clipping); } if (Stroke is not null) { chart.Canvas.AddDrawableTask(Stroke); Stroke.AddGeometryToPaintTask(chart.Canvas, Geometry); + Stroke.SetClipRectangle(chart.Canvas, clipping); } } diff --git a/src/LiveChartsCore/VisualElements/VisualElement.cs b/src/LiveChartsCore/VisualElements/VisualElement.cs index 5d279b196..61b37b661 100644 --- a/src/LiveChartsCore/VisualElements/VisualElement.cs +++ b/src/LiveChartsCore/VisualElements/VisualElement.cs @@ -44,6 +44,7 @@ public abstract class VisualElement : ChartElement /// Gets the primary scaler. @@ -98,6 +99,12 @@ public abstract class VisualElement : ChartElement public int ScalesYAt { get => _scalesYAt; set => SetProperty(ref _scalesYAt, value); } + /// + /// Gets or sets the clipping mode, clipping restricts the visual element for being drawn outside of the chart area (DrawMargin), + /// default is , and means that anything outside the chart bounds will be ignored. + /// + public ClipMode ClippingMode { get => _clippingMode; set => SetProperty(ref _clippingMode, value); } + /// /// Called when the pointer goes down on the visual. /// diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs index 750855d7d..4df12b984 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs @@ -131,7 +131,8 @@ private void BuildLayout(Chart chart) Padding = new Padding(8, 0, 0, 0), MaxWidth = (float)LiveCharts.DefaultSettings.MaxTooltipsAndLegendsLabelsWidth, VerticalAlignment = Align.Start, - HorizontalAlignment = Align.Start + HorizontalAlignment = Align.Start, + ClippingMode = ClipMode.None } } }); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs index bdac0334c..1f76de782 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs @@ -148,7 +148,8 @@ public void Show(IEnumerable foundPoints, Chart foundPoints, Chart foundPoints, Chart AsDrawnC { Width = sizedGeometry.Width, Height = sizedGeometry.Height, + ClippingMode = Measure.ClipMode.None }; if (g is ISvgPath svgGeometry) From 7444467e42bc01df912e1d66f2589483314d1377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Wed, 13 Sep 2023 17:12:17 -0600 Subject: [PATCH 75/78] increase tooltip hight for tests --- tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs | 2 +- .../SeriesTests/FinancialSeriesTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs index 4d497287a..bf10792ae 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/BoxSeriesTests.cs @@ -120,7 +120,7 @@ public void ShouldPlaceToolTips() }, Name = "A", MaxBarWidth = 1000, - YToolTipLabelFormatter = x => $"{x.Coordinate.PrimaryValue}{Environment.NewLine}{x.Coordinate.PrimaryValue}{Environment.NewLine}", + YToolTipLabelFormatter = x => $"{x.Coordinate.PrimaryValue}{Environment.NewLine}{x.Coordinate.PrimaryValue}{Environment.NewLine}{x.Coordinate.PrimaryValue}{Environment.NewLine}", DataPadding = new Drawing.LvcPoint(0, 0) }; diff --git a/tests/LiveChartsCore.UnitTesting/SeriesTests/FinancialSeriesTest.cs b/tests/LiveChartsCore.UnitTesting/SeriesTests/FinancialSeriesTest.cs index a1b8c2756..26f80ecc1 100644 --- a/tests/LiveChartsCore.UnitTesting/SeriesTests/FinancialSeriesTest.cs +++ b/tests/LiveChartsCore.UnitTesting/SeriesTests/FinancialSeriesTest.cs @@ -142,7 +142,7 @@ public void ShouldPlaceToolTips() }, Name = "A", MaxBarWidth = 1000, - YToolTipLabelFormatter = x => $"{x.Coordinate.PrimaryValue}{Environment.NewLine}{x.Coordinate.PrimaryValue}{Environment.NewLine}", + YToolTipLabelFormatter = x => $"{x.Coordinate.PrimaryValue}{Environment.NewLine}{x.Coordinate.PrimaryValue}{Environment.NewLine}{x.Coordinate.PrimaryValue}{Environment.NewLine}", DataPadding = new Drawing.LvcPoint(0, 0) }; From a3ddbdcc436b403538456a517e7fd676534ba38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Thu, 14 Sep 2023 19:26:53 -0600 Subject: [PATCH 76/78] fixes #1198 --- .../SKCharts/InMemorySkiaSharpChart.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs index f0da04fe1..36934f765 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs @@ -89,18 +89,30 @@ public virtual SKImage GetImage() /// /// Saves the image to the specified path. /// - /// The path. + /// The stream. /// The format. /// The quality, an integer from 0 to 100. /// - public virtual void SaveImage(string path, SKEncodedImageFormat format = SKEncodedImageFormat.Png, int quality = 80) + public virtual void SaveImage(Stream stream, SKEncodedImageFormat format = SKEncodedImageFormat.Png, int quality = 80) { using var image = GetImage(); using var data = image.Encode(format, quality); - using var stream = File.OpenWrite(path); data.SaveTo(stream); } + /// + /// Saves the image to the specified path. + /// + /// The path. + /// The format. + /// The quality, an integer from 0 to 100. + /// + public virtual void SaveImage(string path, SKEncodedImageFormat format = SKEncodedImageFormat.Png, int quality = 80) + { + using var stream = File.OpenWrite(path); + SaveImage(stream, format, quality); + } + /// /// Draws the image to the specified canvas. /// From 298983d3489a9bd7a7aa77a628c4cb437f011f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Thu, 14 Sep 2023 20:35:49 -0600 Subject: [PATCH 77/78] fixes #1188 --- .../Drawing/Geometries/Geometry.cs | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/Geometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/Geometry.cs index 55a869ad8..90714a1d9 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/Geometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/Geometry.cs @@ -222,34 +222,48 @@ public override void Draw(SkiaSharpDrawingContext context) } } - SKPaint? originalStroke = null; - if (context.PaintTask.IsStroke && Stroke is not null) + var hasGeometryOpacity = Opacity < 1; + + if (Fill is null && Stroke is null) { - Stroke.IsStroke = true; - originalStroke = context.Paint; - Stroke.InitializeTask(context); + if (hasGeometryOpacity) context.PaintTask.ApplyOpacityMask(context, this); + OnDraw(context, context.Paint); + if (hasGeometryOpacity) context.PaintTask.RestoreOpacityMask(context, this); } - SKPaint? originalFill = null; - if (!context.PaintTask.IsStroke && Fill is not null) + else { - Fill.IsStroke = false; - originalFill = context.Paint; - Fill.InitializeTask(context); - } + var originalPaint = context.Paint; + var originalTask = context.PaintTask; - if (Opacity != 1) context.PaintTask.ApplyOpacityMask(context, this); - OnDraw(context, context.Paint); - if (Opacity != 1) context.PaintTask.RestoreOpacityMask(context, this); + // using fill and stroke on each geometry has a performance penalty, but allows + // to use different paints for each geometry. - if (context.PaintTask.IsStroke && Stroke is not null) - { - Stroke.Dispose(); - if (originalStroke != null) context.Paint = originalStroke; - } - if (!context.PaintTask.IsStroke && Fill is not null) - { - Fill.Dispose(); - if (originalFill != null) context.Paint = originalFill; + if (Fill is not null) + { + Fill.IsStroke = false; + Fill.InitializeTask(context); + + if (hasGeometryOpacity) Fill.ApplyOpacityMask(context, this); + OnDraw(context, context.Paint); + if (hasGeometryOpacity) Fill.RestoreOpacityMask(context, this); + + Fill.Dispose(); + } + + if (Stroke is not null) + { + Stroke.IsStroke = true; + Stroke.InitializeTask(context); + + if (hasGeometryOpacity) Stroke.ApplyOpacityMask(context, this); + OnDraw(context, context.Paint); + if (hasGeometryOpacity) Stroke.RestoreOpacityMask(context, this); + + Stroke.Dispose(); + } + + context.Paint = originalPaint; + context.PaintTask = originalTask; } if (HasTransform) context.Canvas.Restore(); From 659ba0a224c2b939202908df5adafa2bf5132ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Thu, 14 Sep 2023 21:39:50 -0600 Subject: [PATCH 78/78] fixes #1076 --- src/LiveChartsCore/Axis.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/LiveChartsCore/Axis.cs b/src/LiveChartsCore/Axis.cs index 80e3938b8..a250d1ae7 100644 --- a/src/LiveChartsCore/Axis.cs +++ b/src/LiveChartsCore/Axis.cs @@ -493,9 +493,8 @@ NamePadding is not null || SeparatorsPaint is not null || LabelsPaint is not nul if (_forceStepToMin) s = _minStep; var start = Math.Truncate(min / s) * s; - var separatorsSource = CustomSeparators ?? Axis.EnumerateSeparators(start, s, max); - foreach (var i in separatorsSource) + foreach (var i in EnumerateSeparators(start, max, s)) { var separatorKey = Labelers.SixRepresentativeDigits(i - 1d + 1d); var labelContent = i < min || i > max ? string.Empty : TryGetLabelOrLogError(labeler, i - 1d + 1d); @@ -781,9 +780,16 @@ public void InvalidateCrosshair(Chart chart, LvcPoint pointerPo chart.Canvas.Invalidate(); } - private static IEnumerable EnumerateSeparators(double start, double s, double max) + private IEnumerable EnumerateSeparators(double start, double end, double step) { - for (var i = start - s; i <= max + s; i += s) yield return i; + if (CustomSeparators is not null) + { + foreach (var s in CustomSeparators) yield return s; + yield break; + } + + var relativeEnd = end - start; + for (var i = 0d; i <= relativeEnd; i += step) yield return start + i; } private static ChartPoint? FindClosestPoint( @@ -852,7 +858,7 @@ public virtual LvcSize GetPossibleSize(Chart chart) var h = 0f; var r = (float)LabelsRotation; - for (var i = start; i <= max; i += s) + foreach (var i in EnumerateSeparators(start, max, s)) { var textGeometry = new TTextGeometry { @@ -1004,7 +1010,7 @@ private LvcSize GetPossibleMaxLabelSize(Chart chart) if (max - min == 0) return maxLabelSize; - for (var i = min; i <= max; i += s) + foreach (var i in EnumerateSeparators(min, max, s)) { var textGeometry = new TTextGeometry {