diff --git a/samples/ViewModelsSamples/VisualTest/TwoChartsOneSeries/ViewModel.cs b/samples/ViewModelsSamples/VisualTest/TwoChartsOneSeries/ViewModel.cs index dde2342e0..8ccf833e2 100644 --- a/samples/ViewModelsSamples/VisualTest/TwoChartsOneSeries/ViewModel.cs +++ b/samples/ViewModelsSamples/VisualTest/TwoChartsOneSeries/ViewModel.cs @@ -1,6 +1,7 @@ using System; using CommunityToolkit.Mvvm.ComponentModel; using LiveChartsCore; +using LiveChartsCore.Defaults; using LiveChartsCore.SkiaSharpView; namespace ViewModelsSamples.VisualTest.TwoChartsOneSeries; @@ -10,17 +11,29 @@ public partial class ViewModel { public ViewModel() { - var values = new int[100]; + //var values = new int[100]; + //var r = new Random(); + //var t = 0; + + //for (var i = 0; i < 100; i++) + //{ + // t += r.Next(-90, 100); + // values[i] = t; + //} + + //Series = new ISeries[] { new StepLineSeries { Values = values } }; + + var values = new ObservableValue[100]; var r = new Random(); var t = 0; for (var i = 0; i < 100; i++) { t += r.Next(-90, 100); - values[i] = t; + values[i] = new(t); } - Series = new ISeries[] { new StepLineSeries { Values = values } }; + Series = new ISeries[] { new StepLineSeries { Values = values } }; } public ISeries[] Series { get; set; } diff --git a/src/LiveChartsCore/CartesianChart.cs b/src/LiveChartsCore/CartesianChart.cs index ade1d99ea..66bb943d6 100644 --- a/src/LiveChartsCore/CartesianChart.cs +++ b/src/LiveChartsCore/CartesianChart.cs @@ -44,6 +44,7 @@ public class CartesianChart : Chart internal readonly HashSet> _everMeasuredAxes = new(); internal readonly HashSet> _everMeasuredSections = new(); private readonly ICartesianChartView _chartView; + private readonly ISizedGeometry _zoomingSection; private int _nextSeries = 0; private double _zoomingSpeed = 0; private readonly bool _requiresLegendMeasureAlways = false; @@ -58,16 +59,23 @@ public class CartesianChart : Chart /// The view. /// The default platform configuration. /// The canvas. + /// The zooming section. /// Forces the legends to redraw with every measure request. public CartesianChart( ICartesianChartView view, Action defaultPlatformConfig, MotionCanvas canvas, + ISizedGeometry? zoomingSection, bool requiresLegendMeasureAlways = false) : base(canvas, defaultPlatformConfig, view) { _chartView = view; _requiresLegendMeasureAlways = requiresLegendMeasureAlways; + _zoomingSection = zoomingSection ?? throw new Exception($"{nameof(zoomingSection)} is required."); + _zoomingSection.X = -1; + _zoomingSection.Y = -1; + _zoomingSection.Width = 0; + _zoomingSection.Height = 0; } /// @@ -227,7 +235,7 @@ public void Zoom(LvcPoint pivot, ZoomDirection direction, double? scaleFactor = maxt = max + ld * 0.5 * dir; } - if (maxt - mint < xi.DataBounds.MinDelta * 5) return; + if (direction == ZoomDirection.ZoomIn && maxt - mint < xi.DataBounds.MinDelta * 3) return; var xm = (max - min) * (isActive ? MaxAxisActiveBound : MaxAxisBound); if (maxt > xi.DataBounds.Max && direction == ZoomDirection.ZoomOut) maxt = xi.DataBounds.Max + xm; @@ -281,7 +289,7 @@ public void Zoom(LvcPoint pivot, ZoomDirection direction, double? scaleFactor = maxt = max + ld * 0.5 * dir; } - if (maxt - mint < yi.DataBounds.MinDelta * 5) return; + if (direction == ZoomDirection.ZoomIn && maxt - mint < yi.DataBounds.MinDelta * 3) return; var ym = (max - min) * (isActive ? MaxAxisActiveBound : MaxAxisBound); if (maxt > yi.DataBounds.Max && direction == ZoomDirection.ZoomOut) maxt = yi.DataBounds.Max + ym; @@ -688,9 +696,9 @@ protected internal override void Measure() } var drawablePlane = (IPlane)axis; - _ = _everMeasuredAxes.Add(drawablePlane); if (drawablePlane.IsVisible) { + _everMeasuredAxes.Add(drawablePlane); drawablePlane.Measure(this); _ = toDeleteAxes.Remove(drawablePlane); } @@ -782,4 +790,137 @@ public override void Unload() IsFirstDraw = true; } + + private LvcPoint? _sectionZoomingStart = null; + + internal override void InvokePointerDown(LvcPoint point, bool isSecondaryAction) + { + if (isSecondaryAction) + { + _sectionZoomingStart = point; + + _zoomingSection.X = point.X; + _zoomingSection.Y = point.Y; + + var xMode = (_zoomMode & ZoomAndPanMode.X) == ZoomAndPanMode.X; + var yMode = (_zoomMode & ZoomAndPanMode.Y) == ZoomAndPanMode.Y; + + if (!xMode) + { + _zoomingSection.X = DrawMarginLocation.X; + _zoomingSection.Width = DrawMarginSize.Width; + } + + if (!yMode) + { + _zoomingSection.Y = DrawMarginLocation.Y; + _zoomingSection.Height = DrawMarginSize.Height; + } + + Update(); + return; + } + + base.InvokePointerDown(point, isSecondaryAction); + } + + internal override void InvokePointerMove(LvcPoint point) + { + if (_sectionZoomingStart is not null) + { + var xMode = (_zoomMode & ZoomAndPanMode.X) == ZoomAndPanMode.X; + var yMode = (_zoomMode & ZoomAndPanMode.Y) == ZoomAndPanMode.Y; + + if (xMode) _zoomingSection.Width = point.X - _sectionZoomingStart.Value.X; + if (yMode) _zoomingSection.Height = point.Y - _sectionZoomingStart.Value.Y; + + Update(); + return; + } + + base.InvokePointerMove(point); + } + + internal override void InvokePointerUp(LvcPoint point, bool isSecondaryAction) + { + if (_sectionZoomingStart is not null) + { + if ((_zoomMode & ZoomAndPanMode.X) == ZoomAndPanMode.X) + { + for (var i = 0; i < XAxes.Length; i++) + { + var x = XAxes[i]; + + var xi = ScaleUIPoint(_sectionZoomingStart.Value, i, 0)[0]; + var xj = ScaleUIPoint(point, i, 0)[0]; + + double xMax, xMin; + + if (xi > xj) + { + xMax = xi; + xMin = xj; + } + else + { + xMax = xj; + xMin = xi; + } + + if (xMax > (x.MaxLimit ?? double.MaxValue)) xMax = x.MaxLimit ?? double.MaxValue; + if (xMin < (x.MinLimit ?? double.MinValue)) xMin = x.MinLimit ?? double.MinValue; + + if (xMax - xMin > x.DataBounds.MinDelta * 3) + { + x.MinLimit = xMin; + x.MaxLimit = xMax; + } + } + } + + if ((_zoomMode & ZoomAndPanMode.Y) == ZoomAndPanMode.Y) + { + for (var i = 0; i < YAxes.Length; i++) + { + var y = YAxes[i]; + + var yi = ScaleUIPoint(_sectionZoomingStart.Value, 0, i)[1]; + var yj = ScaleUIPoint(point, 0, i)[1]; + + double yMax, yMin; + + if (yi > yj) + { + yMax = yi; + yMin = yj; + } + else + { + yMax = yj; + yMin = yi; + } + + if (yMax > (y.MaxLimit ?? double.MaxValue)) yMax = y.MaxLimit ?? double.MaxValue; + if (yMin < (y.MinLimit ?? double.MinValue)) yMin = y.MinLimit ?? double.MinValue; + + if (yMax - yMin > y.DataBounds.MinDelta * 3) + { + y.MinLimit = yMin; + y.MaxLimit = yMax; + } + } + } + + _zoomingSection.X = -1; + _zoomingSection.Y = -1; + _zoomingSection.Width = 0; + _zoomingSection.Height = 0; + Update(); + + _sectionZoomingStart = null; + return; + } + + base.InvokePointerUp(point, isSecondaryAction); + } } diff --git a/src/LiveChartsCore/Chart.cs b/src/LiveChartsCore/Chart.cs index 10535b300..a6059b9f6 100644 --- a/src/LiveChartsCore/Chart.cs +++ b/src/LiveChartsCore/Chart.cs @@ -343,8 +343,7 @@ internal void ClearTooltipData() Canvas.Invalidate(); } - - internal void InvokePointerDown(LvcPoint point) + internal virtual void InvokePointerDown(LvcPoint point, bool isSecondaryAction) { PointerDown?.Invoke(point); @@ -366,12 +365,12 @@ internal void InvokePointerDown(LvcPoint point) View.OnDataPointerDown(iterable, point); } - internal void InvokePointerMove(LvcPoint point) + internal virtual void InvokePointerMove(LvcPoint point) { PointerMove?.Invoke(point); } - internal void InvokePointerUp(LvcPoint point) + internal virtual void InvokePointerUp(LvcPoint point, bool isSecondaryAction) { PointerUp?.Invoke(point); } diff --git a/src/LiveChartsCore/ColumnSeries.cs b/src/LiveChartsCore/ColumnSeries.cs index bdf795fc2..39cf035f2 100644 --- a/src/LiveChartsCore/ColumnSeries.cs +++ b/src/LiveChartsCore/ColumnSeries.cs @@ -115,7 +115,7 @@ public override void Measure(Chart chart) var secondary = secondaryScale.ToPixels(point.SecondaryValue); var b = Math.Abs(primary - helper.p); - if (point.IsNull) + if (point.IsEmpty) { if (visual is not null) { diff --git a/src/LiveChartsCore/Defaults/DateTimePoint.cs b/src/LiveChartsCore/Defaults/DateTimePoint.cs index 971e31a3c..e81b8b22f 100644 --- a/src/LiveChartsCore/Defaults/DateTimePoint.cs +++ b/src/LiveChartsCore/Defaults/DateTimePoint.cs @@ -21,9 +21,11 @@ // SOFTWARE. using System; +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.Defaults; @@ -48,8 +50,9 @@ public DateTimePoint() /// The value. public DateTimePoint(DateTime dateTime, double? value) { - _dateTime = dateTime; - _value = value; + DateTime = dateTime; + Value = value; + Coordinate = value is null ? Coordinate.Empty : new(dateTime.Ticks, value.Value); } /// @@ -68,14 +71,14 @@ public DateTimePoint(DateTime dateTime, double? value) /// public double? Value { get => _value; set { _value = value; OnPropertyChanged(); } } - /// - public ChartPoint? ChartPoint { get; set; } + /// + public int EntityIndex { get; set; } - /// - public int EntityId { get; set; } + /// + public Dictionary? ChartPoints { get; set; } - /// - public Coordinate Coordinate => new(_dateTime.Ticks, _value ?? 0d); + /// + public Coordinate Coordinate { get; private set; } = Coordinate.Empty; /// /// Occurs when a property value changes. @@ -89,6 +92,7 @@ public DateTimePoint(DateTime dateTime, double? value) /// Name of the property. protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { + Coordinate = _value is null ? Coordinate.Empty : new(_dateTime.Ticks, _value.Value); PropertyChanged?.Invoke(propertyName, new PropertyChangedEventArgs(propertyName)); } } diff --git a/src/LiveChartsCore/Defaults/FinancialPoint.cs b/src/LiveChartsCore/Defaults/FinancialPoint.cs index b1fd6219d..7deba81cd 100644 --- a/src/LiveChartsCore/Defaults/FinancialPoint.cs +++ b/src/LiveChartsCore/Defaults/FinancialPoint.cs @@ -21,9 +21,11 @@ // SOFTWARE. using System; +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.Defaults; @@ -32,10 +34,10 @@ namespace LiveChartsCore.Defaults; /// public class FinancialPoint : IChartEntity, INotifyPropertyChanged { - private double _high; - private double _open; - private double _close; - private double _low; + private double? _high; + private double? _open; + private double? _close; + private double? _low; private DateTime _date; /// @@ -52,13 +54,13 @@ public FinancialPoint() /// The open. /// The close. /// The low. - public FinancialPoint(DateTime date, double high, double open, double close, double low) + public FinancialPoint(DateTime date, double? high, double? open, double? close, double? low) { - _date = date; - _high = high; - _open = open; - _close = close; - _low = low; + Date = date; + High = high; + Open = open; + Close = close; + Low = low; } /// @@ -75,7 +77,7 @@ public FinancialPoint(DateTime date, double high, double open, double close, dou /// /// The high. /// - public double High { get => _high; set { _high = value; OnPropertyChanged(); } } + public double? High { get => _high; set { _high = value; OnPropertyChanged(); } } /// /// Gets or sets the open. @@ -83,7 +85,7 @@ public FinancialPoint(DateTime date, double high, double open, double close, dou /// /// The open. /// - public double Open { get => _open; set { _open = value; OnPropertyChanged(); } } + public double? Open { get => _open; set { _open = value; OnPropertyChanged(); } } /// /// Gets or sets the close. @@ -91,7 +93,7 @@ public FinancialPoint(DateTime date, double high, double open, double close, dou /// /// The close. /// - public double Close { get => _close; set { _close = value; OnPropertyChanged(); } } + public double? Close { get => _close; set { _close = value; OnPropertyChanged(); } } /// /// Gets or sets the low. @@ -99,16 +101,16 @@ public FinancialPoint(DateTime date, double high, double open, double close, dou /// /// The low. /// - public double Low { get => _low; set { _low = value; OnPropertyChanged(); } } + public double? Low { get => _low; set { _low = value; OnPropertyChanged(); } } - /// - public ChartPoint? ChartPoint { get; set; } + /// + public int EntityIndex { get; set; } - /// - public int EntityId { get; set; } + /// + public Dictionary? ChartPoints { get; set; } - /// - public Coordinate Coordinate => new(_high, _date.Ticks, _open, _close, _low); + /// + public Coordinate Coordinate { get; private set; } = Coordinate.Empty; /// /// Occurs when a property value changes. @@ -122,6 +124,9 @@ public FinancialPoint(DateTime date, double high, double open, double close, dou /// Name of the property. protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { + Coordinate = _open is null || _high is null || _low is null || _close is null + ? Coordinate.Empty + : new(_high.Value, _date.Ticks, _open.Value, _close.Value, _low.Value); PropertyChanged?.Invoke(propertyName, new PropertyChangedEventArgs(propertyName)); } } diff --git a/src/LiveChartsCore/Kernel/Providers/EntitiesDataFactory.cs b/src/LiveChartsCore/Defaults/MappedChartEntity.cs similarity index 54% rename from src/LiveChartsCore/Kernel/Providers/EntitiesDataFactory.cs rename to src/LiveChartsCore/Defaults/MappedChartEntity.cs index 5ed731fd4..ecfeb7c0b 100644 --- a/src/LiveChartsCore/Kernel/Providers/EntitiesDataFactory.cs +++ b/src/LiveChartsCore/Defaults/MappedChartEntity.cs @@ -21,36 +21,30 @@ // SOFTWARE. using System.Collections.Generic; -using LiveChartsCore.Drawing; +using LiveChartsCore.Kernel; using LiveChartsCore.Kernel.Sketches; -namespace LiveChartsCore.Kernel.Providers; +namespace LiveChartsCore.Defaults; /// -/// Just a cleaner but optimized for objects. +/// Defines the class, a helper class to map any object that does not implements , +/// when you need a better performance you should implement in your DTOs, the default objects in the library +/// already implement . /// -public class EntitiesDataFactory : DataFactory - where TDrawingContext : DrawingContext +public sealed class MappedChartEntity : IChartEntity { - /// - public override IEnumerable Fetch(ISeries series, IChart chart) - { - if (series.Values is null) yield break; - var index = 0; - - foreach (var value in series.Values) - { - if (value is not IChartEntity entity) continue; + /// + public int EntityIndex { get; set; } - entity.ChartPoint ??= new ChartPoint(chart.View, series); - entity.ChartPoint.Context.DataSource = entity; - entity.ChartPoint.Context.Index = index; - entity.EntityId = index; - entity.ChartPoint.Coordinate = entity.Coordinate; + /// + public Dictionary? ChartPoints { get; set; } - yield return entity.ChartPoint; + /// + public Coordinate Coordinate { get; private set; } = Coordinate.Empty; - index++; - } + internal void UpdateCoordinate(ChartPoint chartPoint) + { + Coordinate = new Coordinate( + chartPoint.PrimaryValue, chartPoint.SecondaryValue, chartPoint.TertiaryValue, chartPoint.QuaternaryValue, chartPoint.QuinaryValue); } } diff --git a/src/LiveChartsCore/Defaults/ObservablePoint.cs b/src/LiveChartsCore/Defaults/ObservablePoint.cs index 2f0eb7fd6..03ec2a013 100644 --- a/src/LiveChartsCore/Defaults/ObservablePoint.cs +++ b/src/LiveChartsCore/Defaults/ObservablePoint.cs @@ -20,9 +20,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.Defaults; @@ -48,8 +50,8 @@ public ObservablePoint() /// The y coordinate. public ObservablePoint(double? x, double? y) { - _x = x; - _y = y; + X = x; + Y = y; } /// @@ -68,14 +70,14 @@ public ObservablePoint(double? x, double? y) /// public double? Y { get => _y; set { _y = value; OnPropertyChanged(); } } - /// - public ChartPoint? ChartPoint { get; set; } + /// + public int EntityIndex { get; set; } - /// - public int EntityId { get; set; } + /// + public Dictionary? ChartPoints { get; set; } - /// - public Coordinate Coordinate => new(_x ?? 0d, _y ?? 0d); + /// + public Coordinate Coordinate { get; private set; } = Coordinate.Empty; /// /// Occurs when a property value changes. @@ -84,11 +86,14 @@ public ObservablePoint(double? x, double? y) public event PropertyChangedEventHandler? PropertyChanged; /// - /// Called when a property changed. + /// Called when a property changes. /// /// Name of the property. protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { + Coordinate = _x is null || _y is null + ? Coordinate.Empty + : new Coordinate(_x.Value, _y.Value); PropertyChanged?.Invoke(propertyName, new PropertyChangedEventArgs(propertyName)); } } diff --git a/src/LiveChartsCore/Defaults/ObservablePolarPoint.cs b/src/LiveChartsCore/Defaults/ObservablePolarPoint.cs index 7003f928b..4e239d51a 100644 --- a/src/LiveChartsCore/Defaults/ObservablePolarPoint.cs +++ b/src/LiveChartsCore/Defaults/ObservablePolarPoint.cs @@ -20,9 +20,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.Defaults; @@ -47,8 +49,8 @@ public ObservablePolarPoint() /// The radius. public ObservablePolarPoint(double? angle, double? radius) { - _angle = angle; - _radius = radius; + Angle = angle; + Radius = radius; } /// @@ -61,14 +63,14 @@ public ObservablePolarPoint(double? angle, double? radius) /// public double? Radius { get => _radius; set { _radius = value; OnPropertyChanged(); } } - /// - public ChartPoint? ChartPoint { get; set; } + /// + public int EntityIndex { get; set; } - /// - public int EntityId { get; set; } + /// + public Dictionary? ChartPoints { get; set; } - /// - public Coordinate Coordinate => new(_radius ?? 0d, _angle ?? 0d, 0d, 0d, 0d); + /// + public Coordinate Coordinate { get; private set; } = Coordinate.Empty; /// /// Called when a property changes. @@ -80,6 +82,9 @@ public ObservablePolarPoint(double? angle, double? radius) /// protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { + Coordinate = _radius is null || _angle is null + ? Coordinate.Empty + : new(_angle.Value, _radius.Value); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } diff --git a/src/LiveChartsCore/Defaults/ObservableValue.cs b/src/LiveChartsCore/Defaults/ObservableValue.cs index b3ea86fbd..48e5de37a 100644 --- a/src/LiveChartsCore/Defaults/ObservableValue.cs +++ b/src/LiveChartsCore/Defaults/ObservableValue.cs @@ -20,9 +20,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.Defaults; @@ -33,6 +35,7 @@ namespace LiveChartsCore.Defaults; public class ObservableValue : IChartEntity, INotifyPropertyChanged { private double? _value; + private int _entityIndex; /// /// Initializes a new instance of the class. @@ -46,7 +49,7 @@ public ObservableValue() /// The value. public ObservableValue(double? value) { - _value = value; + Value = value; } /// @@ -57,14 +60,25 @@ public ObservableValue(double? value) /// public double? Value { get => _value; set { _value = value; OnPropertyChanged(); } } - /// - public ChartPoint? ChartPoint { get; set; } + /// + public int EntityIndex + { + get => _entityIndex; + set + { + // the coordinate of this type depends on the index of element in the data collection. + // we update the coordinate if the index changed. + if (value == _entityIndex) return; + _entityIndex = value; + OnCoordinateChanged(); + } + } - /// - public int EntityId { get; set; } + /// + public Dictionary? ChartPoints { get; set; } - /// - public Coordinate Coordinate => new(EntityId, _value ?? 0d); + /// + public Coordinate Coordinate { get; private set; } = Coordinate.Empty; /// /// Occurs when a property value changes. @@ -78,6 +92,17 @@ public ObservableValue(double? value) /// Name of the property. protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { + OnCoordinateChanged(); PropertyChanged?.Invoke(propertyName, new PropertyChangedEventArgs(propertyName)); } + + /// + /// Called when the coordinate changed. + /// + protected virtual void OnCoordinateChanged() + { + Coordinate = _value is null + ? Coordinate.Empty + : new(EntityIndex, _value.Value); + } } diff --git a/src/LiveChartsCore/Defaults/TimeSpanPoint.cs b/src/LiveChartsCore/Defaults/TimeSpanPoint.cs index 2b483ce8c..4dc69f222 100644 --- a/src/LiveChartsCore/Defaults/TimeSpanPoint.cs +++ b/src/LiveChartsCore/Defaults/TimeSpanPoint.cs @@ -21,9 +21,11 @@ // SOFTWARE. using System; +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.Defaults; @@ -48,8 +50,8 @@ public TimeSpanPoint() /// The value. public TimeSpanPoint(TimeSpan timeSpan, double? value) { - _timeSpan = timeSpan; - _value = value; + TimeSpan = timeSpan; + Value = value; } /// @@ -68,14 +70,14 @@ public TimeSpanPoint(TimeSpan timeSpan, double? value) /// public double? Value { get => _value; set { _value = value; OnPropertyChanged(); } } - /// - public ChartPoint? ChartPoint { get; set; } + /// + public int EntityIndex { get; set; } - /// - public int EntityId { get; set; } + /// + public Dictionary? ChartPoints { get; set; } - /// - public Coordinate Coordinate => new(_timeSpan.Ticks, _value ?? 0d); + /// + public Coordinate Coordinate { get; private set; } = Coordinate.Empty; /// /// Occurs when a property value changes. @@ -89,6 +91,9 @@ public TimeSpanPoint(TimeSpan timeSpan, double? value) /// Name of the property. protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { + Coordinate = _value is null + ? Coordinate.Empty + : new(_timeSpan.Ticks, _value ?? 0d); PropertyChanged?.Invoke(propertyName, new PropertyChangedEventArgs(propertyName)); } } diff --git a/src/LiveChartsCore/Defaults/WeightedPoint.cs b/src/LiveChartsCore/Defaults/WeightedPoint.cs index f570e54c8..9f614b1b0 100644 --- a/src/LiveChartsCore/Defaults/WeightedPoint.cs +++ b/src/LiveChartsCore/Defaults/WeightedPoint.cs @@ -20,9 +20,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using LiveChartsCore.Kernel; +using LiveChartsCore.Kernel.Sketches; namespace LiveChartsCore.Defaults; @@ -50,9 +52,9 @@ public WeightedPoint() /// The weight. public WeightedPoint(double? x, double? y, double? weight) { - _x = x; - _y = y; - _weight = weight; + X = x; + Y = y; + Weight = weight; } /// @@ -79,27 +81,30 @@ public WeightedPoint(double? x, double? y, double? weight) /// public double? Weight { get => _weight; set { _weight = value; OnPropertyChanged(); } } - /// - public ChartPoint? ChartPoint { get; set; } - - /// - public int EntityId { get; set; } - - /// - public Coordinate Coordinate => new(_x ?? 0, _y ?? 0, _weight ?? 0); - /// /// Occurs when a property value changes. /// /// public event PropertyChangedEventHandler? PropertyChanged; + /// + public int EntityIndex { get; set; } + + /// + public Dictionary? ChartPoints { get; set; } + + /// + public Coordinate Coordinate { get; private set; } = Coordinate.Empty; + /// /// Called when a property changed. /// /// Name of the property. protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { + Coordinate = _x is null || _y is null + ? Coordinate.Empty + : new(_x ?? 0, _y ?? 0, _weight ?? 0); PropertyChanged?.Invoke(propertyName, new PropertyChangedEventArgs(propertyName)); } } diff --git a/src/LiveChartsCore/FinancialSeries.cs b/src/LiveChartsCore/FinancialSeries.cs index 1de6e2078..59f263f2b 100644 --- a/src/LiveChartsCore/FinancialSeries.cs +++ b/src/LiveChartsCore/FinancialSeries.cs @@ -166,7 +166,7 @@ public override void Measure(Chart chart) var low = primaryScale.ToPixels(point.QuinaryValue); var middle = open; - if (point.IsNull) + if (point.IsEmpty) { if (visual is not null) { diff --git a/src/LiveChartsCore/HeatSeries.cs b/src/LiveChartsCore/HeatSeries.cs index f923486a4..ef018ccdd 100644 --- a/src/LiveChartsCore/HeatSeries.cs +++ b/src/LiveChartsCore/HeatSeries.cs @@ -128,7 +128,7 @@ public override void Measure(Chart chart) var baseColor = HeatFunctions.InterpolateColor(tertiary, _weightBounds, HeatMap, _heatStops); - if (point.IsNull) + if (point.IsEmpty) { if (visual is not null) { diff --git a/src/LiveChartsCore/Kernel/ChartPoint.cs b/src/LiveChartsCore/Kernel/ChartPoint.cs index f960e373d..cdfcbd132 100644 --- a/src/LiveChartsCore/Kernel/ChartPoint.cs +++ b/src/LiveChartsCore/Kernel/ChartPoint.cs @@ -29,26 +29,53 @@ namespace LiveChartsCore.Kernel; /// /// Defines a point in a chart. /// -public class ChartPoint : ICoordinate +public class ChartPoint { + private Coordinate _localCoordinate = Coordinate.Empty; + + /// + /// Overrides whether the coordinate is empty. + /// + protected bool IsLocalEmpty; + /// /// Initializes a new instance of the class. /// /// The chart. /// The series. - public ChartPoint(IChartView chart, ISeries series) + /// The entity. + public ChartPoint(IChartView chart, ISeries series, IChartEntity entity) + { + Context = new ChartPointContext(chart, series, entity); + } + + /// + /// Initializes a new instance of the class. + /// + /// The point. + protected ChartPoint(ChartPoint point) : this(point.Context.Chart, point.Context.Series, point.Context.Entity) + { + IsLocalEmpty = point.IsLocalEmpty; + } + + private ChartPoint() { - Context = new ChartPointContext(chart, series); + Context = new ChartPointContext(); } + /// + /// Gets a new instance of an empty chart point. + /// + public static ChartPoint Empty => new() { IsLocalEmpty = true }; + /// /// Gets or sets a value indicating whether this instance is null. /// /// /// true if this instance is null; otherwise, false. /// - [Obsolete($"Renamed to {nameof(IsEmpty)}")] - public bool IsNull { get => IsEmpty; set => IsEmpty = value; } + [Obsolete($"Use IsEmpty instead")] + public bool IsNull => IsEmpty; /// /// Gets or sets a value indicating whether this instance is empty. @@ -56,7 +83,7 @@ public ChartPoint(IChartView chart, ISeries series) /// /// true if this instance is empty; otherwise, false. /// - public bool IsEmpty { get; set; } + public bool IsEmpty => IsLocalEmpty || Context.Entity.Coordinate.IsEmpty; /// /// Gets or sets the primary value. @@ -66,10 +93,10 @@ public ChartPoint(IChartView chart, ISeries series) /// public double PrimaryValue { - get => Coordinate.PrimaryValue; - [Obsolete($"Coordinate setters are obsolete, please set the {nameof(Coordinate)} property instead.")] + get => _localCoordinate.IsEmpty ? Context.Entity.Coordinate.PrimaryValue : _localCoordinate.PrimaryValue; set => OnCoordinateChanged( - new Coordinate(value, Coordinate.SecondaryValue, Coordinate.TertiaryValue, Coordinate.QuaternaryValue, Coordinate.QuinaryValue)); + new Coordinate(value, _localCoordinate.SecondaryValue, _localCoordinate.TertiaryValue, + _localCoordinate.QuaternaryValue, _localCoordinate.QuinaryValue)); } /// @@ -80,10 +107,10 @@ public double PrimaryValue /// public double SecondaryValue { - get => Coordinate.SecondaryValue; - [Obsolete($"Coordinate setters are obsolete, please set the {nameof(Coordinate)} property instead.")] + get => _localCoordinate.IsEmpty ? Context.Entity.Coordinate.SecondaryValue : _localCoordinate.SecondaryValue; set => OnCoordinateChanged( - new Coordinate(Coordinate.PrimaryValue, value, Coordinate.TertiaryValue, Coordinate.QuaternaryValue, Coordinate.QuinaryValue)); + new Coordinate(_localCoordinate.PrimaryValue, value, _localCoordinate.TertiaryValue, + _localCoordinate.QuaternaryValue, _localCoordinate.QuinaryValue)); } /// @@ -94,10 +121,10 @@ public double SecondaryValue /// public double TertiaryValue { - get => Coordinate.TertiaryValue; - [Obsolete($"Coordinate setters are obsolete, please set the {nameof(Coordinate)} property instead.")] + get => _localCoordinate.IsEmpty ? Context.Entity.Coordinate.TertiaryValue : _localCoordinate.TertiaryValue; set => OnCoordinateChanged( - new Coordinate(Coordinate.PrimaryValue, Coordinate.SecondaryValue, value, Coordinate.QuaternaryValue, Coordinate.QuinaryValue)); + new Coordinate(_localCoordinate.PrimaryValue, _localCoordinate.SecondaryValue, value, + _localCoordinate.QuaternaryValue, _localCoordinate.QuinaryValue)); } /// @@ -108,10 +135,10 @@ public double TertiaryValue /// public double QuaternaryValue { - get => Coordinate.QuaternaryValue; - [Obsolete($"Coordinate setters are obsolete, please set the {nameof(Coordinate)} property instead.")] + get => _localCoordinate.IsEmpty ? Context.Entity.Coordinate.QuaternaryValue : _localCoordinate.QuaternaryValue; set => OnCoordinateChanged( - new Coordinate(Coordinate.PrimaryValue, Coordinate.SecondaryValue, Coordinate.TertiaryValue, value, Coordinate.QuinaryValue)); + new Coordinate(_localCoordinate.PrimaryValue, _localCoordinate.SecondaryValue, + _localCoordinate.TertiaryValue, value, _localCoordinate.QuinaryValue)); } /// @@ -122,10 +149,10 @@ public double QuaternaryValue /// public double QuinaryValue { - get => Coordinate.QuinaryValue; - [Obsolete($"Coordinate setters are obsolete, please set the {nameof(Coordinate)} property instead.")] + get => _localCoordinate.IsEmpty ? Context.Entity.Coordinate.QuinaryValue : _localCoordinate.QuinaryValue; set => OnCoordinateChanged( - new Coordinate(Coordinate.PrimaryValue, Coordinate.SecondaryValue, Coordinate.TertiaryValue, Coordinate.QuaternaryValue, value)); + new Coordinate(_localCoordinate.PrimaryValue, _localCoordinate.SecondaryValue, + _localCoordinate.TertiaryValue, _localCoordinate.QuaternaryValue, value)); } /// @@ -157,9 +184,6 @@ public double QuinaryValue /// public ChartPointContext Context { get; } - /// - public Coordinate Coordinate { get; set; } - /// /// Gets the distance to a given point. /// @@ -172,7 +196,10 @@ public double DistanceTo(LvcPoint point) private void OnCoordinateChanged(Coordinate coordinate) { - Coordinate = coordinate; + // ToDo: + // how can this be improved??? + // does this have a significant performance impact? + _localCoordinate = coordinate; } } @@ -188,12 +215,9 @@ public class ChartPoint : ChartPoint /// Initializes a new instance of the class. /// /// The point. - public ChartPoint(ChartPoint point) : base(point.Context.Chart, point.Context.Series) + public ChartPoint(ChartPoint point) : base(point) { - IsNull = point.IsNull; - Coordinate = point.Coordinate; StackedValue = point.StackedValue; - Context.Index = point.Context.Index; Context.DataSource = point.Context.DataSource; Context.Visual = point.Context.Visual; Context.Label = point.Context.Label; diff --git a/src/LiveChartsCore/Kernel/ChartPointContext.cs b/src/LiveChartsCore/Kernel/ChartPointContext.cs index 365e9467b..2735c1b88 100644 --- a/src/LiveChartsCore/Kernel/ChartPointContext.cs +++ b/src/LiveChartsCore/Kernel/ChartPointContext.cs @@ -20,6 +20,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System; +using LiveChartsCore.Defaults; using LiveChartsCore.Kernel.Drawing; using LiveChartsCore.Kernel.Sketches; @@ -35,10 +37,21 @@ public class ChartPointContext /// /// The chart. /// The series. - public ChartPointContext(IChartView chart, ISeries series) + /// The entity. + public ChartPointContext(IChartView chart, ISeries series, IChartEntity entity) { Chart = chart; Series = series; + Entity = entity; + } + + internal ChartPointContext() + { + // dummy empty constructor.. + // This is used only when the IChartEntity was null + Chart = null!; + Series = null!; + Entity = new MappedChartEntity(); } /// @@ -58,15 +71,21 @@ public ChartPointContext(IChartView chart, ISeries series) public ISeries Series { get; } /// - /// Gets the position of the point the collection that was used when the point was drawn. + /// Gets the . /// - public int Index { get; internal set; } + public IChartEntity Entity { get; } /// /// Gets the DataSource. /// public object? DataSource { get; internal set; } + /// + /// Gets the position of the point the collection that was used when the point was drawn. + /// + [Obsolete("Use Entity.EntityIndex")] + public int Index => Entity?.EntityIndex ?? 0; + /// /// Gets the visual. /// diff --git a/src/LiveChartsCore/Kernel/Coordinate.cs b/src/LiveChartsCore/Kernel/Coordinate.cs index b0a1d6307..7d476240e 100644 --- a/src/LiveChartsCore/Kernel/Coordinate.cs +++ b/src/LiveChartsCore/Kernel/Coordinate.cs @@ -27,10 +27,6 @@ namespace LiveChartsCore.Kernel; /// public readonly struct Coordinate { -#pragma warning disable IDE0032 // Use auto property - private readonly bool _isEmpty; -#pragma warning restore IDE0032 // Use auto property - /// /// Initializes a new instance of the struct. /// @@ -67,20 +63,18 @@ public Coordinate(double x, double y, double weight) : this(y, x, weight, 0, 0) private Coordinate(bool isEmpty) : this(0, 0, 0, 0, 0) { - _isEmpty = isEmpty; + IsEmpty = isEmpty; } /// /// Gets an empty coordinate instance. /// - public static readonly Coordinate Empty = new(true); + public static Coordinate Empty => new(true); /// /// Evaluates whether the instance is empty. /// -#pragma warning disable IDE0032 // Use auto property - public readonly bool IsEmpty => _isEmpty; -#pragma warning restore IDE0032 // Use auto property + public readonly bool IsEmpty { get; } /// /// Gets or sets the primary value, normally the Y coordinate or the value in a gauge. diff --git a/src/LiveChartsCore/Kernel/Extensions.cs b/src/LiveChartsCore/Kernel/Extensions.cs index f92687dea..aedc535b7 100644 --- a/src/LiveChartsCore/Kernel/Extensions.cs +++ b/src/LiveChartsCore/Kernel/Extensions.cs @@ -30,7 +30,7 @@ namespace LiveChartsCore.Kernel; /// -/// LiveCharts kerner extensions. +/// LiveCharts kernel extensions. /// public static class Extensions { @@ -141,15 +141,19 @@ public static AxisTick GetTick(this ICartesianAxis axis, LvcSize controlSize, Bo var min = axis.MinLimit is null ? bounds.Min : axis.MinLimit.Value; var range = max - min; + if (range == 0) range = min; + var separations = axis.Orientation == AxisOrientation.Y ? Math.Round(controlSize.Height / (12 * Cf), 0) : Math.Round(controlSize.Width / (20 * Cf), 0); + var minimum = range / separations; var magnitude = Math.Pow(10, Math.Floor(Math.Log(minimum) / Math.Log(10))); var residual = minimum / magnitude; var tick = residual > 5 ? 10 * magnitude : residual > 2 ? 5 * magnitude : residual > 1 ? 2 * magnitude : magnitude; + return new AxisTick { Value = tick, Magnitude = magnitude }; } @@ -301,7 +305,7 @@ public static TooltipFindingStrategy GetTooltipFindingStrategy(this IEnumerable< /// /// Finds the closest point to the specified location in UI coordinates. /// - /// The points to look in to.bcv + /// The points to look in to. /// The location. /// public static ChartPoint FindClosestTo(this IEnumerable points, LvcPoint point) @@ -312,7 +316,7 @@ public static ChartPoint FindClosestTo(this IEnumerable points, LvcP /// /// Finds the closest point to the specified location in UI coordinates. /// - /// The points to look in to.bcv + /// The points to look in to. /// The location. /// public static ChartPoint FindClosestTo( @@ -359,7 +363,7 @@ public static Scaler GetNextScaler(this ICartesianAxis axis, Ca } /// - /// Returns an enumeration with only the fisrt element. + /// Returns an enumeration with only the first element. /// /// The source type. /// The target type. @@ -375,6 +379,17 @@ public static IEnumerable SelectFirst(this IEnumerable source, Fun } } + /// + /// Gets the point for the given view. + /// + /// The points dictionary. + /// The view. + /// + public static ChartPoint? GetPointForView(this Dictionary dictionary, IChartView view) + { + return dictionary.TryGetValue(view, out var point) ? point : null; + } + private static ChartPoint _findClosestTo(this IEnumerable points, LvcPoint point) { var o = points.Select(p => new { distance = p.DistanceTo(point), point = p }).OrderBy(p => p.distance).ToArray(); diff --git a/src/LiveChartsCore/Kernel/IChartEntity.cs b/src/LiveChartsCore/Kernel/IChartEntity.cs index c0665ddee..4a76d3829 100644 --- a/src/LiveChartsCore/Kernel/IChartEntity.cs +++ b/src/LiveChartsCore/Kernel/IChartEntity.cs @@ -20,20 +20,28 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System.Collections.Generic; +using LiveChartsCore.Kernel.Sketches; + namespace LiveChartsCore.Kernel; /// /// Defines a point with a visual representation in the user interface. /// -public interface IChartEntity : ICoordinate +public interface IChartEntity { /// - /// Gets or sets the entity id. + /// Gets the entity index, a consecutive integer based on the position of the entity in the data collection. + /// + public int EntityIndex { get; set; } + + /// + /// Gets the chart points dictionary. /// - public int EntityId { get; set; } + public Dictionary? ChartPoints { get; set; } /// - /// Gets or sets the chart point. + /// Gets the coordinate. /// - public ChartPoint? ChartPoint { get; set; } + Coordinate Coordinate { get; } } diff --git a/src/LiveChartsCore/Kernel/ICoordinate.cs b/src/LiveChartsCore/Kernel/ICoordinate.cs deleted file mode 100644 index b9d967fc5..000000000 --- a/src/LiveChartsCore/Kernel/ICoordinate.cs +++ /dev/null @@ -1,34 +0,0 @@ -// The MIT License(MIT) -// -// Copyright(c) 2021 Alberto Rodriguez Orozco & LiveCharts Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -namespace LiveChartsCore.Kernel; - -/// -/// Defines an object with a coordinate coordinate. -/// -public interface ICoordinate -{ - /// - /// Gets the coordinate. - /// - public Coordinate Coordinate { get; } -} diff --git a/src/LiveChartsCore/Kernel/LiveChartsSettings.cs b/src/LiveChartsCore/Kernel/LiveChartsSettings.cs index 97d857186..d70e61bed 100644 --- a/src/LiveChartsCore/Kernel/LiveChartsSettings.cs +++ b/src/LiveChartsCore/Kernel/LiveChartsSettings.cs @@ -143,20 +143,20 @@ internal Action GetMap() : (Action)mapper; } - internal LiveChartsSettings HasProvider(ChartProvider factory) + internal LiveChartsSettings HasProvider(ChartEngine factory) where TDrawingContext : DrawingContext { _currentProvider = factory; return this; } - internal ChartProvider GetProvider() + internal ChartEngine GetProvider() where TDrawingContext : DrawingContext { return _currentProvider is null ? throw new NotImplementedException( - $"There is no a {nameof(ChartProvider)} registered.") - : (ChartProvider)_currentProvider; + $"There is no a {nameof(ChartEngine)} registered.") + : (ChartEngine)_currentProvider; } /// @@ -262,209 +262,68 @@ public LiveChartsSettings AddDefaultMappers() HasMap((model, point) => { point.PrimaryValue = model; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { point.PrimaryValue = model; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { point.PrimaryValue = model; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { point.PrimaryValue = model; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { point.PrimaryValue = model; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { - point.PrimaryValue = unchecked((double)model); - point.SecondaryValue = point.Context.Index; + point.PrimaryValue = (double)model; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { - if (model is null) - { - point.IsNull = true; - return; - } - point.IsNull = false; + if (model is null) throw new Exception("Unexpected exception"); point.PrimaryValue = model.Value; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { - if (model is null) - { - point.IsNull = true; - return; - } - point.IsNull = false; + if (model is null) throw new Exception("Unexpected exception"); point.PrimaryValue = model.Value; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { - if (model is null) - { - point.IsNull = true; - return; - } - point.IsNull = false; + if (model is null) throw new Exception("Unexpected exception"); point.PrimaryValue = model.Value; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { - if (model is null) - { - point.IsNull = true; - return; - } - point.IsNull = false; + if (model is null) throw new Exception("Unexpected exception"); point.PrimaryValue = model.Value; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { - if (model is null) - { - point.IsNull = true; - return; - } - point.IsNull = false; + if (model is null) throw new Exception("Unexpected exception"); point.PrimaryValue = model.Value; - point.SecondaryValue = point.Context.Index; + point.SecondaryValue = point.Context.Entity.EntityIndex; }) .HasMap((model, point) => { - if (model is null) - { - point.IsNull = true; - return; - } - point.IsNull = false; - point.PrimaryValue = unchecked((double)model.Value); - point.SecondaryValue = point.Context.Index; - }) - .HasMap((model, point) => - { - if (model is null) - throw new Exception( - $"A {nameof(WeightedPoint)} can not be null, instead set to null to any of its properties."); - - if (model.Weight is null || model.X is null || model.Y is null) - { - point.IsNull = true; - return; - } - - point.IsNull = false; - point.PrimaryValue = model.Y.Value; - point.SecondaryValue = model.X.Value; - point.TertiaryValue = model.Weight.Value; - }) - .HasMap((model, point) => - { - if (model is null) - throw new Exception( - $"A {nameof(ObservableValue)} can not be null, instead set to null to any of its properties."); - - if (model.Value is null) - { - point.IsNull = true; - return; - } - - point.IsNull = false; - point.PrimaryValue = model.Value.Value; - point.SecondaryValue = point.Context.Index; - }) - .HasMap((model, point) => - { - if (model is null) - throw new Exception( - $"A {nameof(ObservablePoint)} can not be null, instead set to null to any of its properties."); - - if (model.X is null || model.Y is null) - { - point.IsNull = true; - return; - } - - point.IsNull = false; - point.PrimaryValue = model.Y.Value; - point.SecondaryValue = model.X.Value; - }) - .HasMap((model, point) => - { - if (model is null) - throw new Exception( - $"A {nameof(ObservablePolarPoint)} can not be null, instead set to null to any of its properties."); - - if (model.Angle is null || model.Radius is null) - { - point.IsNull = true; - return; - } - - point.IsNull = false; - point.PrimaryValue = model.Radius.Value; - point.SecondaryValue = model.Angle.Value; - }) - .HasMap((model, point) => - { - if (model is null) - throw new Exception( - $"A {nameof(DateTimePoint)} can not be null, instead set to null the " + - $"{nameof(DateTimePoint.Value)} property."); - - if (model.Value is null) - { - point.IsNull = true; - return; - } - - point.IsNull = false; - point.PrimaryValue = model.Value.Value; - point.SecondaryValue = model.DateTime.Ticks; - }) - .HasMap((model, point) => - { - if (model is null) - throw new Exception( - $"A {nameof(TimeSpanPoint)} can not be null, instead set to null the " + - $"{nameof(TimeSpanPoint.Value)} property."); - - if (model.Value is null) - { - point.IsNull = true; - return; - } - - point.IsNull = false; - point.PrimaryValue = model.Value.Value; - point.SecondaryValue = model.TimeSpan.Ticks; - }) - .HasMap((model, point) => - { - if (model is null) - throw new Exception( - $"A {nameof(FinancialPoint)} can not be null"); - - point.PrimaryValue = model.High; - point.SecondaryValue = model.Date.Ticks; - point.TertiaryValue = model.Open; - point.QuaternaryValue = model.Close; - point.QuinaryValue = model.Low; + if (model is null) throw new Exception("Unexpected exception"); + point.PrimaryValue = (double)model.Value; + point.SecondaryValue = point.Context.Entity.EntityIndex; }); } } diff --git a/src/LiveChartsCore/Kernel/Providers/ChartProvider.cs b/src/LiveChartsCore/Kernel/Providers/ChartEngine.cs similarity index 84% rename from src/LiveChartsCore/Kernel/Providers/ChartProvider.cs rename to src/LiveChartsCore/Kernel/Providers/ChartEngine.cs index ab294b1ba..38496ad74 100644 --- a/src/LiveChartsCore/Kernel/Providers/ChartProvider.cs +++ b/src/LiveChartsCore/Kernel/Providers/ChartEngine.cs @@ -20,7 +20,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -using System.ComponentModel; using LiveChartsCore.Drawing; using LiveChartsCore.Geo; using LiveChartsCore.Kernel.Sketches; @@ -28,10 +27,10 @@ namespace LiveChartsCore.Kernel.Providers; /// -/// Defines the chart provider class. +/// Defines the class. /// /// The type of the drawing context. -public abstract class ChartProvider +public abstract class ChartEngine where TDrawingContext : DrawingContext { /// @@ -41,11 +40,7 @@ public abstract class ChartProvider /// public virtual DataFactory GetDefaultDataFactory() { - var isChartEntity = typeof(IChartEntity).IsAssignableFrom(typeof(TModel)); - - return isChartEntity - ? new EntitiesDataFactory() // <- this is the way to go - : new DataFactory(); // <- this factory is just here to support older versions and by val types. + return new DataFactory(); } /// diff --git a/src/LiveChartsCore/Kernel/Providers/DataFactory.cs b/src/LiveChartsCore/Kernel/Providers/DataFactory.cs index 7843063c6..92d62947d 100644 --- a/src/LiveChartsCore/Kernel/Providers/DataFactory.cs +++ b/src/LiveChartsCore/Kernel/Providers/DataFactory.cs @@ -22,6 +22,8 @@ using System; using System.Collections.Generic; +using System.Linq; +using LiveChartsCore.Defaults; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel.Sketches; using LiveChartsCore.Measure; @@ -37,46 +39,29 @@ namespace LiveChartsCore.Kernel.Providers; public class DataFactory where TDrawingContext : DrawingContext { - /// - /// Gets the by value map. - /// - protected Dictionary> ByChartbyValueVisualMap { get; } = new(); - -#nullable disable - - // note #270422 - // We use the ByChartbyValueVisualMap for nullable and value types - // for reference types we use the ByChartByReferenceVisualMap it does not allows nulls, it throws in the mapper - // when it founds a null type and then it warns you on how to use it. - // this is a current limitation and could be supported in future verions. - - /// - /// Gets the by reference map. - /// - protected Dictionary> ByChartByReferenceVisualMap { get; } = new(); - -#nullable restore - - /// - /// Indicates whether the factory uses value or reference types. - /// - protected bool IsValueType { get; private set; } = false; + private readonly bool _isTModelChartEntity = false; + private readonly bool _isValueType = false; + private readonly Dictionary> _chartIndexEntityMap = new(); + private readonly Dictionary> _chartRefEntityMap = new(); + private ISeries? _series; /// /// Gets or sets the previous known bounds. /// - public DimensionalBounds PreviousKnownBounds { get; set; } + protected DimensionalBounds PreviousKnownBounds { get; set; } = new DimensionalBounds(true); /// /// Initializes a new instance of the class. /// public DataFactory() { - var t = typeof(TModel); - IsValueType = t.IsValueType; - var bounds = new DimensionalBounds(true); PreviousKnownBounds = bounds; + + var t = typeof(TModel); + _isValueType = t.IsValueType; + + _isTModelChartEntity = typeof(IChartEntity).IsAssignableFrom(typeof(TModel)); } /// @@ -88,59 +73,17 @@ public DataFactory() public virtual IEnumerable Fetch(ISeries series, IChart chart) { if (series.Values is null) yield break; + _series = series; - var canvas = (MotionCanvas)chart.Canvas; - - var mapper = series.Mapping ?? LiveCharts.CurrentSettings.GetMap(); - var index = 0; - - if (IsValueType) + foreach (var value in GetEntities(series, chart)) { - _ = ByChartbyValueVisualMap.TryGetValue(canvas.Sync, out var d); - if (d is null) + if (value is null) { - d = new Dictionary(); - ByChartbyValueVisualMap[canvas.Sync] = d; + yield return ChartPoint.Empty; + continue; } - var byValueVisualMap = d; - - foreach (var item in series.Values) - { - if (!byValueVisualMap.TryGetValue(index, out var cp)) - byValueVisualMap[index] = cp = new ChartPoint(chart.View, series); - cp.Context.Index = index++; - cp.Context.DataSource = item; - - mapper(item, cp); - - yield return cp; - } - } - else - { - _ = ByChartByReferenceVisualMap.TryGetValue(canvas.Sync, out var d); - if (d is null) - { -#nullable disable - // see note #270422 - d = new Dictionary(); -#nullable restore - ByChartByReferenceVisualMap[canvas.Sync] = d; - } - var byReferenceVisualMap = d; - - foreach (var item in series.Values) - { - if (!byReferenceVisualMap.TryGetValue(item, out var cp)) - byReferenceVisualMap[item] = cp = new ChartPoint(chart.View, series); - - cp.Context.Index = index++; - cp.Context.DataSource = item; - mapper(item, cp); - - yield return cp; - } + yield return value.ChartPoints?.GetPointForView(chart.View) ?? ChartPoint.Empty; } } @@ -151,22 +94,25 @@ public virtual IEnumerable Fetch(ISeries series, IChart char /// public virtual void DisposePoint(ChartPoint point) { - if (IsValueType) + if (_isTModelChartEntity) return; + + var canvas = (MotionCanvas)point.Context.Chart.CoreChart.Canvas; + + if (_isValueType) { - var canvas = (MotionCanvas)point.Context.Chart.CoreChart.Canvas; - _ = ByChartbyValueVisualMap.TryGetValue(canvas.Sync, out var d); - var byValueVisualMap = d; - if (byValueVisualMap is null) return; - _ = byValueVisualMap.Remove(point.Context.Index); + _ = _chartIndexEntityMap.TryGetValue(canvas.Sync, out var d); + var map = d; + if (map is null) return; + _ = map.Remove(point.Context.Entity.EntityIndex); } else { - if (point.Context.DataSource is null) return; - var canvas = (MotionCanvas)point.Context.Chart.CoreChart.Canvas; - _ = ByChartByReferenceVisualMap.TryGetValue(canvas.Sync, out var d); - var byReferenceVisualMap = d; - if (byReferenceVisualMap is null) return; - _ = byReferenceVisualMap.Remove((TModel)point.Context.DataSource); + _ = _chartRefEntityMap.TryGetValue(canvas.Sync, out var d); + var map = d; + if (map is null) return; + var src = (TModel?)point.Context.DataSource; + if (src is null) return; + _ = map.Remove(src); } } @@ -176,15 +122,18 @@ public virtual void DisposePoint(ChartPoint point) /// public virtual void Dispose(IChart chart) { - if (IsValueType) + _series = null; + if (_isTModelChartEntity) return; + + if (_isValueType) { var canvas = (MotionCanvas)chart.Canvas; - _ = ByChartbyValueVisualMap.Remove(canvas.Sync); + _ = _chartIndexEntityMap.Remove(canvas.Sync); } else { var canvas = (MotionCanvas)chart.Canvas; - _ = ByChartByReferenceVisualMap.Remove(canvas.Sync); + _ = _chartRefEntityMap.Remove(canvas.Sync); } } @@ -217,6 +166,8 @@ public virtual SeriesBounds GetCartesianBounds( foreach (var point in series.Fetch(chart)) { + if (point.IsEmpty) continue; + var primary = point.PrimaryValue; var secondary = point.SecondaryValue; var tertiary = point.TertiaryValue; @@ -276,6 +227,8 @@ public virtual SeriesBounds GetFinancialBounds( ChartPoint? previous = null; foreach (var point in series.Fetch(chart)) { + if (point.IsEmpty) continue; + var primaryMax = point.PrimaryValue; var primaryMin = point.QuinaryValue; var secondary = point.SecondaryValue; @@ -329,6 +282,8 @@ public virtual SeriesBounds GetPieBounds( foreach (var point in series.Fetch(chart)) { + if (point.IsEmpty) continue; + _ = stack.StackPoint(point); bounds.PrimaryBounds.AppendValue(point.PrimaryValue); bounds.SecondaryBounds.AppendValue(point.SecondaryValue); @@ -346,30 +301,183 @@ public virtual SeriesBounds GetPieBounds( return new SeriesBounds(bounds, false); } + /// /// Clears the visuals in the cache. /// - /// - public virtual void RestartVisuals() + public void RestartVisuals() { - foreach (var byReferenceVisualMap in ByChartByReferenceVisualMap) + if (_series is not null && _series.Values is IEnumerable entities) { - foreach (var item in byReferenceVisualMap.Value) + foreach (var entity in entities) { - if (item.Value.Context.Visual is not IAnimatable visual) continue; - visual.RemoveTransition(null); + foreach (var chartPoint in entity.ChartPoints?.Values ?? Enumerable.Empty()) + { + if (chartPoint.Context.Visual is not IAnimatable visual) continue; + visual.RemoveTransition(null); + } } - byReferenceVisualMap.Value.Clear(); } - foreach (var byValueVisualMap in ByChartbyValueVisualMap) + foreach (var item in _chartIndexEntityMap.Values) { - foreach (var item in byValueVisualMap.Value) + foreach (var index in item.Values) { - if (item.Value.Context.Visual is not IAnimatable visual) continue; - visual.RemoveTransition(null); + foreach (var chartPoint in index.ChartPoints?.Values ?? Enumerable.Empty()) + { + if (chartPoint.Context.Visual is not IAnimatable visual) continue; + visual.RemoveTransition(null); + } } - byValueVisualMap.Value.Clear(); + } + _chartIndexEntityMap.Clear(); + + foreach (var item in _chartRefEntityMap.Values) + { + foreach (var index in item.Values) + { + foreach (var chartPoint in index.ChartPoints?.Values ?? Enumerable.Empty()) + { + if (chartPoint.Context.Visual is not IAnimatable visual) continue; + visual.RemoveTransition(null); + } + } + } + _chartRefEntityMap.Clear(); + } + + private IEnumerable GetEntities(ISeries series, IChart chart) + { + return _isTModelChartEntity + ? EnumerateChartEntities(series, chart) + : (_isValueType + ? EnumerateByValEntities(series, chart) + : EnumerateByRefEntities(series, chart)); + } + + private IEnumerable EnumerateChartEntities(ISeries series, IChart chart) + { + if (series.Values is null) yield break; + var entities = (IEnumerable)series.Values; + var index = 0; + + foreach (var entity in entities) + { + if (entity is null) + { + index++; + continue; + } + + entity.ChartPoints ??= new Dictionary(); + if (!entity.ChartPoints.TryGetValue(chart.View, out var point)) + { + point = new ChartPoint(chart.View, series, entity); + entity.ChartPoints[chart.View] = point; + } + + point.Context.DataSource = entity; + entity.EntityIndex = index++; + + yield return entity; + } + } + + private IEnumerable EnumerateByValEntities(ISeries series, IChart chart) + { + if (series.Values is null) yield break; + + var canvas = (MotionCanvas)chart.Canvas; + var mapper = series.Mapping ?? LiveCharts.CurrentSettings.GetMap(); + var index = 0; + + _ = _chartIndexEntityMap.TryGetValue(canvas.Sync, out var d); + if (d is null) + { + d = new Dictionary(); + _chartIndexEntityMap[canvas.Sync] = d; + } + var IndexEntityMap = d; + + foreach (var item in series.Values) + { + if (item is null) + { + yield return new MappedChartEntity(); + index++; + continue; + } + + if (!IndexEntityMap.TryGetValue(index, out var entity)) + { + IndexEntityMap[index] = entity = new MappedChartEntity + { + ChartPoints = new Dictionary() + }; + } + + if (!entity.ChartPoints!.TryGetValue(chart.View, out var point)) + { + point = new ChartPoint(chart.View, series, entity); + entity.ChartPoints[chart.View] = point; + } + + point.Context.DataSource = item; + entity.EntityIndex = index++; + + mapper(item, point); + entity.UpdateCoordinate(point); + + yield return entity; + } + } + + private IEnumerable EnumerateByRefEntities(ISeries series, IChart chart) + { + if (series.Values is null) yield break; + + var canvas = (MotionCanvas)chart.Canvas; + var mapper = series.Mapping ?? LiveCharts.CurrentSettings.GetMap(); + var index = 0; + + _ = _chartRefEntityMap.TryGetValue(canvas.Sync, out var d); + if (d is null) + { + d = new Dictionary(); + _chartRefEntityMap[canvas.Sync] = d; + } + var IndexEntityMap = d; + + foreach (var item in series.Values) + { + if (item is null) + { + yield return new MappedChartEntity(); + index++; + continue; + } + + if (!IndexEntityMap.TryGetValue(item, out var entity)) + { + IndexEntityMap[item] = entity = new MappedChartEntity + { + ChartPoints = new Dictionary() + }; + } + + if (!entity.ChartPoints!.TryGetValue(chart.View, out var point)) + { + point = new ChartPoint(chart.View, series, entity); + entity.ChartPoints[chart.View] = point; + } + + point.Context.DataSource = item; + entity.EntityIndex = index++; + + mapper(item, point); + entity.UpdateCoordinate(point); + + yield return entity; } } } diff --git a/src/LiveChartsCore/LineSeries.cs b/src/LiveChartsCore/LineSeries.cs index f815da20c..45854a291 100644 --- a/src/LiveChartsCore/LineSeries.cs +++ b/src/LiveChartsCore/LineSeries.cs @@ -249,7 +249,6 @@ public override void Measure(Chart chart) var visual = (TVisualPoint?)data.TargetPoint.Context.Visual; - if (visual is null) { var v = new TVisualPoint(); diff --git a/src/LiveChartsCore/LiveChartsCore.csproj b/src/LiveChartsCore/LiveChartsCore.csproj index f94373969..e1a67044f 100644 --- a/src/LiveChartsCore/LiveChartsCore.csproj +++ b/src/LiveChartsCore/LiveChartsCore.csproj @@ -17,7 +17,7 @@ LiveChartsCore LiveChartsCore - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for .Net, this is the core package probably you need another package also unless you are building your own backed. MIT diff --git a/src/LiveChartsCore/Measure/MeasureExtensions.cs b/src/LiveChartsCore/Measure/MeasureExtensions.cs index c2143700b..ae9f52e8f 100644 --- a/src/LiveChartsCore/Measure/MeasureExtensions.cs +++ b/src/LiveChartsCore/Measure/MeasureExtensions.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; +using System.Linq; using LiveChartsCore.Kernel; namespace LiveChartsCore.Measure; @@ -52,7 +53,7 @@ public static IEnumerable> SplitByNullGaps( /// internal static IEnumerable AsSplineData(this IEnumerable source) { - using var e = source.GetEnumerator(); + using var e = source.Where(x => !x.IsEmpty).GetEnumerator(); if (!e.MoveNext()) yield break; var data = new SplineData(e.Current); @@ -85,7 +86,7 @@ private static IEnumerable YieldReturnUntilNextNullChartPoint( { while (builder.Enumerator.MoveNext()) { - if (builder.Enumerator.Current.IsNull) + if (builder.Enumerator.Current.IsEmpty) { var wasEmpty = builder.IsEmpty; builder.IsEmpty = true; diff --git a/src/LiveChartsCore/Measure/Scaler.cs b/src/LiveChartsCore/Measure/Scaler.cs index 79c2e413c..e65f64319 100644 --- a/src/LiveChartsCore/Measure/Scaler.cs +++ b/src/LiveChartsCore/Measure/Scaler.cs @@ -180,7 +180,7 @@ internal Scaler() public double MinVal { get; private set; } /// - /// Converts to pixels. + /// Measures an absolute value in pixels. /// /// The value. /// @@ -195,9 +195,9 @@ public float MeasureInPixels(double value) } /// - /// Converts to pixels. + /// Converts a given value (in chart values) to pixels. /// - /// The value. + /// The value in chart values. /// public float ToPixels(double value) { @@ -205,9 +205,9 @@ public float ToPixels(double value) } /// - /// Converts to chart values. + /// Converts a given value (in pixels) to chart values. /// - /// The pixels. + /// The value in pixels. /// public double ToChartValues(double pixels) { diff --git a/src/LiveChartsCore/Motion/MotionProperty.cs b/src/LiveChartsCore/Motion/MotionProperty.cs index 37c1e1606..d73d9095e 100644 --- a/src/LiveChartsCore/Motion/MotionProperty.cs +++ b/src/LiveChartsCore/Motion/MotionProperty.cs @@ -122,7 +122,7 @@ public T GetMovement(Animatable animatable) { if (Animation is null || Animation.EasingFunction is null || fromValue is null || IsCompleted) return OnGetMovement(1); - if (_requiresToInitialize) + if (_requiresToInitialize || _startTime == long.MinValue) { _startTime = animatable.CurrentTime; _endTime = animatable.CurrentTime + Animation._duration; diff --git a/src/LiveChartsCore/PieSeries.cs b/src/LiveChartsCore/PieSeries.cs index 75d4ef79b..fd95d62fd 100644 --- a/src/LiveChartsCore/PieSeries.cs +++ b/src/LiveChartsCore/PieSeries.cs @@ -232,7 +232,7 @@ public override void Measure(Chart chart) { var visual = point.Context.Visual as TVisual; - if (point.IsNull) + if (point.IsEmpty) { if (visual is not null) { diff --git a/src/LiveChartsCore/PolarLineSeries.cs b/src/LiveChartsCore/PolarLineSeries.cs index fe92d3c8f..6e8c24f8f 100644 --- a/src/LiveChartsCore/PolarLineSeries.cs +++ b/src/LiveChartsCore/PolarLineSeries.cs @@ -857,7 +857,7 @@ private IEnumerable SplitEachNull( foreach (var point in points) { - if (point.IsNull) + if (point.IsEmpty) { if (point.Context.Visual is TVisualPoint visual) { diff --git a/src/LiveChartsCore/RowSeries.cs b/src/LiveChartsCore/RowSeries.cs index 979204eb3..cdda9b4f3 100644 --- a/src/LiveChartsCore/RowSeries.cs +++ b/src/LiveChartsCore/RowSeries.cs @@ -116,7 +116,7 @@ public override void Measure(Chart chart) var secondary = secondaryScale.ToPixels(point.SecondaryValue); var b = Math.Abs(primary - helper.p); - if (point.IsNull) + if (point.IsEmpty) { if (visual is not null) { diff --git a/src/LiveChartsCore/ScatterSeries.cs b/src/LiveChartsCore/ScatterSeries.cs index 8ef7a1ae8..5de00b001 100644 --- a/src/LiveChartsCore/ScatterSeries.cs +++ b/src/LiveChartsCore/ScatterSeries.cs @@ -129,7 +129,7 @@ public override void Measure(Chart chart) var x = xScale.ToPixels(point.SecondaryValue); var y = yScale.ToPixels(point.PrimaryValue); - if (point.IsNull) + if (point.IsEmpty) { if (visual is not null) { diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs index cf5ec08e3..937f8420c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/CartesianChart.axaml.cs @@ -42,6 +42,7 @@ using LiveChartsCore.Measure; using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Painting; namespace LiveChartsCore.SkiaSharpView.Avalonia; @@ -739,9 +740,20 @@ void IChartView.InvokeOnUIThread(Action action) protected void InitializeCore() { var canvas = this.FindControl("canvas"); + + var zoomingSection = new Drawing.Geometries.RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + _avaloniaCanvas = canvas; _core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore, zoomingSection); _core.Measuring += OnCoreMeasuring; _core.UpdateStarted += OnCoreUpdateStarted; @@ -816,7 +828,7 @@ private void CartesianChart_PointerPressed(object? sender, PointerPressedEventAr if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return; var p = e.GetPosition(this); foreach (var w in desktop.Windows) w.PointerReleased += Window_PointerReleased; - _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y)); + _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), e.GetCurrentPoint(this).Properties.IsRightButtonPressed); } private void CartesianChart_PointerMoved(object? sender, PointerEventArgs e) @@ -830,7 +842,7 @@ private void Window_PointerReleased(object? sender, PointerReleasedEventArgs e) if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return; foreach (var w in desktop.Windows) w.PointerReleased -= Window_PointerReleased; var p = e.GetPosition(this); - _core?.InvokePointerUp(new LvcPoint((float)p.X, (float)p.Y)); + _core?.InvokePointerUp(new LvcPoint((float)p.X, (float)p.Y), e.GetCurrentPoint(this).Properties.IsRightButtonPressed); } private void CartesianChart_PointerLeave(object? sender, PointerEventArgs e) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj index 6a1de95f9..0231e4262 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/LiveChartsCore.SkiaSharpView.Avalonia.csproj @@ -6,7 +6,7 @@ netcoreapp2.0;netstandard2.0;net462; LiveChartsCore.SkiaSharpView.Avalonia LiveChartsCore.SkiaSharpView.Avalonia - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for AvaloniaUI. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/PieChart.axaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/PieChart.axaml.cs index c833b42c2..26955ce9a 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/PieChart.axaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/PieChart.axaml.cs @@ -712,7 +712,7 @@ private void Chart_PointerMoved(object? sender, PointerEventArgs e) private void Chart_PointerPressed(object sender, PointerPressedEventArgs e) { var p = e.GetPosition(this); - _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y)); + _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), false); } private void OnCoreUpdateFinished(IChartView chart) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/PolarChart.axaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/PolarChart.axaml.cs index 000252cea..bdf997ff7 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/PolarChart.axaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Avalonia/PolarChart.axaml.cs @@ -797,7 +797,7 @@ private void PolarChart_PointerPressed(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 += Window_PointerReleased; - _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y)); + _core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), false); } private void PolarChart_PointerMoved(object? sender, PointerEventArgs e) @@ -811,7 +811,7 @@ private void Window_PointerReleased(object? sender, PointerReleasedEventArgs e) if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return; foreach (var w in desktop.Windows) w.PointerReleased -= Window_PointerReleased; var p = e.GetPosition(this); - _core?.InvokePointerUp(new LvcPoint((float)p.X, (float)p.Y)); + _core?.InvokePointerUp(new LvcPoint((float)p.X, (float)p.Y), false); } private void OnCoreUpdateFinished(IChartView chart) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/CartesianChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/CartesianChart.cs index 3e94c1c46..0c439c1ef 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/CartesianChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/CartesianChart.cs @@ -32,6 +32,8 @@ using LiveChartsCore.Kernel.Sketches; using LiveChartsCore.Measure; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; +using LiveChartsCore.SkiaSharpView.Painting; namespace LiveChartsCore.SkiaSharpView.WPF; @@ -40,10 +42,11 @@ public class CartesianChart : Chart, ICartesianChartView _seriesObserver; - private CollectionDeepObserver _xObserver; - private CollectionDeepObserver _yObserver; - private CollectionDeepObserver> _sectionsObserver; + private readonly CollectionDeepObserver _seriesObserver; + private readonly CollectionDeepObserver _xObserver; + private readonly CollectionDeepObserver _yObserver; + private readonly CollectionDeepObserver> _sectionsObserver; + private readonly RectangleGeometry _zoomingSection = new(); #endregion @@ -299,10 +302,23 @@ protected override void InitializeCore() { if (canvas is null) throw new Exception("canvas not found"); + var zoomingSection = new RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore, zoomingSection); legend = Template.FindName("legend", this) as IChartLegend; tooltip = Template.FindName("tooltip", this) as IChartTooltip; + + + core.Update(); } @@ -328,13 +344,13 @@ private void OnMouseDown(object sender, System.Windows.Input.MouseButtonEventArg { _ = CaptureMouse(); var p = e.GetPosition(this); - core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y)); + core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), e.ChangedButton == MouseButton.Right); } 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)); + core?.InvokePointerUp(new LvcPoint((float)p.X, (float)p.Y), e.ChangedButton == MouseButton.Right); ReleaseMouseCapture(); } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsCore.SkiaSharpView.WPF.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsCore.SkiaSharpView.WPF.csproj index a54060cb8..73ff10f2c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsCore.SkiaSharpView.WPF.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/LiveChartsCore.SkiaSharpView.WPF.csproj @@ -1,4 +1,4 @@ - + enable @@ -7,7 +7,7 @@ net462;netcoreapp3.1 LiveChartsCore.SkiaSharpView.WPF LiveChartsCore.SkiaSharpView.WPF - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for WPF. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/PieChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/PieChart.cs index 858a84981..2c7f65839 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/PieChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/PieChart.cs @@ -26,6 +26,7 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Windows; +using System.Windows.Input; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; using LiveChartsCore.Kernel.Sketches; @@ -157,6 +158,6 @@ protected override void OnUnloaded() private void OnMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { var p = e.GetPosition(this); - core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y)); + core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), e.ChangedButton == MouseButton.Right); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/PolarChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/PolarChart.cs index 14e24f402..febdf2ac8 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/PolarChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WPF/PolarChart.cs @@ -26,6 +26,7 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Windows; +using System.Windows.Input; using LiveChartsCore.Drawing; using LiveChartsCore.Kernel; using LiveChartsCore.Kernel.Sketches; @@ -285,13 +286,13 @@ private void OnMouseDown(object sender, System.Windows.Input.MouseButtonEventArg { _ = CaptureMouse(); var p = e.GetPosition(this); - core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y)); + core?.InvokePointerDown(new LvcPoint((float)p.X, (float)p.Y), e.ChangedButton == MouseButton.Right); } 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)); + core?.InvokePointerUp(new LvcPoint((float)p.X, (float)p.Y), e.ChangedButton == MouseButton.Right); ReleaseMouseCapture(); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/CartesianChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/CartesianChart.cs index a386f9409..ae2e93c7e 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/CartesianChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/CartesianChart.cs @@ -31,6 +31,8 @@ using LiveChartsCore.Kernel.Sketches; using LiveChartsCore.Measure; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; +using LiveChartsCore.SkiaSharpView.Painting; namespace LiveChartsCore.SkiaSharpView.WinForms; @@ -172,8 +174,18 @@ public DrawMarginFrame? DrawMarginFrame /// protected override void InitializeCore() { + var zoomingSection = new RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(motionCanvas.CanvasCore, zoomingSection); + motionCanvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, motionCanvas.CanvasCore, true); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, motionCanvas.CanvasCore, zoomingSection, true); if (((IChartView)this).DesignerMode) return; core.Update(); } @@ -209,11 +221,11 @@ private void OnMouseWheel(object? sender, MouseEventArgs e) private void OnMouseDown(object? sender, MouseEventArgs e) { - core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y), e.Button == MouseButtons.Right); } private void OnMouseUp(object? sender, MouseEventArgs e) { - core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y), e.Button == MouseButtons.Right); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsCore.SkiaSharpView.WinForms.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsCore.SkiaSharpView.WinForms.csproj index 3e185bba2..4e1eb2839 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsCore.SkiaSharpView.WinForms.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/LiveChartsCore.SkiaSharpView.WinForms.csproj @@ -9,7 +9,7 @@ net462;netcoreapp3.1 LiveChartsCore.SkiaSharpView.WinForms LiveChartsCore.SkiaSharpView.WinForms - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for WindowsForms. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/MotionCanvas.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/MotionCanvas.cs index 53ef15125..76aacb197 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/MotionCanvas.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/MotionCanvas.cs @@ -48,7 +48,6 @@ public partial class MotionCanvas : UserControl public MotionCanvas() { InitializeComponent(); - CanvasCore.Invalidated += CanvasCore_Invalidated; } /// @@ -91,6 +90,13 @@ protected override void OnParentChanged(EventArgs e) base.OnParentChanged(e); } + /// + protected override void CreateHandle() + { + base.CreateHandle(); + CanvasCore.Invalidated += CanvasCore_Invalidated; + } + /// protected override void OnHandleDestroyed(EventArgs e) { diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/PieChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/PieChart.cs index 7e7d7fec5..64fea2698 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/PieChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/PieChart.cs @@ -110,6 +110,6 @@ protected override void InitializeCore() private void OnMouseDown(object? sender, MouseEventArgs e) { - core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y), false); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/PolarChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/PolarChart.cs index 251e751fc..1f683cfcf 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/PolarChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.WinForms/PolarChart.cs @@ -217,11 +217,11 @@ private void OnMouseWheel(object? sender, MouseEventArgs e) private void OnMouseDown(object? sender, MouseEventArgs e) { - core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y), false); } private void OnMouseUp(object? sender, MouseEventArgs e) { - core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y), false); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/CartesianChart.xaml.cs index 761ecd66f..cc53d8772 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/CartesianChart.xaml.cs @@ -33,6 +33,8 @@ using LiveChartsCore.Measure; using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; +using LiveChartsCore.SkiaSharpView.Painting; using LiveChartsCore.SkiaSharpView.XamarinForms; using SkiaSharp.Views.Forms; using Xamarin.Essentials; @@ -771,8 +773,18 @@ void IChartView.InvokeOnUIThread(Action action) /// protected void InitializeCore() { + var zoomingSection = new RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore, zoomingSection); core.Update(); } @@ -886,7 +898,7 @@ private void OnSkCanvasTouched(object? sender, SKTouchEventArgs e) if (core is null) return; var location = new LvcPoint(e.Location.X, e.Location.Y); - core.InvokePointerDown(location); + core.InvokePointerDown(location, false); core.InvokePointerMove(location); Touched?.Invoke(this, e); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj index 486329f01..7a22729d5 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/LiveChartsCore.SkiaSharpView.Xamarin.Forms.csproj @@ -6,7 +6,7 @@ netstandard2.0; LiveChartsCore.SkiaSharpView.XamarinForms LiveChartsCore.SkiaSharpView.XamarinForms - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for XamarinForms. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/PieChart.xaml.cs index 9e7bbc187..2e1fce041 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/PieChart.xaml.cs @@ -708,7 +708,7 @@ private void OnSkCanvasTouched(object? sender, SKTouchEventArgs e) if (core is null) return; var location = new LvcPoint(e.Location.X, e.Location.Y); - core.InvokePointerDown(location); + core.InvokePointerDown(location, false); core.InvokePointerMove(location); Touched?.Invoke(this, e); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/PolarChart.xaml.cs index 762dc7467..5581dbbfa 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp.Xamarin.Forms/PolarChart.xaml.cs @@ -819,7 +819,7 @@ private void OnSkCanvasTouched(object? sender, SKTouchEventArgs e) if (core is null) return; var location = new LvcPoint(e.Location.X, e.Location.Y); - core.InvokePointerDown(location); + core.InvokePointerDown(location, false); core.InvokePointerMove(location); Touched?.Invoke(this, e); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/DoughnutGeometry.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/DoughnutGeometry.cs index 9262611d7..b0ed7a61f 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/DoughnutGeometry.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/DoughnutGeometry.cs @@ -136,7 +136,7 @@ public override void OnDraw(SkiaSharpDrawingContext context, SKPaint paint) (float)(cx + Math.Cos((sweepAngle + startAngle) * toRadians) * wedge), (float)(cy + Math.Sin((sweepAngle + startAngle) * toRadians) * wedge)); path.ArcTo( - new SKPoint { X = wedge + pushout, Y = wedge + pushout }, + new SKPoint { X = wedge, Y = wedge }, 0, sweepAngle > 180 ? SKPathArcSize.Large : SKPathArcSize.Small, SKPathDirection.CounterClockwise, diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/LiveChartsCore.SkiaSharpView.csproj b/src/skiasharp/LiveChartsCore.SkiaSharp/LiveChartsCore.SkiaSharpView.csproj index 2d2b40c47..6a7dd1d74 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/LiveChartsCore.SkiaSharpView.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/LiveChartsCore.SkiaSharpView.csproj @@ -17,7 +17,7 @@ LiveChartsCore.SkiaSharpView LiveChartsCore.SkiaSharpView - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for .Net, this package contains the SkiaSharp backend. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKCartesianChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKCartesianChart.cs index d15e48dfa..73750c536 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKCartesianChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKCartesianChart.cs @@ -30,6 +30,7 @@ using LiveChartsCore.Measure; using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; using SkiaSharp; namespace LiveChartsCore.SkiaSharpView.SKCharts; @@ -55,7 +56,7 @@ public SKCartesianChart() initializer.ApplyStyleToChart(this); Core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, CoreCanvas); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, CoreCanvas, new RectangleGeometry()); Core.Measuring += OnCoreMeasuring; Core.UpdateStarted += OnCoreUpdateStarted; Core.UpdateFinished += OnCoreUpdateFinished; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharp/SkiaSharpProvider.cs b/src/skiasharp/LiveChartsCore.SkiaSharp/SkiaSharpProvider.cs index 2c96333a3..fa3912ad0 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharp/SkiaSharpProvider.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharp/SkiaSharpProvider.cs @@ -30,28 +30,28 @@ namespace LiveChartsCore.SkiaSharpView; -/// -public class SkiaSharpProvider : ChartProvider +/// +public class SkiaSharpProvider : ChartEngine { - /// + /// public override IMapFactory GetDefaultMapFactory() { return new MapFactory(); } - /// + /// public override ICartesianAxis GetDefaultCartesianAxis() { return new Axis(); } - /// + /// public override IPolarAxis GetDefaultPolarAxis() { return new PolarAxis(); } - /// + /// public override IPaint GetSolidColorPaint(LvcColor color) { return new SolidColorPaint(new SKColor(color.R, color.G, color.B, color.A)); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/CartesianChart.razor.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/CartesianChart.razor.cs index 8e7b90bfa..a4cb3f599 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/CartesianChart.razor.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/CartesianChart.razor.cs @@ -28,6 +28,8 @@ using LiveChartsCore.Kernel.Sketches; using LiveChartsCore.Measure; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; +using LiveChartsCore.SkiaSharpView.Painting; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; @@ -182,8 +184,18 @@ protected override void InitializeCore() { if (motionCanvas is null) throw new Exception("MotionCanvas component was not found"); + var zoomingSection = new RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(motionCanvas.CanvasCore, zoomingSection); + motionCanvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, motionCanvas.CanvasCore); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, motionCanvas.CanvasCore, zoomingSection); if (((IChartView)this).DesignerMode) return; core.Update(); } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor index 885c03b80..766b40562 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor @@ -29,7 +29,7 @@ blazor bug? --> -
+
@@ -40,7 +40,7 @@ OnPointerDownCallback="OnPointerDown" OnPointerMoveCallback="OnPointerMove" OnPointerUpCallback="OnPointerUp" - OnPointerLeaveCallback="OnPointerLeave" + OnPointerOutCallback="OnPointerOut" OnWheelCallback="OnWheel">
diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor.cs index de2867ec3..1a949ef14 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor.cs @@ -306,7 +306,7 @@ private void OnCoreMeasuring(IChartView chart) /// protected virtual void OnPointerDown(PointerEventArgs e) { - core?.InvokePointerDown(new LvcPoint((float)e.OffsetX, (float)e.OffsetY)); + core?.InvokePointerDown(new LvcPoint((float)e.OffsetX, (float)e.OffsetY), e.Button == 2); _ = OnPointerDownCallback.InvokeAsync(e); } @@ -326,7 +326,7 @@ protected virtual void OnPointerMove(PointerEventArgs e) /// protected virtual void OnPointerUp(PointerEventArgs e) { - core?.InvokePointerUp(new LvcPoint((float)e.OffsetX, (float)e.OffsetY)); + core?.InvokePointerUp(new LvcPoint((float)e.OffsetX, (float)e.OffsetY), e.Button == 2); _ = OnPointerUpCallback.InvokeAsync(e); } @@ -345,7 +345,7 @@ protected virtual void OnDisposing() { } /// Called when the pointer leaves the control. ///
/// - protected virtual void OnPointerLeave(PointerEventArgs e) + protected virtual void OnPointerOut(PointerEventArgs e) { HideTooltip(); core?.InvokePointerLeft(); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor.css b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor.css index 88b24c328..8645b108a 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor.css +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/Chart.razor.css @@ -1,8 +1,17 @@ -::deep canvas { +::deep.lvc-content { + height: 100%; + width: 100%; +} + +::deep canvas { + height: 100%; width: 100%; } ::deep .lvc-chart-container { + height: 100%; + width: 100%; + display: -ms-flexbox; display: -webkit-flex; display: flex; @@ -45,7 +54,9 @@ } ::deep .lvc-canvas-container { + height: 100%; width: 100%; + -webkit-order: 0; -ms-flex-order: 0; order: 0; diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveChartsCore.SkiaSharpView.Blazor.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveChartsCore.SkiaSharpView.Blazor.csproj index b634db37f..0aac1770c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveChartsCore.SkiaSharpView.Blazor.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/LiveChartsCore.SkiaSharpView.Blazor.csproj @@ -17,7 +17,7 @@ net6.0 enable enable - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for Blazor. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/MotionCanvas.razor b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/MotionCanvas.razor index bdaed0f2a..f424fa192 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/MotionCanvas.razor +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/MotionCanvas.razor @@ -40,7 +40,7 @@ @onpointerdown="OnPointerDown" @onpointermove="OnPointerMove" @onpointerup="OnPointerUp" - @onpointerleave="OnPointerLeave" + @onpointerout="OnPointerOut" @onmousewheel="OnWheel"> } @@ -52,7 +52,7 @@ else @onpointerdown="OnPointerDown" @onpointermove="OnPointerMove" @onpointerup="OnPointerUp" - @onpointerleave="OnPointerLeave" + @onpointerout="OnPointerOut" @onmousewheel="OnWheel" > } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/MotionCanvas.razor.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/MotionCanvas.razor.cs index ecf0a2f6a..d8b5e7e24 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/MotionCanvas.razor.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/MotionCanvas.razor.cs @@ -106,7 +106,7 @@ public List> PaintTasks /// Gets or sets the pointer leave callback. ///
[Parameter] - public EventCallback OnPointerLeaveCallback { get; set; } + public EventCallback OnPointerOutCallback { get; set; } /// /// Called when the pointer goes down. @@ -145,12 +145,12 @@ protected virtual void OnWheel(WheelEventArgs e) } /// - /// Called when the pointer leves the control. + /// Called when the pointer leaves the control. /// /// - protected virtual void OnPointerLeave(PointerEventArgs e) + protected virtual void OnPointerOut(PointerEventArgs e) { - _ = OnPointerLeaveCallback.InvokeAsync(e); + _ = OnPointerOutCallback.InvokeAsync(e); } private void OnPaintGlSurface(SKPaintGLSurfaceEventArgs e) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/CartesianChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/CartesianChart.cs index 73e6b1f7d..ac7243097 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/CartesianChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/CartesianChart.cs @@ -31,6 +31,8 @@ using LiveChartsCore.Kernel.Sketches; using LiveChartsCore.Measure; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; +using LiveChartsCore.SkiaSharpView.Painting; namespace LiveChartsCore.SkiaSharpView.Eto; @@ -164,8 +166,18 @@ public DrawMarginFrame? DrawMarginFrame /// protected override void InitializeCore() { + var zoomingSection = new RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(motionCanvas.CanvasCore, zoomingSection); + motionCanvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, motionCanvas.CanvasCore, true); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, motionCanvas.CanvasCore, zoomingSection, true); core.Update(); } @@ -213,11 +225,11 @@ private void OnMouseWheel(object? sender, MouseEventArgs e) private void OnMouseDown(object? sender, MouseEventArgs e) { - core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y), e.Buttons == MouseButtons.Alternate); } private void OnMouseUp(object? sender, MouseEventArgs e) { - core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y), e.Buttons == MouseButtons.Alternate); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsCore.SkiaSharpView.Eto.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsCore.SkiaSharpView.Eto.csproj index 81db5e525..7bdafac65 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsCore.SkiaSharpView.Eto.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/LiveChartsCore.SkiaSharpView.Eto.csproj @@ -7,7 +7,7 @@ netstandard2.0 LiveChartsCore.SkiaSharpView.Eto LiveChartsCore.SkiaSharpView.Eto - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for Eto.Forms. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/PieChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/PieChart.cs index a71d0ce1f..de3e03f49 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/PieChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/PieChart.cs @@ -114,6 +114,6 @@ protected override void OnUnloading() private void OnMouseDown(object? sender, MouseEventArgs e) { - core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y), false); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/PolarChart.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/PolarChart.cs index f7badd618..ff9e73293 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/PolarChart.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Eto/PolarChart.cs @@ -220,11 +220,11 @@ private void OnMouseWheel(object? sender, MouseEventArgs e) private void OnMouseDown(object? sender, MouseEventArgs e) { - core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerDown(new LvcPoint(e.Location.X, e.Location.Y), false); } private void OnMouseUp(object? sender, MouseEventArgs e) { - core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y)); + core?.InvokePointerUp(new LvcPoint(e.Location.X, e.Location.Y), false); } } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs index 2d0bf9446..f461b1a12 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/CartesianChart.xaml.cs @@ -34,6 +34,8 @@ using LiveChartsCore.Measure; using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; +using LiveChartsCore.SkiaSharpView.Painting; using Microsoft.Maui; using Microsoft.Maui.ApplicationModel; using Microsoft.Maui.Controls; @@ -772,8 +774,18 @@ void IChartView.InvokeOnUIThread(Action action) /// protected void InitializeCore() { + var zoomingSection = new RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore, zoomingSection); core.Update(); } @@ -894,7 +906,7 @@ private void OnSkCanvasTouched(object? sender, SKTouchEventArgs e) if (core is null) return; var location = new LvcPoint(e.Location.X, e.Location.Y); - core.InvokePointerDown(location); + core.InvokePointerDown(location, false); core.InvokePointerMove(location); Touched?.Invoke(this, e); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj index 9f6f87250..99b700148 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.csproj @@ -14,7 +14,7 @@ 10.0.17763.0 10.0.17763.0 - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for Maui. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.nuspec b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.nuspec index 584e533d1..76aa350b8 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.nuspec +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/LiveChartsCore.SkiaSharpView.Maui.nuspec @@ -2,7 +2,7 @@ LiveChartsCore.SkiaSharpView.Maui - 2.0.0-beta.350 + 2.0.0-beta.360 LiveChartsCore.SkiaSharpView.Maui BetoRodriguez true @@ -17,23 +17,23 @@ - + - + - + - + - + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs index c1f5e77ae..d7070e17c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PieChart.xaml.cs @@ -705,7 +705,7 @@ private void OnSkCanvasTouched(object? sender, SKTouchEventArgs e) if (core is null) return; var location = new LvcPoint(e.Location.X, e.Location.Y); - core.InvokePointerDown(location); + core.InvokePointerDown(location, false); core.InvokePointerMove(location); Touched?.Invoke(this, e); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs index 61deed5d1..87cdfa3a1 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Maui/PolarChart.xaml.cs @@ -815,7 +815,7 @@ private void OnSkCanvasTouched(object? sender, SKTouchEventArgs e) if (core is null) return; var location = new LvcPoint(e.Location.X, e.Location.Y); - core.InvokePointerDown(location); + core.InvokePointerDown(location, false); core.InvokePointerMove(location); Touched?.Invoke(this, e); diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs index 74bc281f4..422804291 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/CartesianChart.xaml.cs @@ -41,6 +41,8 @@ using Microsoft.UI.Xaml.Media; using LiveChartsCore.SkiaSharpView.Uno.WinUI.Helpers; using Windows.UI.Text; +using LiveChartsCore.SkiaSharpView.Painting; +using Microsoft.UI.Input; // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 @@ -885,8 +887,18 @@ private void OnLoaded(object sender, RoutedEventArgs e) if (_core is null) { + var zoomingSection = new Drawing.Geometries.RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + _core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore, zoomingSection); if (SyncContext != null) _motionCanvas.CanvasCore.Sync = SyncContext; @@ -957,7 +969,13 @@ 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)); + var isRight = false; + if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) + { + var properties = e.GetCurrentPoint(this).Properties; + isRight = properties.IsRightButtonPressed; + } + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); } private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) @@ -971,7 +989,13 @@ private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) private void OnPointerReleased(object? sender, PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + var isRight = false; + if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) + { + var properties = e.GetCurrentPoint(this).Properties; + isRight = properties.IsRightButtonPressed; + } + _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); ReleasePointerCapture(e.Pointer); } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj index 457c1ece3..07026f72e 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/LiveChartsCore.SkiaSharpView.Uno.WinUI.csproj @@ -1,4 +1,4 @@ - + net6.0-windows10.0.18362;netstandard2.0;net6.0-ios;net6.0-macos;net6.0-maccatalyst;net6.0-android @@ -6,7 +6,7 @@ enable 10.0 - 2.0.0-beta.350 + 2.0.0-beta.360 icon.png Simple, flexible, interactive and powerful data visualization for Uno.WinUI. MIT diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs index 03672d384..906f470f1 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PieChart.xaml.cs @@ -790,7 +790,7 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e) private void OnPointerPressed(object sender, PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); } private void OnPointerMoved(object sender, PointerRoutedEventArgs e) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs index bfa0d7c89..765516c33 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno.WinUI/PolarChart.xaml.cs @@ -910,13 +910,13 @@ private void OnPointerExited(object sender, PointerRoutedEventArgs e) private void OnPointerReleased(object sender, PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); } private void OnPointerPressed(object sender, PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); } private void OnWheelChanged(object sender, PointerRoutedEventArgs e) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/CartesianChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/CartesianChart.xaml.cs index 96e3fe00c..257d82fbf 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/CartesianChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/CartesianChart.xaml.cs @@ -34,7 +34,9 @@ using LiveChartsCore.Measure; using LiveChartsCore.Motion; using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Painting; using LiveChartsCore.SkiaSharpView.Uno.Helpers; +using Windows.Devices.Input; using Windows.UI.Text; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -884,8 +886,18 @@ private void OnLoaded(object sender, RoutedEventArgs e) if (_core is null) { + var zoomingSection = new Drawing.Geometries.RectangleGeometry(); + var zoomingSectionPaint = new SolidColorPaint + { + IsFill = true, + Color = new SkiaSharp.SKColor(33, 150, 243, 50), + ZIndex = int.MaxValue + }; + zoomingSectionPaint.AddGeometryToPaintTask(canvas.CanvasCore, zoomingSection); + canvas.CanvasCore.AddDrawableTask(zoomingSectionPaint); + _core = new CartesianChart( - this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore); + this, LiveChartsSkiaSharp.DefaultPlatformBuilder, canvas.CanvasCore, zoomingSection); if (SyncContext != null) _motionCanvas.CanvasCore.Sync = SyncContext; @@ -956,7 +968,15 @@ 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)); + + var isRight = false; + if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) + { + var properties = e.GetCurrentPoint(this).Properties; + isRight = properties.IsRightButtonPressed; + } + + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); } private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) @@ -970,7 +990,15 @@ private void OnPointerMoved(object? sender, PointerRoutedEventArgs e) private void OnPointerReleased(object? sender, PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + + var isRight = false; + if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) + { + var properties = e.GetCurrentPoint(this).Properties; + isRight = properties.IsRightButtonPressed; + } + + _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), isRight); ReleasePointerCapture(e.Pointer); } diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/LiveChartsCore.SkiaSharpView.Uno.csproj b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/LiveChartsCore.SkiaSharpView.Uno.csproj index 4b066759c..408b942da 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/LiveChartsCore.SkiaSharpView.Uno.csproj +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.Uno/LiveChartsCore.SkiaSharpView.Uno.csproj @@ -1,4 +1,4 @@ - + - - + + diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/PieChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/PieChart.xaml.cs index d76a4cfc9..9c18b466c 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/PieChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/PieChart.xaml.cs @@ -827,13 +827,13 @@ private void OnPointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoute private void OnPointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); } private void OnPointerReleased(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); } private void OnUnloaded(object sender, RoutedEventArgs e) diff --git a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/PolarChart.xaml.cs b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/PolarChart.xaml.cs index 9cd826985..e9f49136b 100644 --- a/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/PolarChart.xaml.cs +++ b/src/skiasharp/LiveChartsCore.SkiaSharpView.WinUI/PolarChart.xaml.cs @@ -914,13 +914,13 @@ private void OnPointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoute private void OnPointerReleased(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerUp(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); } private void OnPointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) { var p = e.GetCurrentPoint(this); - _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y)); + _core?.InvokePointerDown(new LvcPoint((float)p.Position.X, (float)p.Position.Y), false); } private void OnWheelChanged(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)