diff --git a/src/LiveChartsCore/CoreHeatLandSeries.cs b/src/LiveChartsCore/CoreHeatLandSeries.cs index 6892307c3..ed34a1adb 100644 --- a/src/LiveChartsCore/CoreHeatLandSeries.cs +++ b/src/LiveChartsCore/CoreHeatLandSeries.cs @@ -102,7 +102,7 @@ public void Measure(MapContext context) if (!_isHeatInCanvas) { - context.View.Canvas.AddDrawableTask(_heatPaint); + context.View.CoreCanvas.AddDrawableTask(_heatPaint); _isHeatInCanvas = true; } @@ -124,7 +124,7 @@ public void Measure(MapContext context) foreach (var land in Lands ?? []) { _ = Maps.BuildProjector( - context.View.MapProjection, [context.View.Width, context.View.Height]); + context.View.MapProjection, [context.View.ControlSize.Width, context.View.ControlSize.Height]); var heat = HeatFunctions.InterpolateColor((float)land.Value, bounds, HeatMap, heatStops); @@ -156,8 +156,11 @@ public void Delete(MapContext context) /// /// Initializes the series. /// - protected void IntitializeSeries(Paint heatPaint) => + protected void IntitializeSeries(Paint heatPaint) + { + heatPaint.PaintStyle = PaintStyle.Fill; _heatPaint = heatPaint; + } /// /// Called to invoke the property changed event. diff --git a/src/LiveChartsCore/Geo/IGeoMapView.cs b/src/LiveChartsCore/Geo/IGeoMapView.cs index 3b88e947f..5279e7a69 100644 --- a/src/LiveChartsCore/Geo/IGeoMapView.cs +++ b/src/LiveChartsCore/Geo/IGeoMapView.cs @@ -22,7 +22,7 @@ using System; using System.Collections.Generic; -using LiveChartsCore.Motion; +using LiveChartsCore.Kernel.Sketches; using LiveChartsCore.Painting; namespace LiveChartsCore.Geo; @@ -30,28 +30,13 @@ namespace LiveChartsCore.Geo; /// /// Defines a geographic map. /// -public interface IGeoMapView +public interface IGeoMapView : IDrawnView { /// /// Gets or sets the active map. /// DrawnMap ActiveMap { get; set; } - /// - /// Gets the motion canvas. - /// - CoreMotionCanvas Canvas { get; } - - /// - /// Gets the control width. - /// - float Width { get; } - - /// - /// Gets the control height. - /// - float Height { get; } - /// /// Gets or sets the stroke. /// @@ -83,10 +68,10 @@ public interface IGeoMapView /// object SyncContext { get; set; } - /// - /// Gets or sets the view command. - /// - object? ViewCommand { get; set; } + ///// + ///// Gets or sets the view command. + ///// + //object? ViewCommand { get; set; } /// /// Invokes an action in the UI thread. diff --git a/src/LiveChartsCore/GeoMapChart.cs b/src/LiveChartsCore/GeoMapChart.cs index 5319976f5..e8675cc91 100644 --- a/src/LiveChartsCore/GeoMapChart.cs +++ b/src/LiveChartsCore/GeoMapChart.cs @@ -111,8 +111,8 @@ public virtual void Update(ChartUpdateParams? chartUpdateParams = null) /// public void Unload() { - if (View.Stroke is not null) View.Canvas.RemovePaintTask(View.Stroke); - if (View.Fill is not null) View.Canvas.RemovePaintTask(View.Fill); + if (View.Stroke is not null) View.CoreCanvas.RemovePaintTask(View.Stroke); + if (View.Fill is not null) View.CoreCanvas.RemovePaintTask(View.Fill); _everMeasuredSeries.Clear(); _heatPaint = null!; @@ -125,7 +125,7 @@ public void Unload() _activeMap = null!; _mapFactory = null!; - View.Canvas.Dispose(); + View.CoreCanvas.Dispose(); } /// @@ -161,7 +161,7 @@ protected virtual Task UpdateThrottlerUnlocked() { View.InvokeOnUIThread(() => { - lock (View.Canvas.Sync) + lock (View.CoreCanvas.Sync) { if (_isUnloaded) return; Measure(); @@ -177,32 +177,32 @@ protected internal void Measure() { if (_activeMap is not null && _activeMap != View.ActiveMap) { - _previousStroke?.ClearGeometriesFromPaintTask(View.Canvas); - _previousFill?.ClearGeometriesFromPaintTask(View.Canvas); + _previousStroke?.ClearGeometriesFromPaintTask(View.CoreCanvas); + _previousFill?.ClearGeometriesFromPaintTask(View.CoreCanvas); _previousFill = null; _previousStroke = null; - View.Canvas.Clear(); + View.CoreCanvas.Clear(); } _activeMap = View.ActiveMap; if (!_isHeatInCanvas) { - View.Canvas.AddDrawableTask(_heatPaint); + View.CoreCanvas.AddDrawableTask(_heatPaint); _isHeatInCanvas = true; } if (_previousStroke != View.Stroke) { if (_previousStroke is not null) - View.Canvas.RemovePaintTask(_previousStroke); + View.CoreCanvas.RemovePaintTask(_previousStroke); if (View.Stroke is not null) { if (View.Stroke.ZIndex == 0) View.Stroke.ZIndex = PaintConstants.GeoMapStrokeZIndex; View.Stroke.PaintStyle = PaintStyle.Stroke; - View.Canvas.AddDrawableTask(View.Stroke); + View.CoreCanvas.AddDrawableTask(View.Stroke); } _previousStroke = View.Stroke; @@ -211,12 +211,12 @@ protected internal void Measure() if (_previousFill != View.Fill) { if (_previousFill is not null) - View.Canvas.RemovePaintTask(_previousFill); + View.CoreCanvas.RemovePaintTask(_previousFill); if (View.Fill is not null) { View.Fill.PaintStyle = PaintStyle.Fill; - View.Canvas.AddDrawableTask(View.Fill); + View.CoreCanvas.AddDrawableTask(View.Fill); } _previousFill = View.Fill; @@ -227,7 +227,7 @@ protected internal void Measure() var context = new MapContext( this, View, View.ActiveMap, - Maps.BuildProjector(View.MapProjection, [View.Width, View.Height])); + Maps.BuildProjector(View.MapProjection, [View.ControlSize.Width, View.ControlSize.Height])); _mapFactory.GenerateLands(context); @@ -245,7 +245,7 @@ protected internal void Measure() _ = _everMeasuredSeries.Remove(series); } - View.Canvas.Invalidate(); + View.CoreCanvas.Invalidate(); } private Task PanningThrottlerUnlocked() @@ -253,7 +253,7 @@ private Task PanningThrottlerUnlocked() return Task.Run(() => View.InvokeOnUIThread(() => { - lock (View.Canvas.Sync) + lock (View.CoreCanvas.Sync) { Pan( new LvcPoint( diff --git a/src/LiveChartsCore/Kernel/Sketches/IChartView.cs b/src/LiveChartsCore/Kernel/Sketches/IChartView.cs index 543743878..86185723c 100644 --- a/src/LiveChartsCore/Kernel/Sketches/IChartView.cs +++ b/src/LiveChartsCore/Kernel/Sketches/IChartView.cs @@ -25,7 +25,6 @@ using LiveChartsCore.Drawing; using LiveChartsCore.Kernel.Events; using LiveChartsCore.Measure; -using LiveChartsCore.Motion; using LiveChartsCore.Painting; using LiveChartsCore.Themes; using LiveChartsCore.VisualElements; @@ -35,7 +34,7 @@ namespace LiveChartsCore.Kernel.Sketches; /// /// Defines a chart view /// -public interface IChartView +public interface IChartView : IDrawnView { /// /// Gets or sets the series collection. @@ -80,14 +79,6 @@ public interface IChartView /// LvcColor BackColor { get; } - /// - /// Gets the size of the control. - /// - /// - /// The size of the control. - /// - LvcSize ControlSize { get; } - /// /// Gets or sets the draw margin, if this property is null, the library will calculate a margin, this margin is the distance /// between the view bounds and the drawable area. @@ -176,14 +167,6 @@ public interface IChartView /// bool AutoUpdateEnabled { get; set; } - /// - /// Gets the core canvas. - /// - /// - /// The core canvas. - /// - CoreMotionCanvas CoreCanvas { get; } - /// /// Gets or sets the chart title. /// diff --git a/src/LiveChartsCore/Kernel/Sketches/IDrawnView.cs b/src/LiveChartsCore/Kernel/Sketches/IDrawnView.cs new file mode 100644 index 000000000..a9fb443fb --- /dev/null +++ b/src/LiveChartsCore/Kernel/Sketches/IDrawnView.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 LiveChartsCore.Drawing; +using LiveChartsCore.Motion; + +namespace LiveChartsCore.Kernel.Sketches; + +/// +/// Defines a drawn view. +/// +public interface IDrawnView +{ + /// + /// Gets the motion canvas. + /// + CoreMotionCanvas CoreCanvas { get; } + + /// + /// Gets the size of the control. + /// + /// + /// The size of the control. + /// + LvcSize ControlSize { get; } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/GeoMap.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/GeoMap.cs index 86ef8df91..2fea3fb14 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/GeoMap.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/GeoMap.cs @@ -20,255 +20,17 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -using System; -using System.Collections.Generic; -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Input; -using Avalonia.Markup.Xaml; -using Avalonia.Media; -using Avalonia.Threading; -using LiveChartsCore.Drawing; using LiveChartsCore.Geo; -using LiveChartsCore.Kernel.Observers; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Painting; -using SkiaSharp; -namespace LiveChartsCore.SkiaSharpView.Avalonia; - -/// -public partial class GeoMap : UserControl, IGeoMapView -{ - private readonly CollectionDeepObserver _seriesObserver; - private readonly GeoMapChart _core; - - /// - /// Initializes a new instance of the class. - /// - public GeoMap() - { - Content = new MotionCanvas(); - _core = new GeoMapChart(this); - _seriesObserver = new CollectionDeepObserver(() => _core?.Update()); - - Background = new SolidColorBrush(new Color(0, 0, 0, 0)); - - PointerWheelChanged += OnPointerWheelChanged; - PointerPressed += OnPointerPressed; - PointerMoved += OnPointerMoved; - PointerExited += OnPointerLeave; - - //Shapes = Enumerable.Empty>(); - ActiveMap = Maps.GetWorldMap(); - SyncContext = new object(); - - DetachedFromVisualTree += GeoMap_DetachedFromVisualTree; - } - - #region dependency props - - /// - /// The active map property. - /// - public static readonly AvaloniaProperty ActiveMapProperty = - AvaloniaProperty.Register(nameof(ActiveMap), null, inherits: true); - - /// - /// The active map property. - /// - public static readonly AvaloniaProperty SyncContextProperty = - AvaloniaProperty.Register(nameof(SyncContext), null, inherits: true); - - /// - /// The active map property. - /// - public static readonly AvaloniaProperty ViewCommandProperty = - AvaloniaProperty.Register(nameof(ViewCommand), null, inherits: true); - - /// - /// The projection property. - /// - public static readonly AvaloniaProperty MapProjectionProperty = - AvaloniaProperty.Register(nameof(MapProjection), MapProjection.Default, inherits: true); - - /// - /// The series property. - /// - public static readonly AvaloniaProperty> SeriesProperty = - AvaloniaProperty.Register>(nameof(Series), - [], inherits: true); - - /// - /// The stroke property. - /// - public static readonly AvaloniaProperty StrokeProperty = - AvaloniaProperty.Register(nameof(Stroke), - new SolidColorPaint(new SKColor(255, 255, 255, 255), 1) { PaintStyle = PaintStyle.Stroke }, inherits: true); - - /// - /// The fill color property. - /// - public static readonly AvaloniaProperty FillProperty = - AvaloniaProperty.Register(nameof(Fill), - new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }, inherits: true); - - #endregion - - #region props - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - bool IGeoMapView.DesignerMode => Design.IsDesignMode; - - /// - public object SyncContext - { - get => GetValue(SyncContextProperty)!; - set => SetValue(SyncContextProperty, value); - } - - /// - public object? ViewCommand - { - get => GetValue(ViewCommandProperty); - set => SetValue(ViewCommandProperty, value); - } - - /// - public CoreMotionCanvas Canvas - { - get - { - var canvas = this.FindControl("canvas"); - return canvas!.CanvasCore; - } - } +// ============================================================================== +// +// use the LiveChartsGeneratedCode.SourceGenMapChart class to add avalonia specific +// code, this class is just to expose the GeoMap class in this namespace. +// +// ============================================================================== - /// - public DrawnMap ActiveMap - { - get => (DrawnMap)GetValue(ActiveMapProperty)!; - set => SetValue(ActiveMapProperty, value); - } - - /// - float IGeoMapView.Width => (float)Bounds.Width; - - /// - float IGeoMapView.Height => (float)Bounds.Height; - - /// - public MapProjection MapProjection - { - get => (MapProjection)GetValue(MapProjectionProperty)!; - set => SetValue(MapProjectionProperty, value); - } - - /// - public Paint? Stroke - { - get => (Paint?)GetValue(StrokeProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - _ = SetValue(StrokeProperty, value); - } - } - - /// - public Paint? Fill - { - get => (Paint?)GetValue(FillProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - _ = SetValue(FillProperty, value); - } - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty)!; - set => SetValue(SeriesProperty, value); - } - - #endregion - - void IGeoMapView.InvokeOnUIThread(Action action) => - Dispatcher.UIThread.Post(action); - - /// - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - base.OnPropertyChanged(change); - - if (change.Property.Name == nameof(IsPointerOver)) return; - - if (change.Property.Name == nameof(Series)) - { - _seriesObserver?.Dispose(); - _seriesObserver?.Initialize((IEnumerable?)change.NewValue); - } - - if (change.Property.Name == nameof(ViewCommand)) - { - _core.ViewTo(ViewCommand); - return; - } - - _core?.Update(); - } - - private void OnPointerWheelChanged(object? sender, PointerWheelEventArgs e) - { - if (_core is null) return; - - var p = e.GetPosition(this); - - _core.ViewTo( - new ZoomOnPointerView( - new LvcPoint((float)p.X, (float)p.Y), - e.Delta.Y > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut)); - } - - private void OnPointerPressed(object? sender, PointerPressedEventArgs e) - { - if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return; - var p = e.GetPosition(this); - foreach (var w in desktop.Windows) w.PointerReleased += OnWindowPointerReleased; - _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y)); - } - - private void OnPointerMoved(object? sender, PointerEventArgs e) - { - var p = e.GetPosition(this); - _core?.InvokePointerMove(new LvcPoint((float)p.X, (float)p.Y)); - } - - private void OnWindowPointerReleased(object? sender, PointerReleasedEventArgs e) - { - if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return; - foreach (var w in desktop.Windows) w.PointerReleased -= OnWindowPointerReleased; - var p = e.GetPosition(this); - _core?.InvokePointerUp(new LvcPoint((float)p.X, (float)p.Y)); - } - - private void OnPointerLeave(object? sender, PointerEventArgs e) => - _core?.InvokePointerLeft(); - - private void GeoMap_DetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) - { - if (_core is null) return; - _core.Unload(); - } +namespace LiveChartsCore.SkiaSharpView.Avalonia; - private void InitializeComponent() => - AvaloniaXamlLoader.Load(this); -} +/// +public class GeoMap : LiveChartsGeneratedCode.SourceGenMapChart +{ } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsGeneratedCode/SourceGenChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsGeneratedCode/SourceGenChart.cs index 2106f94d6..ac5324a04 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsGeneratedCode/SourceGenChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsGeneratedCode/SourceGenChart.cs @@ -75,7 +75,7 @@ protected SourceGenChart() private MotionCanvas CanvasView => (MotionCanvas)Content!; - /// + /// public CoreMotionCanvas CoreCanvas => CanvasView.CanvasCore; bool IChartView.DesignerMode => Design.IsDesignMode; @@ -84,7 +84,7 @@ protected SourceGenChart() Background is not ISolidColorBrush b ? CoreCanvas._virtualBackgroundColor : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); - LvcSize IChartView.ControlSize => new() { Width = (float)CanvasView.Bounds.Width, Height = (float)CanvasView.Bounds.Height }; + LvcSize IDrawnView.ControlSize => new() { Width = (float)CanvasView.Bounds.Width, Height = (float)CanvasView.Bounds.Height }; private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsGeneratedCode/SourceGenMapChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsGeneratedCode/SourceGenMapChart.cs new file mode 100644 index 000000000..1078bb850 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsGeneratedCode/SourceGenMapChart.cs @@ -0,0 +1,79 @@ +// 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; +using Avalonia.Controls; +using Avalonia.Rendering; +using Avalonia.Threading; +using LiveChartsCore.Drawing; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Avalonia; + +namespace LiveChartsGeneratedCode; + +// ============================================================================== +// +// this file contains the Avalonia specific code for the SourceGenMapChart class, +// the rest of the code can be found in the _Shared project. +// +// ============================================================================== + +/// +public partial class SourceGenMapChart : UserControl, IGeoMapView, ICustomHitTest +{ + /// + /// Initializes a new instance of the class. + /// + public SourceGenMapChart() + { + Content = new MotionCanvas(); + InitializeChartControl(); + + SizeChanged += (s, e) => + CoreChart.Update(); + + DetachedFromVisualTree += GeoMap_DetachedFromVisualTree; + } + + private MotionCanvas MotionCanvas => (MotionCanvas)Content!; + + /// + public CoreMotionCanvas CoreCanvas => MotionCanvas.CanvasCore; + + bool IGeoMapView.DesignerMode => Design.IsDesignMode; + LvcSize IDrawnView.ControlSize => new() { Width = (float)MotionCanvas.Bounds.Width, Height = (float)MotionCanvas.Bounds.Height }; + + private void GeoMap_DetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e) + { + if (CoreChart is null) return; + CoreChart.Unload(); + } + + void IGeoMapView.InvokeOnUIThread(Action action) => + Dispatcher.UIThread.Post(action); + + bool ICustomHitTest.HitTest(Point point) => + new Rect(Bounds.Size).Contains(point); +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/GeoMap.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/GeoMap.cs index 98d945dae..be46f0159 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/GeoMap.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/GeoMap.cs @@ -20,253 +20,17 @@ // 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.ComponentModel; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using LiveChartsCore.Drawing; -using LiveChartsCore.Geo; -using LiveChartsCore.Kernel.Observers; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Painting; -using SkiaSharp; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.SkiaSharpView.WPF; -/// -/// Defines a geographic map. -/// -/// -public class GeoMap : UserControl, IGeoMapView -{ - private readonly CollectionDeepObserver _seriesObserver; - private GeoMapChart? _core; - private MotionCanvas? _canvas; +// ============================================================================== +// +// use the LiveChartsGeneratedCode.SourceGenMapChart class to add wpf specific +// code, this class is just to expose the GeoMap class in this namespace. +// +// ============================================================================== - /// - /// Initializes a new instance of the class. - /// - public GeoMap() - { - MouseDown += OnMouseDown; - MouseMove += OnMouseMove; - MouseUp += OnMouseUp; - MouseLeave += OnMouseLeave; - MouseWheel += OnMouseWheel; - - SizeChanged += GeoMap_SizeChanged; - - _seriesObserver = new CollectionDeepObserver(() => _core?.Update()); - - SetCurrentValue(SeriesProperty, Enumerable.Empty()); - SetCurrentValue(ActiveMapProperty, Maps.GetWorldMap()); - SetCurrentValue(SyncContextProperty, new object()); - - Unloaded += GeoMap_Unloaded; - } - - #region dependency props - - /// - /// The active map property - /// - public static readonly DependencyProperty ActiveMapProperty = - DependencyProperty.Register(nameof(ActiveMap), typeof(DrawnMap), 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(); - seriesObserver?.Initialize((IEnumerable)args.NewValue); - chart._core?.Update(); - })); - - /// - /// The stroke property - /// - public static readonly DependencyProperty StrokeProperty = - DependencyProperty.Register( - nameof(Stroke), typeof(Paint), typeof(GeoMap), - new PropertyMetadata(new SolidColorPaint(new SKColor(255, 255, 255, 255)) { PaintStyle = PaintStyle.Stroke }, OnDependencyPropertyChanged)); - - /// - /// The fill property - /// - public static readonly DependencyProperty FillProperty = - DependencyProperty.Register( - nameof(Fill), typeof(Paint), typeof(GeoMap), - new PropertyMetadata(new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }, OnDependencyPropertyChanged)); - - #endregion - - #region props - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - bool IGeoMapView.DesignerMode => DesignerProperties.GetIsInDesignMode(this); - - /// - public object SyncContext - { - get => GetValue(SyncContextProperty); - set => SetValue(SyncContextProperty, value); - } - - /// - public object? ViewCommand - { - get => GetValue(ViewCommandProperty); - set => SetValue(ViewCommandProperty, value); - } - - /// - public CoreMotionCanvas Canvas => _canvas is null - ? throw new Exception($"Canvas not found") - : _canvas.CanvasCore; - - /// - public DrawnMap ActiveMap - { - get => (DrawnMap)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 Paint? Stroke - { - get => (Paint)GetValue(StrokeProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - SetValue(StrokeProperty, value); - } - } - - /// - public Paint? Fill - { - get => (Paint)GetValue(FillProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - SetValue(FillProperty, value); - } - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty); - set => SetValue(SeriesProperty, value); - } - - #endregion - - /// - /// Called when the template is applied. - /// - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - Content = _canvas = new MotionCanvas(false); - _core = new GeoMapChart(this); - } - - void IGeoMapView.InvokeOnUIThread(Action action) => - Dispatcher.Invoke(action); - - private void GeoMap_SizeChanged(object sender, SizeChangedEventArgs e) => - _core?.Update(); - - private void OnMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) - { - _ = CaptureMouse(); - var p = e.GetPosition(this); - _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y)); - } - - private void OnMouseMove(object sender, System.Windows.Input.MouseEventArgs e) - { - var p = e.GetPosition(this); - _core?.InvokePointerMove(new LvcPoint((float)p.X, (float)p.Y)); - } - - private void OnMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) - { - var p = e.GetPosition(this); - _core?.InvokePointerUp(new LvcPoint((float)p.X, (float)p.Y)); - ReleaseMouseCapture(); - } - - private void OnMouseLeave(object sender, System.Windows.Input.MouseEventArgs e) => - _core?.InvokePointerLeft(); - - private void OnMouseWheel(object? sender, System.Windows.Input.MouseWheelEventArgs e) - { - if (_core is null) throw new Exception("core not found"); - var p = e.GetPosition(this); - _core.ViewTo( - new ZoomOnPointerView( - new LvcPoint((float)p.X, (float)p.Y), e.Delta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut)); - } - - private void GeoMap_Unloaded(object sender, RoutedEventArgs e) => _core?.Unload(); - - private static void OnDependencyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args) - { - var chart = (GeoMap)o; - chart._core?.Update(); - } -} +/// +public sealed partial class GeoMap : LiveChartsGeneratedCode.SourceGenMapChart +{ } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsGeneratedCode/SourceGenChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsGeneratedCode/SourceGenChart.cs index 4efd0174a..8418ff4e7 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsGeneratedCode/SourceGenChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsGeneratedCode/SourceGenChart.cs @@ -70,7 +70,7 @@ protected SourceGenChart() private MotionCanvas MotionCanvas => (MotionCanvas)Content; - /// + /// public CoreMotionCanvas CoreCanvas => MotionCanvas.CanvasCore; bool IChartView.DesignerMode => DesignerProperties.GetIsInDesignMode(this); @@ -79,7 +79,7 @@ protected SourceGenChart() Background is not SolidColorBrush b ? CoreCanvas._virtualBackgroundColor : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); - LvcSize IChartView.ControlSize => new() { Width = (float)ActualWidth, Height = (float)ActualHeight }; + LvcSize IDrawnView.ControlSize => new() { Width = (float)ActualWidth, Height = (float)ActualHeight }; private void OnLoaded(object sender, RoutedEventArgs e) { diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsGeneratedCode/SourceGenMapChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsGeneratedCode/SourceGenMapChart.cs new file mode 100644 index 000000000..831a94900 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsGeneratedCode/SourceGenMapChart.cs @@ -0,0 +1,75 @@ +// 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.ComponentModel; +using System.Windows; +using System.Windows.Controls; +using LiveChartsCore; +using LiveChartsCore.Drawing; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.WPF; + +namespace LiveChartsGeneratedCode; + +// ============================================================================== +// +// this file contains the WPF specific code for the SourceGenMapChart class, +// the rest of the code can be found in the _Shared project. +// +// ============================================================================== + +/// +public abstract partial class SourceGenMapChart : UserControl, IGeoMapView +{ + /// + /// Initializes a new instance of the class. + /// + /// Default colors are not valid + protected SourceGenMapChart() + { + Content = new MotionCanvas(false); + + SizeChanged += (s, e) => + CoreChart.Update(); + + InitializeChartControl(); + + Unloaded += OnUnloaded; + } + + private MotionCanvas MotionCanvas => (MotionCanvas)Content; + + /// + public CoreMotionCanvas CoreCanvas => MotionCanvas.CanvasCore; + + bool IGeoMapView.DesignerMode => DesignerProperties.GetIsInDesignMode(this); + LvcSize IDrawnView.ControlSize => new() { Width = (float)ActualWidth, Height = (float)ActualHeight }; + + private void OnUnloaded(object sender, RoutedEventArgs e) => + CoreChart?.Unload(); + + void IGeoMapView.InvokeOnUIThread(Action action) => + Dispatcher.Invoke(action); +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/GeoMap.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/GeoMap.cs index c8ff86f99..5bb28b447 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/GeoMap.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/GeoMap.cs @@ -20,172 +20,17 @@ // 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.ComponentModel; -using System.Windows.Forms; -using LiveChartsCore.Drawing; -using LiveChartsCore.Geo; -using LiveChartsCore.Kernel.Observers; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Painting; -using SkiaSharp; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.SkiaSharpView.WinForms; -/// -/// The geo map control. -/// -/// -public partial class GeoMap : UserControl, IGeoMapView -{ - private readonly GeoMapChart _core; - private readonly CollectionDeepObserver _seriesObserver; - private DrawnMap _activeMap; +// ============================================================================== +// +// use the LiveChartsGeneratedCode.SourceGenMapChart class to add winui/uno specific +// code, this class is just to expose the GeoMap class in this namespace. +// +// ============================================================================== - /// - /// Initializes a new instance of the class. - /// - public GeoMap() - { - InitializeComponent(); - _activeMap = Maps.GetWorldMap(); - - _core = new GeoMapChart(this); - - _seriesObserver = new CollectionDeepObserver(() => _core?.Update()); - - var c = Controls[0].Controls[0]; - - c.MouseDown += OnMouseDown; - c.MouseMove += OnMouseMove; - c.MouseUp += OnMouseUp; - c.MouseLeave += OnMouseLeave; - c.MouseWheel += OnMouseWheel; - - Resize += GeoMap_Resize; - } - - /// - public CoreMotionCanvas Canvas => motionCanvas1.CanvasCore; - - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public bool AutoUpdateEnabled { get; set; } = true; - - /// - bool IGeoMapView.DesignerMode => LicenseManager.UsageMode == LicenseUsageMode.Designtime; - - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public object SyncContext { get; set; } = new(); - - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public object? ViewCommand - { - get; - set - { - field = value; - if (value is not null) _core.ViewTo(value); - } - } = null; - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public DrawnMap ActiveMap { get => _activeMap; set { _activeMap = value; OnPropertyChanged(); } } - - /// - float IGeoMapView.Width => ClientSize.Width; - - /// - float IGeoMapView.Height => ClientSize.Height; - - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public MapProjection MapProjection { get; set { field = value; OnPropertyChanged(); } } = MapProjection.Default; - - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Paint? Stroke - { - get; - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - field = value; - OnPropertyChanged(); - } - } = new SolidColorPaint(new SKColor(255, 255, 255, 255)) { PaintStyle = PaintStyle.Stroke }; - - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Paint? Fill - { - get; - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - field = value; - OnPropertyChanged(); - } - } = new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }; - - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public IEnumerable Series - { - get; - set - { - _seriesObserver?.Dispose(); - _seriesObserver?.Initialize(value); - field = value; - OnPropertyChanged(); - } - } = []; - - void IGeoMapView.InvokeOnUIThread(Action action) - { - if (!IsHandleCreated) return; - _ = BeginInvoke(action).AsyncWaitHandle.WaitOne(); - } - - /// - /// Called when a property changes. - /// - protected void OnPropertyChanged() => - _core?.Update(); - - /// - protected override void OnHandleDestroyed(EventArgs e) - { - base.OnHandleDestroyed(e); - _core?.Unload(); - } - - private void GeoMap_Resize(object? sender, EventArgs e) => - _core?.Update(); - - private void OnMouseDown(object? sender, MouseEventArgs e) => - _core?.InvokePointerDown(new(e.Location.X, e.Location.Y)); - private void OnMouseMove(object? sender, MouseEventArgs e) => - _core?.InvokePointerMove(new(e.Location.X, e.Location.Y)); - - private void OnMouseUp(object? sender, MouseEventArgs e) => - _core?.InvokePointerUp(new(e.Location.X, e.Location.Y)); - - private void OnMouseLeave(object? sender, EventArgs e) => - _core?.InvokePointerLeft(); - - private void OnMouseWheel(object? sender, MouseEventArgs e) - { - if (_core is null) throw new Exception("core not found"); - var p = e.Location; - _core.ViewTo( - new ZoomOnPointerView(new LvcPoint(p.X, p.Y), e.Delta > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut)); - Capture = true; - } -} +/// +public sealed partial class GeoMap : LiveChartsGeneratedCode.SourceGenMapChart +{ } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenChart.cs index 9a87c91cf..edb034874 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenChart.cs @@ -55,7 +55,7 @@ protected SourceGenChart() motionCanvas.TabIndex = 0; AutoScaleMode = AutoScaleMode.Font; Controls.Add(motionCanvas); - Name = "CartesianChart"; + Name = "Chart"; ResumeLayout(true); InitializeChartControl(); @@ -71,7 +71,7 @@ protected SourceGenChart() c.MouseLeave += OnMouseLeave; } - /// "/> + /// "/> public CoreMotionCanvas CoreCanvas => ((MotionCanvas)Controls[0]).CanvasCore; bool IChartView.DesignerMode => LicenseManager.UsageMode == LicenseUsageMode.Designtime; @@ -82,7 +82,7 @@ protected SourceGenChart() LvcColor IChartView.BackColor => new(BackColor.R, BackColor.G, BackColor.B, BackColor.A); [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - LvcSize IChartView.ControlSize => new() { Width = Width, Height = Height }; + LvcSize IDrawnView.ControlSize => new() { Width = Width, Height = Height }; /// /// Gets the drawn control. diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenMapChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenMapChart.cs new file mode 100644 index 000000000..45a8cff9f --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenMapChart.cs @@ -0,0 +1,100 @@ +// 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.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using LiveChartsCore.Drawing; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.WinForms; + +namespace LiveChartsGeneratedCode; + +// ============================================================================== +// +// this file contains the WinForms specific code for the SourceGenMapChart class, +// the rest of the code can be found in the _Shared project. +// +// ============================================================================== + +/// +public abstract partial class SourceGenMapChart : UserControl, IGeoMapView +{ + /// + /// Initializes a new instance of the class. + /// + protected SourceGenMapChart() + { + var motionCanvas = new MotionCanvas(); + SuspendLayout(); + motionCanvas.Dock = DockStyle.Fill; + motionCanvas.Location = new Point(0, 0); + motionCanvas.Name = "motionCanvas"; + motionCanvas.Size = new Size(150, 150); + motionCanvas.TabIndex = 0; + AutoScaleMode = AutoScaleMode.Font; + Controls.Add(motionCanvas); + Name = "GeoChart"; + ResumeLayout(true); + + InitializeChartControl(); + + motionCanvas.Resize += (s, e) => + CoreChart.Update(); + } + + /// "/> + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public CoreMotionCanvas CoreCanvas => ((MotionCanvas)Controls[0]).CanvasCore; + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + bool IGeoMapView.DesignerMode => false; + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + LvcSize IDrawnView.ControlSize => new() { Width = Width, Height = Height }; + + /// + /// Gets the drawn control. + /// + /// + public Control GetDrawnControl() => Controls[0].Controls[0]; + + void IGeoMapView.InvokeOnUIThread(Action action) + { + if (!IsHandleCreated) return; + _ = BeginInvoke(action); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + /// + protected override void OnHandleDestroyed(EventArgs e) + { + base.OnHandleDestroyed(e); + CoreChart?.Unload(); + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenMapChart.resx b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenMapChart.resx new file mode 100644 index 000000000..f298a7be8 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsGeneratedCode/SourceGenMapChart.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/src/skiasharp/LiveChartsCore.SkiaSharp/MapFactory.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/MapFactory.cs index 115d34f64..7c8bcc97e 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/MapFactory.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/MapFactory.cs @@ -64,13 +64,13 @@ public void GenerateLands(MapContext context) if (fill is not null) { - context.View.Canvas.AddDrawableTask(fill); + context.View.CoreCanvas.AddDrawableTask(fill); _ = _usedPaints.Add(fill); _ = toRemovePaints.Remove(fill); } if (stroke is not null) { - context.View.Canvas.AddDrawableTask(stroke); + context.View.CoreCanvas.AddDrawableTask(stroke); _ = _usedPaints.Add(stroke); _ = toRemovePaints.Remove(stroke); } @@ -97,8 +97,8 @@ public void GenerateLands(MapContext context) _ = _usedPathShapes.Add(shape); _ = toRemovePathShapes.Remove(shape); - stroke?.AddGeometryToPaintTask(context.View.Canvas, shape); - fill?.AddGeometryToPaintTask(context.View.Canvas, shape); + stroke?.AddGeometryToPaintTask(context.View.CoreCanvas, shape); + fill?.AddGeometryToPaintTask(context.View.CoreCanvas, shape); shape.Commands.Clear(); @@ -131,8 +131,8 @@ public void GenerateLands(MapContext context) foreach (var shape in toRemovePathShapes) { - stroke?.RemoveGeometryFromPaintTask(context.View.Canvas, shape); - fill?.RemoveGeometryFromPaintTask(context.View.Canvas, shape); + stroke?.RemoveGeometryFromPaintTask(context.View.CoreCanvas, shape); + fill?.RemoveGeometryFromPaintTask(context.View.CoreCanvas, shape); shape.Commands.Clear(); @@ -143,7 +143,7 @@ public void GenerateLands(MapContext context) foreach (var paint in toRemovePaints) { _ = _usedPaints.Remove(paint); - context.View.Canvas.RemovePaintTask(paint); + context.View.CoreCanvas.RemovePaintTask(paint); } foreach (var layerName in toRemoveLayers) @@ -182,20 +182,20 @@ public void Dispose() var shape = landData.Shape; if (shape is null) continue; - stroke?.RemoveGeometryFromPaintTask(_mapView.Canvas, shape); - fill?.AddGeometryToPaintTask(_mapView.Canvas, shape); + stroke?.RemoveGeometryFromPaintTask(_mapView.CoreCanvas, shape); + fill?.AddGeometryToPaintTask(_mapView.CoreCanvas, shape); landData.Shape = null; } } foreach (var paint in _usedPaints) { - _mapView.Canvas.RemovePaintTask(paint); - paint.ClearGeometriesFromPaintTask(_mapView.Canvas); + _mapView.CoreCanvas.RemovePaintTask(paint); + paint.ClearGeometriesFromPaintTask(_mapView.CoreCanvas); } - if (stroke is not null) _mapView.Canvas.RemovePaintTask(stroke); - if (fill is not null) _mapView.Canvas.RemovePaintTask(fill); + if (stroke is not null) _mapView.CoreCanvas.RemovePaintTask(stroke); + if (fill is not null) _mapView.CoreCanvas.RemovePaintTask(fill); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs index b7992c3d5..c0015ddd3 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/InMemorySkiaSharpChart.cs @@ -35,16 +35,16 @@ namespace LiveChartsCore.SkiaSharpView.SKCharts; /// /// Initializes a new instance of the class. /// -public abstract class InMemorySkiaSharpChart(IChartView? chartView = null) +public abstract class InMemorySkiaSharpChart(IDrawnView? drawnView = null) { - private readonly IChartView? _chartView = chartView; + private readonly IDrawnView? _drawnView = drawnView; static InMemorySkiaSharpChart() { _ = LiveChartsSkiaSharp.EnsureInitialized(); } - /// + /// public CoreMotionCanvas CoreCanvas { get; } = new(); internal bool ExplicitDisposing { get; set; } @@ -65,7 +65,7 @@ static InMemorySkiaSharpChart() /// public int Height { - get => _chartView is null ? field : (int)_chartView.ControlSize.Height; + get => _drawnView is null ? field : (int)_drawnView.ControlSize.Height; set { field = value; WarnSize(); } } = 600; @@ -77,7 +77,7 @@ public int Height /// public int Width { - get => _chartView is null ? field : (int)_chartView.ControlSize.Width; + get => _drawnView is null ? field : (int)_drawnView.ControlSize.Width; set { field = value; WarnSize(); } } = 900; @@ -153,9 +153,9 @@ public virtual void DrawOnCanvas(SKCanvas canvas) var bg = coreChart.GetTheme().VirtualBackroundColor.AsSKColor(); - if (_chartView is not null) + if (_drawnView is not null) { - _chartView.CoreCanvas.DrawFrame( + _drawnView.CoreCanvas.DrawFrame( new SkiaSharpDrawingContext(CoreCanvas, canvas, bg)); return; } @@ -178,9 +178,9 @@ public virtual void DrawOnCanvas(SKCanvas canvas) private void WarnSize() { #if DEBUG - if (_chartView is null) return; + if (_drawnView is null) return; throw new InvalidOperationException( - $"The chart image dimensions are ignored when built from an {nameof(IChartView)} instance. " + + $"The chart image dimensions are ignored when built from an {nameof(IDrawnView)} instance. " + $"If you need the chart in a specific size, please use the parameterless contructor and build " + $"the chart from there, or resize the chart in UI first to the desired size."); #endif diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/LiveChartsGeneratedCode/SourceGenSKChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/LiveChartsGeneratedCode/SourceGenSKChart.cs index 4543fba12..735a8ca3e 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/LiveChartsGeneratedCode/SourceGenSKChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/LiveChartsGeneratedCode/SourceGenSKChart.cs @@ -45,7 +45,8 @@ public abstract partial class SourceGenSKChart : InMemorySkiaSharpChart /// Initializes a new instance of the class. /// /// The chart view to generate the image from. - public SourceGenSKChart(IChartView? chartView = null) : base(chartView) + public SourceGenSKChart(IChartView? chartView = null) + : base(chartView) { EasingFunction = null; AutoUpdateEnabled = false; @@ -60,7 +61,7 @@ public SourceGenSKChart(IChartView? chartView = null) : base(chartView) bool IChartView.DesignerMode => false; bool IChartView.IsDarkMode => false; LvcColor IChartView.BackColor => Background.AsLvcColor(); - LvcSize IChartView.ControlSize => new() { Width = Width, Height = Height }; + LvcSize IDrawnView.ControlSize => new() { Width = Width, Height = Height }; void IChartView.InvokeOnUIThread(Action action) => action(); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/LiveChartsGeneratedCode/SourceGenSKMapChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/LiveChartsGeneratedCode/SourceGenSKMapChart.cs new file mode 100644 index 000000000..b9b0990ef --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/LiveChartsGeneratedCode/SourceGenSKMapChart.cs @@ -0,0 +1,75 @@ +// 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; +using LiveChartsCore.Drawing; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.SKCharts; +using SkiaSharp; + +namespace LiveChartsGeneratedCode; + +// ============================================================================== +// +// this file contains the SkiaSharp (image generation) specific code for the SourceGenSKMapChart class, +// the rest of the code can be found in the _Shared project. +// +// ============================================================================== + +/// +public partial class SourceGenSKMapChart : InMemorySkiaSharpChart, IGeoMapView +{ + /// + /// Initializes a new instance of the class. + /// + public SourceGenSKMapChart(IGeoMapView? mapView = null) + : base(mapView) + { + AutoUpdateEnabled = false; + + InitializeChartControl(); + } + + /// + bool IGeoMapView.DesignerMode => false; + + /// + LvcSize IDrawnView.ControlSize => new() { Width = Width, Height = Height }; + + /// + public override void DrawOnCanvas(SKCanvas canvas) + { + CoreCanvas.DisableAnimations = true; + CoreChart.Measure(); + CoreCanvas.DrawFrame(new SkiaSharpDrawingContext(CoreCanvas, canvas, Background)); + CoreChart.Unload(); + } + + void IGeoMapView.InvokeOnUIThread(Action action) => + action(); + + /// + protected override Chart GetCoreChart() => throw new NotImplementedException(); +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKGeoMap.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKGeoMap.cs index 8fd82d20b..c35c0ec4c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKGeoMap.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKGeoMap.cs @@ -20,118 +20,32 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -using System; -using System.Collections.Generic; using LiveChartsCore.Geo; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Drawing; -using LiveChartsCore.SkiaSharpView.Painting; -using SkiaSharp; + +// ============================================================================== +// +// use the LiveChartsGeneratedCode.SourceGenSKMapChart class to add Skia (image generation) specific +// code, this class is just to expose the GeoMap class in this namespace. +// +// ============================================================================== namespace LiveChartsCore.SkiaSharpView.SKCharts; /// -public class SKGeoMap : InMemorySkiaSharpChart, IGeoMapView +public class SKGeoMap : LiveChartsGeneratedCode.SourceGenSKMapChart { - private readonly GeoMapChart _core; - /// /// Initializes a new instance of the class. /// public SKGeoMap() - { - _core = new GeoMapChart(this); - ActiveMap = Maps.GetWorldMap(); - } + : base(null) + { } /// /// Initializes a new instance of the class. /// - /// The map view. - public SKGeoMap(IGeoMapView mapView) : this() - { - MapProjection = mapView.MapProjection; - Stroke = mapView.Stroke; - Fill = mapView.Fill; - Series = mapView.Series; - } - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - public object SyncContext { get; set; } = new(); - - /// - public bool DesignerMode { get; set; } = false; - - /// - public DrawnMap ActiveMap { get; set; } - - float IGeoMapView.Width => Width; - - float IGeoMapView.Height => Height; - - /// - public CoreMotionCanvas Canvas { get; } = new(); - - /// - public MapProjection MapProjection { get; set; } - - /// - public Paint? Stroke - { - get; - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - field = value; - } - } = new SolidColorPaint(new SKColor(255, 255, 255, 255)) { PaintStyle = PaintStyle.Stroke }; - - /// - public Paint? Fill - { - get; - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - field = value; - } - } = new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }; - - /// - public IEnumerable Series { get; set; } = []; - - /// - public object? ViewCommand - { - get; - set - { - field = value; - if (value is not null) _core.ViewTo(value); - } - } - - /// - public override void DrawOnCanvas(SKCanvas canvas) - { - Canvas.DisableAnimations = true; - - _core.Measure(); - - Canvas.DrawFrame( - new SkiaSharpDrawingContext(Canvas, canvas, Background)); - - _core.Unload(); - } - - void IGeoMapView.InvokeOnUIThread(Action action) => - action(); - - /// - protected override Chart GetCoreChart() => - throw new NotImplementedException(); + /// The control to create the image from. + public SKGeoMap(IGeoMapView chartView) + : base(chartView) + { } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/GeoMap.razor b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/GeoMap.razor index 1c8e80247..191f55845 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/GeoMap.razor +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/GeoMap.razor @@ -22,4 +22,18 @@ SOFTWARE. *@ - +@inherits LiveChartsGeneratedCode.SourceGenMapChart + +@* +============================================================================== + +use the LiveChartsGeneratedCode.SourceGenMapChart class to add blazor specific +code, this class is just to expose the MapChart class in this namespace. + +============================================================================== +*@ + +@{ + base.BuildRenderTree(__builder); +} + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/GeoMap.razor.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/GeoMap.razor.cs deleted file mode 100644 index e6ffc25f3..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/GeoMap.razor.cs +++ /dev/null @@ -1,181 +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.Geo; -using LiveChartsCore.Kernel.Observers; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Painting; -using Microsoft.AspNetCore.Components; -using SkiaSharp; - -namespace LiveChartsCore.SkiaSharpView.Blazor; - -/// -public partial class GeoMap : IGeoMapView, IDisposable -{ -#pragma warning disable IDE0032 // Use auto property, blazor ref - private MotionCanvas _motionCanvas = null!; -#pragma warning restore IDE0032 // Use auto property - private CollectionDeepObserver? _seriesObserver; - private GeoMapChart? _core; - private DrawnMap? _activeMap; - - /// - /// Called when the control initializes. - /// - protected override void OnInitialized() - { - base.OnInitialized(); - - _activeMap = Maps.GetWorldMap(); - } - - /// - /// Called when the control renders. - /// - /// - /// - /// - protected override void OnAfterRender(bool firstRender) - { - if (!firstRender) return; - - _core = new GeoMapChart(this); - - _motionCanvas.SizeChanged += - () => - _core.Update(); - - _seriesObserver = new CollectionDeepObserver(() => _core?.Update()); - _core.Update(); - - if (_motionCanvas is null) throw new Exception("MotionCanvas not found"); - } - - /// - public CoreMotionCanvas Canvas => _motionCanvas?.CanvasCore ?? throw new Exception("MotionCanvas not found."); - - /// - [Parameter] - public bool AutoUpdateEnabled { get; set; } = true; - - /// - bool IGeoMapView.DesignerMode => false; - - /// - [Parameter] - public object SyncContext { get; set; } = new(); - - /// - [Parameter] - public object? ViewCommand - { - get; - set - { - field = value; - if (value is not null) _core?.ViewTo(value); - } - } = null; - - /// - [Parameter] - public DrawnMap ActiveMap - { - get => _activeMap ?? throw new Exception($"{nameof(ActiveMap)} is required."); - set - { - _activeMap = value; - OnPropertyChanged(); - } - } - - /// - float IGeoMapView.Width => _motionCanvas.Width; - - /// - float IGeoMapView.Height => _motionCanvas.Height; - - /// - [Parameter] - public MapProjection MapProjection { get; set { field = value; OnPropertyChanged(); } } = MapProjection.Default; - - /// - [Parameter] - public Paint? Stroke - { - get; - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - field = value; - OnPropertyChanged(); - } - } = new SolidColorPaint(new SKColor(255, 255, 255, 255)) { PaintStyle = PaintStyle.Stroke }; - - /// - [Parameter] - public Paint? Fill - { - get; - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - field = value; - OnPropertyChanged(); - } - } = new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }; - - /// - [Parameter] - public IEnumerable Series - { - get; - set - { - _seriesObserver?.Dispose(); - _seriesObserver?.Initialize(value); - field = value; - OnPropertyChanged(); - } - } = []; - - void IGeoMapView.InvokeOnUIThread(Action action) => - _ = InvokeAsync(action); - - /// - /// Called when a property changes. - /// - protected void OnPropertyChanged() => - _core?.Update(); - - void IDisposable.Dispose() - { - Series = []; - _seriesObserver = null!; - - Canvas.Dispose(); - - _core?.Unload(); - } -} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenChart.razor.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenChart.razor.cs index b3388f490..bfddd1a50 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenChart.razor.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenChart.razor.cs @@ -55,7 +55,7 @@ protected SourceGenChart() CoreChart = null!; } - /// + /// public CoreMotionCanvas CoreCanvas => _motionCanvas.CanvasCore; /// @@ -78,7 +78,7 @@ protected override void OnAfterRender(bool firstRender) bool IChartView.IsDarkMode => false; // Is this possible in Blazor? LvcColor IChartView.BackColor { get; } - LvcSize IChartView.ControlSize => new() + LvcSize IDrawnView.ControlSize => new() { Width = _motionCanvas.Width, Height = _motionCanvas.Height diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenMapChart.razor b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenMapChart.razor new file mode 100644 index 000000000..048195b9a --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenMapChart.razor @@ -0,0 +1,31 @@ +@* + 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.Blazor + +@namespace LiveChartsGeneratedCode + + + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenMapChart.razor.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenMapChart.razor.cs new file mode 100644 index 000000000..1e0160f1e --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveCharetsGeneratedCode/SourceGenMapChart.razor.cs @@ -0,0 +1,83 @@ +// 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; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Blazor; + +namespace LiveChartsGeneratedCode; + +// ============================================================================== +// +// this file contains the Blazor specific code for the SourceGenMapChart class, +// the rest of the code can be found in the _Shared project. +// +// ============================================================================== + +/// +public abstract partial class SourceGenMapChart : IDisposable, IGeoMapView +{ +#pragma warning disable IDE0032 // Use auto property, blazor ref + private MotionCanvas _motionCanvas = null!; +#pragma warning restore IDE0032 // Use auto property + + /// + /// Initializes a new instance of the class. + /// + protected SourceGenMapChart() + { + CoreChart = null!; + } + + /// + public CoreMotionCanvas CoreCanvas => _motionCanvas.CanvasCore; + + bool IGeoMapView.DesignerMode => false; + + LvcSize IDrawnView.ControlSize => new() + { + Width = _motionCanvas.Width, + Height = _motionCanvas.Height + }; + + /// + protected override void OnAfterRender(bool firstRender) + { + if (!firstRender) return; + + InitializeChartControl(); + + _motionCanvas.SizeChanged += + () => + CoreChart.Update(); + + CoreCanvas.Sync = SyncContext; + } + + void IGeoMapView.InvokeOnUIThread(Action action) => + _ = InvokeAsync(action); + + void IDisposable.Dispose() => + CoreChart.Unload(); +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/GeoMap.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/GeoMap.cs index c30b80447..a75ac0a0f 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/GeoMap.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/GeoMap.cs @@ -20,161 +20,17 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -using System; -using System.Collections.Generic; -using Eto.Forms; -using LiveChartsCore.Drawing; using LiveChartsCore.Geo; -using LiveChartsCore.Kernel.Observers; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Painting; -using SkiaSharp; -namespace LiveChartsCore.SkiaSharpView.Eto; - -/// -/// The geo map control. -/// -public class GeoMap : Panel, IGeoMapView -{ - private readonly MotionCanvas _motionCanvas = new(); - private readonly GeoMapChart _core; - private CollectionDeepObserver _seriesObserver; - private DrawnMap _activeMap; - - /// - /// Initializes a new instance of the class. - /// - public GeoMap() - { - _activeMap = Maps.GetWorldMap(); - - _core = new GeoMapChart(this); - _seriesObserver = new CollectionDeepObserver(() => _core?.Update()); - - var c = _motionCanvas; - - c.MouseDown += OnMouseDown; - c.MouseMove += OnMouseMove; - c.MouseUp += OnMouseUp; - c.MouseLeave += OnMouseLeave; - c.MouseWheel += OnMouseWheel; - - SizeChanged += GeoMap_Resize; - - BackgroundColor = global::Eto.Drawing.Colors.White; - - Content = _motionCanvas; - } - - /// - public CoreMotionCanvas Canvas => _motionCanvas.CanvasCore; - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - bool IGeoMapView.DesignerMode => false; - - /// - public object SyncContext { get; set; } = new(); - - /// - public object? ViewCommand - { - get; - set - { - field = value; - if (value is not null) _core.ViewTo(value); - } - } = null; - /// - public DrawnMap ActiveMap { get => _activeMap; set { _activeMap = value; OnPropertyChanged(); } } - - /// - float IGeoMapView.Width => ClientSize.Width; +// ============================================================================== +// +// use the LiveChartsGeneratedCode.SourceGenMapChart class to add eto specific +// code, this class is just to expose the GeoMap class in this namespace. +// +// ============================================================================== - /// - float IGeoMapView.Height => ClientSize.Height; - - /// - public MapProjection MapProjection { get; set { field = value; OnPropertyChanged(); } } = MapProjection.Default; - - /// - public Paint? Stroke - { - get; - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - field = value; - OnPropertyChanged(); - } - } = new SolidColorPaint(new SKColor(255, 255, 255, 255)) { PaintStyle = PaintStyle.Stroke }; - - /// - public Paint? Fill - { - get; - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - field = value; - OnPropertyChanged(); - } - } = new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }; - - /// - public IEnumerable Series - { - get; - set - { - _seriesObserver.Dispose(); - field = value; - OnPropertyChanged(); - } - } = []; - - void IGeoMapView.InvokeOnUIThread(Action action) => - Application.Instance.InvokeAsync(action).Wait(); - - /// - /// Called when a property changes. - /// - protected void OnPropertyChanged() => _core?.Update(); - - /// - protected override void OnUnLoad(EventArgs e) - { - base.OnUnLoad(e); - - _core?.Unload(); - - Series = []; - _seriesObserver = null!; - - Canvas.Dispose(); - } - - private void GeoMap_Resize(object? sender, EventArgs e) => _core?.Update(); - - private void OnMouseDown(object? sender, MouseEventArgs e) => _core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y)); - private void OnMouseMove(object? sender, MouseEventArgs e) => _core?.InvokePointerMove(new LvcPoint(e.Location.X, e.Location.Y)); - - private void OnMouseUp(object? sender, MouseEventArgs e) => _core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y)); - - private void OnMouseLeave(object? sender, EventArgs e) => _core?.InvokePointerLeft(); +namespace LiveChartsCore.SkiaSharpView.Eto; - private void OnMouseWheel(object? sender, MouseEventArgs e) - { - if (_core is null) throw new Exception("core not found"); - var p = e.Location; - _core.ViewTo( - new ZoomOnPointerView(new LvcPoint(p.X, p.Y), e.Delta.Height > 0 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut)); - e.Handled = true; - } -} +/// +public class GeoMap : LiveChartsGeneratedCode.SourceGenMapChart +{ } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsGeneratedCode/SourceGenChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsGeneratedCode/SourceGenChart.cs index 0e8a70b50..a0e6f1590 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsGeneratedCode/SourceGenChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsGeneratedCode/SourceGenChart.cs @@ -62,7 +62,7 @@ protected SourceGenChart() Content.MouseLeave += OnMouseLeave; } - /// + /// public CoreMotionCanvas CoreCanvas => ((MotionCanvas)Content).CanvasCore; bool IChartView.DesignerMode => false; @@ -72,7 +72,7 @@ protected SourceGenChart() LvcColor IChartView.BackColor => new((byte)BackgroundColor.Rb, (byte)BackgroundColor.Gb, (byte)BackgroundColor.Bb, (byte)BackgroundColor.Ab); - LvcSize IChartView.ControlSize => new() { Width = Content.Width, Height = Content.Height }; + LvcSize IDrawnView.ControlSize => new() { Width = Content.Width, Height = Content.Height }; void IChartView.InvokeOnUIThread(Action action) => _ = Application.Instance.InvokeAsync(action); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsGeneratedCode/SourceGenMapChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsGeneratedCode/SourceGenMapChart.cs new file mode 100644 index 000000000..e5bdce3c7 --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsGeneratedCode/SourceGenMapChart.cs @@ -0,0 +1,75 @@ +// 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 Eto.Drawing; +using Eto.Forms; +using LiveChartsCore.Drawing; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Eto; + +namespace LiveChartsGeneratedCode; + +// ============================================================================== +// +// this file contains the Eto specific code for the SourceGenMapChart class, +// the rest of the code can be found in the _Shared project. +// +// ============================================================================== + +/// +public abstract partial class SourceGenMapChart : Panel, IGeoMapView +{ + /// + /// Initializes a new instance of the class. + /// + protected SourceGenMapChart() + { + var motionCanvas = new MotionCanvas(); + + Content = motionCanvas; + BackgroundColor = Colors.White; + + InitializeChartControl(); + + Content.SizeChanged += (s, e) => + CoreChart.Update(); + } + + /// + public CoreMotionCanvas CoreCanvas => ((MotionCanvas)Content).CanvasCore; + + bool IGeoMapView.DesignerMode => false; + LvcSize IDrawnView.ControlSize => new() { Width = Content.Width, Height = Content.Height }; + + void IGeoMapView.InvokeOnUIThread(Action action) => + _ = Application.Instance.InvokeAsync(action); + + /// + protected override void OnUnLoad(EventArgs e) + { + base.OnUnLoad(e); + CoreChart.Unload(); + } +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartView.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartView.cs index 657bbd65e..82fb05c2d 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartView.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/ChartView.cs @@ -20,7 +20,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -using System; using Microsoft.Maui.Controls; namespace LiveChartsCore.SkiaSharpView.Maui; @@ -30,17 +29,6 @@ namespace LiveChartsCore.SkiaSharpView.Maui; /// public abstract partial class ChartView : ContentView { - static ChartView() - { - if (!LiveChartsCoreMauiAppBuilderExtensions.AreHandlersRegistered) - { - throw new InvalidOperationException( - "Since rc5 version, `.UseLiveCharts()` and `.UseSkiaSharp()` must be " + - "chained to `.UseMauiApp()`, in the MauiProgram.cs file. For more info see:" + - "https://livecharts.dev/docs/Maui/2.0.0-rc5/Overview.Installation"); - } - } - internal virtual void OnPressed(object? sender, Native.Events.PressedEventArgs args) { } internal virtual void OnMoved(object? sender, Native.Events.ScreenEventArgs args) { } internal virtual void OnReleased(object? sender, Native.Events.PressedEventArgs args) { } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/GeoMap.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/GeoMap.cs index d4de94268..9c995968a 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/GeoMap.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/GeoMap.cs @@ -20,241 +20,17 @@ // 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.Geo; -using LiveChartsCore.Kernel.Observers; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Painting; -using Microsoft.Maui; -using Microsoft.Maui.ApplicationModel; -using Microsoft.Maui.Controls; -using Microsoft.Maui.Controls.Xaml; -using SkiaSharp; -using Paint = LiveChartsCore.Painting.Paint; -namespace LiveChartsCore.SkiaSharpView.Maui; - -/// -[XamlCompilation(XamlCompilationOptions.Compile)] -public partial class GeoMap : ContentView, IGeoMapView -{ - private readonly CollectionDeepObserver _seriesObserver; - private readonly GeoMapChart _core; - - /// - /// Initializes a new instance of the class. - /// - public GeoMap() - { - Content = new MotionCanvas(false); - _core = new GeoMapChart(this); - - SizeChanged += GeoMap_SizeChanged; - - _seriesObserver = new CollectionDeepObserver(() => _core.Update()); - - SetValue(SeriesProperty, Enumerable.Empty()); - SetValue(ActiveMapProperty, Maps.GetWorldMap()); - SetValue(SyncContextProperty, new object()); - } - - #region dependency props - - /// - /// The active map property - /// - public static readonly BindableProperty ActiveMapProperty = - BindableProperty.Create( - nameof(ActiveMap), typeof(DrawnMap), typeof(GeoMap), null, BindingMode.Default, null, OnBindablePropertyChanged); - - /// - /// The sync context property - /// - public static readonly BindableProperty SyncContextProperty = - BindableProperty.Create( - nameof(SyncContext), typeof(object), typeof(GeoMap), null, BindingMode.Default, null, OnBindablePropertyChanged); - - /// - /// The view command property - /// - public static readonly BindableProperty ViewCommandProperty = - BindableProperty.Create( - nameof(ViewCommand), typeof(object), typeof(GeoMap), null, BindingMode.Default, null, - (BindableObject o, object oldValue, object newValue) => - { - var chart = (GeoMap)o; - chart._core.ViewTo(newValue); - }); - - /// - /// The map projection property - /// - public static readonly BindableProperty MapProjectionProperty = - BindableProperty.Create( - nameof(MapProjection), typeof(MapProjection), typeof(GeoMap), - MapProjection.Default, BindingMode.Default, null, OnBindablePropertyChanged); - - /// - /// The stroke property - /// - public static readonly BindableProperty StrokeProperty = - BindableProperty.Create( - nameof(Stroke), typeof(Paint), typeof(GeoMap), - new SolidColorPaint(new SKColor(255, 255, 255, 255)) { PaintStyle = PaintStyle.Stroke }, - BindingMode.Default, null, OnBindablePropertyChanged); - - /// - /// The fill property - /// - public static readonly BindableProperty FillProperty = - BindableProperty.Create( - nameof(Fill), typeof(Paint), typeof(GeoMap), - new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }, - BindingMode.Default, null, OnBindablePropertyChanged); - - /// - /// The series property - /// - public static readonly BindableProperty SeriesProperty = - BindableProperty.Create( - nameof(Series), typeof(IEnumerable), typeof(GeoMap), - Enumerable.Empty(), - BindingMode.Default, null, (BindableObject o, object oldValue, object newValue) => - { - var chart = (GeoMap)o; - var seriesObserver = chart._seriesObserver; - seriesObserver?.Dispose(); - seriesObserver?.Initialize((IEnumerable)newValue); - chart._core.Update(); - }); - - #endregion - - #region props - - /// - public bool AutoUpdateEnabled { get; set; } = true; - - /// - bool IGeoMapView.DesignerMode => false; - - /// - public object SyncContext - { - get => GetValue(SyncContextProperty); - set => SetValue(SyncContextProperty, value); - } +// ============================================================================== +// +// use the LiveChartsGeneratedCode.SourceGenMapChart class to add MAUI specific +// code, this class is just to expose the GeoMap class in this namespace. +// +// ============================================================================== - /// - public object? ViewCommand - { - get => GetValue(ViewCommandProperty); - set => SetValue(ViewCommandProperty, value); - } - - /// - public CoreMotionCanvas Canvas => ((MotionCanvas)Content).CanvasCore; - - /// - public DrawnMap ActiveMap - { - get => (DrawnMap)GetValue(ActiveMapProperty); - set => SetValue(ActiveMapProperty, value); - } - - /// - float IGeoMapView.Width => (float)Content.Width; - - /// - float IGeoMapView.Height => (float)Content.Height; - - /// - public MapProjection MapProjection - { - get => (MapProjection)GetValue(MapProjectionProperty); - set => SetValue(MapProjectionProperty, value); - } - - /// - public Paint? Stroke - { - get => (Paint)GetValue(StrokeProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - SetValue(StrokeProperty, value); - } - } - - /// - public Paint? Fill - { - get => (Paint)GetValue(FillProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - SetValue(FillProperty, value); - } - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty); - set => SetValue(SeriesProperty, value); - } - - #endregion - - /// - protected override void OnParentSet() - { - base.OnParentSet(); - - if (Parent == null) - { - _core.Unload(); - } - } - - void IGeoMapView.InvokeOnUIThread(Action action) => - _ = MainThread.InvokeOnMainThreadAsync(action); - - private void GeoMap_SizeChanged(object? sender, EventArgs e) => - _core?.Update(); - - private void PanGestureRecognizer_PanUpdated(object? sender, PanUpdatedEventArgs e) - { - if (_core is null) return; - if (e.StatusType != GestureStatus.Running) return; - - var delta = new LvcPoint((float)e.TotalX, (float)e.TotalY); - _core.Pan(delta); - } - - private void PinchGestureRecognizer_PinchUpdated(object? sender, PinchGestureUpdatedEventArgs e) - { - if (e.Status != GestureStatus.Running || Math.Abs(e.Scale - 1) < 0.05 || _core is null) return; - - var p = e.ScaleOrigin; - var w = ((IGeoMapView)this).Width; - var h = ((IGeoMapView)this).Width; - - _core.ViewTo( - new ZoomOnPointerView( - new LvcPoint((float)(p.X * w), (float)(p.Y * h)), - e.Scale > 1 ? ZoomDirection.ZoomIn : ZoomDirection.ZoomOut)); - } +namespace LiveChartsCore.SkiaSharpView.Maui; - private static void OnBindablePropertyChanged(BindableObject o, object oldValue, object newValue) - { - var chart = (GeoMap)o; - if (chart._core is null) return; - chart._core.Update(); - } -} +/// +public class GeoMap : LiveChartsGeneratedCode.SourceGenMapChart +{ } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsGeneratedCode/SourceGenChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsGeneratedCode/SourceGenChart.cs index d90f52f77..fa6b87690 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsGeneratedCode/SourceGenChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsGeneratedCode/SourceGenChart.cs @@ -64,7 +64,7 @@ protected SourceGenChart() private MotionCanvas CanvasView => (MotionCanvas)Content; - /// + /// public CoreMotionCanvas CoreCanvas => CanvasView.CanvasCore; bool IChartView.DesignerMode => false; @@ -79,7 +79,7 @@ LvcColor IChartView.BackColor : CoreCanvas._virtualBackgroundColor; } } - LvcSize IChartView.ControlSize => new() { Width = (float)Width, Height = (float)Height }; + LvcSize IDrawnView.ControlSize => new() { Width = (float)Width, Height = (float)Height }; private void OnLoaded(object? sender, EventArgs e) { diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsGeneratedCode/SourceGenMapChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsGeneratedCode/SourceGenMapChart.cs new file mode 100644 index 000000000..9353ecb5b --- /dev/null +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsGeneratedCode/SourceGenMapChart.cs @@ -0,0 +1,71 @@ +// 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; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Motion; +using LiveChartsCore.SkiaSharpView.Maui; +using Microsoft.Maui.ApplicationModel; + +namespace LiveChartsGeneratedCode; + +// ============================================================================== +// +// this file contains the MAUI specific code for the SourceGenMapChart class, +// the rest of the code can be found in the _Shared project. +// +// ============================================================================== + +/// +public abstract partial class SourceGenMapChart : ChartView, IGeoMapView +{ + /// + /// Initializes a new instance of the class. + /// + protected SourceGenMapChart() + { + Content = new MotionCanvas(false); + + SizeChanged += (s, e) => + CoreChart.Update(); + + InitializeChartControl(); + + Unloaded += OnUnloaded; + } + + private MotionCanvas CanvasView => (MotionCanvas)Content; + + /// + public CoreMotionCanvas CoreCanvas => CanvasView.CanvasCore; + + bool IGeoMapView.DesignerMode => false; + LvcSize IDrawnView.ControlSize => new() { Width = (float)Width, Height = (float)Height }; + + private void OnUnloaded(object? sender, EventArgs e) => + CoreChart?.Unload(); + + void IGeoMapView.InvokeOnUIThread(Action action) => + MainThread.BeginInvokeOnMainThread(action); +} diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/MotionCanvas.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/MotionCanvas.cs index c8b869729..ad2a9d275 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/MotionCanvas.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/MotionCanvas.cs @@ -38,6 +38,14 @@ public class MotionCanvas : AbsoluteLayout static MotionCanvas() { + if (!LiveChartsCoreMauiAppBuilderExtensions.AreHandlersRegistered) + { + throw new InvalidOperationException( + "`.UseLiveCharts()` and `.UseSkiaSharp()` must be " + + "chained to `.UseMauiApp()`, in the MauiProgram.cs file. For more info see: " + + "https://livecharts.dev/docs/Maui/latest/Overview.Installation"); + } + _ = LiveChartsSkiaSharp .EnsureInitialized() .HasRenderingFactory( diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.cs deleted file mode 100644 index e61bc2267..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/GeoMap.cs +++ /dev/null @@ -1,268 +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 LiveChartsCore.Drawing; -using LiveChartsCore.Geo; -using LiveChartsCore.Kernel.Observers; -using LiveChartsCore.Kernel.Sketches; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Painting; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using SkiaSharp; - -namespace LiveChartsCore.SkiaSharpView.WinUI; - -/// -public sealed partial class GeoMap : UserControl, IGeoMapView -{ - private readonly GeoMapChart _core; - private readonly CollectionDeepObserver _seriesObserver; - - /// - /// Initializes a new instance of the class. - /// - public GeoMap() - { - Content = new MotionCanvas(false); - - _core = new GeoMapChart(this); - - PointerPressed += OnPointerPressed; - PointerMoved += OnPointerMoved; - PointerReleased += OnPointerReleased; - PointerWheelChanged += OnWheelChanged; - PointerExited += OnPointerExited; - - SizeChanged += GeoMap_SizeChanged; - - _seriesObserver = new CollectionDeepObserver(() => _core?.Update()); - - 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(DrawnMap), 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 sync context 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(); - seriesObserver?.Initialize((IEnumerable)args.NewValue); - chart._core.Update(); - })); - - /// - /// The stroke property - /// - public static readonly DependencyProperty StrokeProperty = - DependencyProperty.Register( - nameof(Stroke), typeof(Paint), typeof(GeoMap), - new PropertyMetadata(new SolidColorPaint(new SKColor(255, 255, 255, 255)) { PaintStyle = PaintStyle.Stroke }, OnDependencyPropertyChanged)); - - /// - /// The fill property - /// - public static readonly DependencyProperty FillProperty = - DependencyProperty.Register( - nameof(Fill), typeof(Paint), typeof(GeoMap), - new PropertyMetadata(new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }, 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 CoreMotionCanvas Canvas => ((MotionCanvas)Content).CanvasCore; - - /// - public DrawnMap ActiveMap - { - get => (DrawnMap)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 Paint? Stroke - { - get => (Paint)GetValue(StrokeProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - SetValue(StrokeProperty, value); - } - } - - /// - public Paint? Fill - { - get => (Paint)GetValue(FillProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - SetValue(FillProperty, value); - } - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty); - set => SetValue(SeriesProperty, value); - } - - #endregion - - void IGeoMapView.InvokeOnUIThread(Action action) - { - _ = DispatcherQueue.TryEnqueue( - Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, - () => action()); - } - - 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.WinUI/GeoMap.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/GeoMap.cs deleted file mode 100644 index 92dba5457..000000000 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/GeoMap.cs +++ /dev/null @@ -1,267 +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 LiveChartsCore.Drawing; -using LiveChartsCore.Geo; -using LiveChartsCore.Kernel.Observers; -using LiveChartsCore.Kernel.Sketches; -using LiveChartsCore.Measure; -using LiveChartsCore.Motion; -using LiveChartsCore.Painting; -using LiveChartsCore.SkiaSharpView.Painting; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using SkiaSharp; - -namespace LiveChartsCore.SkiaSharpView.WinUI; - -/// -public sealed partial class GeoMap : UserControl, IGeoMapView -{ - private readonly GeoMapChart _core; - private readonly CollectionDeepObserver _seriesObserver; - - /// - /// Initializes a new instance of the class. - /// - public GeoMap() - { - Content = new MotionCanvas(false); - _core = new GeoMapChart(this); - - PointerPressed += OnPointerPressed; - PointerMoved += OnPointerMoved; - PointerReleased += OnPointerReleased; - PointerWheelChanged += OnWheelChanged; - PointerExited += OnPointerExited; - - SizeChanged += GeoMap_SizeChanged; - - _seriesObserver = new CollectionDeepObserver(() => _core?.Update()); - - 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(DrawnMap), 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 sync context 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(); - seriesObserver?.Initialize((IEnumerable)args.NewValue); - chart._core.Update(); - })); - - /// - /// The stroke property - /// - public static readonly DependencyProperty StrokeProperty = - DependencyProperty.Register( - nameof(Stroke), typeof(Paint), typeof(GeoMap), - new PropertyMetadata(new SolidColorPaint(new SKColor(255, 255, 255, 255)) { PaintStyle = PaintStyle.Stroke }, OnDependencyPropertyChanged)); - - /// - /// The fill property - /// - public static readonly DependencyProperty FillProperty = - DependencyProperty.Register( - nameof(Fill), typeof(Paint), typeof(GeoMap), - new PropertyMetadata(new SolidColorPaint(new SKColor(240, 240, 240, 255)) { PaintStyle = PaintStyle.Fill }, 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 CoreMotionCanvas Canvas => ((MotionCanvas)Content).CanvasCore; - - /// - public DrawnMap ActiveMap - { - get => (DrawnMap)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 Paint? Stroke - { - get => (Paint)GetValue(StrokeProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Stroke; - SetValue(StrokeProperty, value); - } - } - - /// - public Paint? Fill - { - get => (Paint)GetValue(FillProperty); - set - { - if (value is not null) value.PaintStyle = PaintStyle.Fill; - SetValue(FillProperty, value); - } - } - - /// - public IEnumerable Series - { - get => (IEnumerable)GetValue(SeriesProperty); - set => SetValue(SeriesProperty, value); - } - - #endregion - - void IGeoMapView.InvokeOnUIThread(Action action) - { - _ = DispatcherQueue.TryEnqueue( - Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, - () => action()); - } - - 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/_Shared.WinUI/GeoMap.cs b/src/skiasharp/_Shared.WinUI/GeoMap.cs new file mode 100644 index 000000000..efb6e3486 --- /dev/null +++ b/src/skiasharp/_Shared.WinUI/GeoMap.cs @@ -0,0 +1,36 @@ +// 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.Kernel.Sketches; + +namespace LiveChartsCore.SkiaSharpView.WinUI; + +// ============================================================================== +// +// use the LiveChartsGeneratedCode.SourceGenMapChart class to add winui/uno specific +// code, this class is just to expose the GeoMap class in this namespace. +// +// ============================================================================== + +/// +public sealed partial class GeoMap : LiveChartsGeneratedCode.SourceGenMapChart +{ } diff --git a/src/skiasharp/_Shared.WinUI/LiveChartsGeneratedCode/SourceGenChart.cs b/src/skiasharp/_Shared.WinUI/LiveChartsGeneratedCode/SourceGenChart.cs index 14f6c76e8..9f806f65a 100644 --- a/src/skiasharp/_Shared.WinUI/LiveChartsGeneratedCode/SourceGenChart.cs +++ b/src/skiasharp/_Shared.WinUI/LiveChartsGeneratedCode/SourceGenChart.cs @@ -80,7 +80,7 @@ public SourceGenChart() private MotionCanvas MotionCanvas => (MotionCanvas)Content; - /// + /// public CoreMotionCanvas CoreCanvas => MotionCanvas.CanvasCore; bool IChartView.DesignerMode => false; @@ -89,7 +89,7 @@ public SourceGenChart() Background is not SolidColorBrush b ? CoreCanvas._virtualBackgroundColor : LvcColor.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B); - LvcSize IChartView.ControlSize => new() { Width = (float)ActualWidth, Height = (float)ActualHeight }; + LvcSize IDrawnView.ControlSize => new() { Width = (float)ActualWidth, Height = (float)ActualHeight }; private void OnLoaded(object sender, RoutedEventArgs e) { diff --git a/src/skiasharp/_Shared.WinUI/LiveChartsGeneratedCode/SourceGenMapChart.cs b/src/skiasharp/_Shared.WinUI/LiveChartsGeneratedCode/SourceGenMapChart.cs new file mode 100644 index 000000000..e51c5e7b7 --- /dev/null +++ b/src/skiasharp/_Shared.WinUI/LiveChartsGeneratedCode/SourceGenMapChart.cs @@ -0,0 +1,84 @@ +// 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 LiveChartsCore.Drawing; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.SkiaSharpView.WinUI; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using LiveChartsCore.Motion; +using LiveChartsCore.Geo; + +namespace LiveChartsGeneratedCode; + +// ============================================================================== +// +// this file contains the WinUI/UNO specific code for the SourceGenMapChart class, +// the rest of the code can be found in the _Shared project. +// +// ============================================================================== + +/// +public abstract partial class SourceGenMapChart : UserControl, IGeoMapView +{ + private static readonly bool s_isWebAssembly = RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")); + + /// + /// Initializes a new instance of the class. + /// + public SourceGenMapChart() + { + Content = new MotionCanvas(false); + + InitializeChartControl(); + + SizeChanged += (s, e) => + CoreChart.Update(); + + Unloaded += OnUnloaded; + } + + private MotionCanvas MotionCanvas => (MotionCanvas)Content; + + /// + public CoreMotionCanvas CoreCanvas => MotionCanvas.CanvasCore; + + bool IGeoMapView.DesignerMode => false; + LvcSize IDrawnView.ControlSize => new() { Width = (float)ActualWidth, Height = (float)ActualHeight }; + + private void OnUnloaded(object sender, RoutedEventArgs e) => + CoreChart.Unload(); + + void IGeoMapView.InvokeOnUIThread(Action action) + { + if (s_isWebAssembly) + { + action(); + return; + } + + _ = DispatcherQueue.TryEnqueue( + Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () => action()); + } +} diff --git a/src/skiasharp/_Shared.WinUI/_Shared.WinUI.projitems b/src/skiasharp/_Shared.WinUI/_Shared.WinUI.projitems index e77c518f0..8e7910781 100644 --- a/src/skiasharp/_Shared.WinUI/_Shared.WinUI.projitems +++ b/src/skiasharp/_Shared.WinUI/_Shared.WinUI.projitems @@ -9,8 +9,10 @@ _Shared.WinUI + + diff --git a/src/skiasharp/_Shared/SourceGenMapChart.cs b/src/skiasharp/_Shared/SourceGenMapChart.cs new file mode 100644 index 000000000..ec0454c4f --- /dev/null +++ b/src/skiasharp/_Shared/SourceGenMapChart.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; +using LiveChartsCore.Geo; +using LiveChartsCore.Kernel.Observers; + +namespace LiveChartsGeneratedCode; + +/// +#if SKIA_IMAGE_LVC +public partial class SourceGenSKMapChart : IGeoMapView +#else +public partial class SourceGenMapChart : IGeoMapView +#endif +{ + private CollectionDeepObserver _seriesObserver = null!; + + /// + /// Gets the core chart. + /// + public GeoMapChart CoreChart { get; private set; } = null!; + + /// + public bool AutoUpdateEnabled { get; set; } = true; + + private void InitializeChartControl() + { + CoreChart = new GeoMapChart(this); + _seriesObserver = new CollectionDeepObserver(() => CoreChart?.Update()); + + ActiveMap = Maps.GetWorldMap(); + SyncContext = new object(); + } +} diff --git a/src/skiasharp/_Shared/SourceGenMapChart.sgp.cs b/src/skiasharp/_Shared/SourceGenMapChart.sgp.cs new file mode 100644 index 000000000..3550d73d9 --- /dev/null +++ b/src/skiasharp/_Shared/SourceGenMapChart.sgp.cs @@ -0,0 +1,135 @@ +// 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. + +#pragma warning disable IDE0005 // Using directive is unnecessary. +#pragma warning disable IDE0060 // Remove unused parameter + +using LiveChartsCore; +using LiveChartsCore.Geo; +using LiveChartsCore.Generators; +using System.Windows.Input; +using System; +using LiveChartsCore.Painting; +using System.Collections.Generic; +using SkiaSharp; +using LiveChartsCore.Drawing; + +#if SKIA_IMAGE_LVC +using SGChart = LiveChartsGeneratedCode.SourceGenSKMapChart; +#else +using SGChart = LiveChartsGeneratedCode.SourceGenMapChart; +#endif + +// ============================================================================================================== +// the static fileds in this file generate bindable/dependency/avalonia or whatever properties... +// the disabled warning make it easier to maintain the code. +// +#pragma warning disable IDE1006 // Naming Styles +#pragma warning disable IDE0052 // Remove unread private member +#pragma warning disable IDE0051 // Remove unused private members +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. +#pragma warning disable CS0169 // The field is never used +#pragma warning disable IDE0044 // Add readonly modifier +#pragma warning disable IDE0040 // Add accessibility modifiers +#pragma warning disable format +// ============================================================================================================== + +namespace LiveChartsGeneratedCode; + +#if SKIA_IMAGE_LVC +public partial class SourceGenSKMapChart +#else +public partial class SourceGenMapChart +#endif +{ + /// + static UIProperty syncContext = new(onChanged: OnSyncContextChanged); + + /// + static UIProperty activeMap; + + /// + static UIProperty mapProjection = new(defaultValue: MapProjection.Default); + + /// + static UIProperty stroke = new(defaultValue: GetPaint(new(255, 255, 255, 255), PaintStyle.Stroke), onChanged: OnPaintPropertyChanged(nameof(Stroke))); + + /// + static UIProperty fill = new(defaultValue: GetPaint(new(240, 240, 240, 255), PaintStyle.Fill), onChanged: OnPaintPropertyChanged(nameof(Fill))); + + /// + static UIProperty> series = new(onChanged: OnSeriesPropertyChanged); + + static void OnSyncContextChanged(SGChart chart, object oldValue, object newValue) + { +#if BLAZOR_LVC + // hack for blazor, we need to wait for the OnAfterRender to have + // a reference to the canvas in the UI, CoreChart is null until then. + if (chart.CoreChart is null) return; +#endif + chart.CoreCanvas.Sync = newValue; + chart.CoreChart.Update(); + } + + static void OnSeriesPropertyChanged(SGChart chart, object oldValue, object newValue) + { +#if BLAZOR_LVC + // hack for blazor, we need to wait for the OnAfterRender to have + // a reference to the canvas in the UI, CoreChart is null until then. + if (chart.CoreChart is null) return; +#endif + chart._seriesObserver?.Dispose(); + chart._seriesObserver?.Initialize((IEnumerable)newValue); + } + + static Action OnPaintPropertyChanged( + string propertyName, object? oldValue = null, object? newValue = null) => + (chart, o, n) => + { + if (n is not Paint newPaint) return; + + newPaint.PaintStyle = propertyName == nameof(Fill) + ? PaintStyle.Fill + : PaintStyle.Stroke; + }; + + static Paint GetPaint(LvcColor color, PaintStyle style) + { + var paint = LiveCharts.DefaultSettings.GetProvider().GetSolidColorPaint(color); + paint.PaintStyle = style; + return paint; + } + +#if AVALONIA_LVC + // avalonia hack to mock the DependencyProperty.OnPropertyChanged delegate. + + /// + protected override void OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property.Name == nameof(IsPointerOver)) return; + + OnXamlPropertyChanged(change); + } +#endif +} diff --git a/src/skiasharp/_Shared/_Shared.projitems b/src/skiasharp/_Shared/_Shared.projitems index 38162f2fc..cb8ecdb34 100644 --- a/src/skiasharp/_Shared/_Shared.projitems +++ b/src/skiasharp/_Shared/_Shared.projitems @@ -10,6 +10,8 @@ + +