Skip to content

Commit

Permalink
Merge pull request #1811 from beto-rodriguez/dev
Browse files Browse the repository at this point in the history
RC 5.2
  • Loading branch information
beto-rodriguez authored Feb 17, 2025
2 parents fc8320b + d3e1f3f commit 937a814
Show file tree
Hide file tree
Showing 73 changed files with 874 additions and 584 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,3 @@ nuget.exe
# https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/strong-naming#create-strong-named-net-libraries
*LiveCharts.snk
build/pack.singed.ps1
/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/wwwroot/domInterop.js
/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/wwwroot/domInterop.js.map
/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/domInterop.js
/src/skiasharp/LiveChartsCore.SkiaSharpView.Blazor/domInterop.js.map
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>

<LiveChartsVersion>2.0.0-rc5.1</LiveChartsVersion>
<LiveChartsVersion>2.0.0-rc5.2</LiveChartsVersion>
<LiveChartsAuthors>BetoRodriguez</LiveChartsAuthors>

<GlobalLangVersion>12.0</GlobalLangVersion>
Expand Down
18 changes: 17 additions & 1 deletion build/pack.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ class Project {
[string]GetFolder() {
return $this.src.SubString(0, $this.src.LastIndexOf("/"));
}

[string]GetName() {
$end = $this.src.LastIndexOf("/")
return $this.src.SubString($end + 1, $this.src.Length - $end - 1);
}
}

if (Test-Path $nupkgOutputPath) {
Expand All @@ -36,10 +41,21 @@ if (Test-Path $nupkgOutputPath) {

foreach ($p in $projects) {
$folder = $p.GetFolder()
$name = $p.GetName()

if (Test-Path $($folder + "/bin")) {
Remove-Item $($folder + "/bin") -Force -Recurse
}

dotnet pack $p.src -o $nupkgOutputPath -c $configuration -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
$expression = "dotnet pack $($p.src) -o $nupkgOutputPath -c $configuration -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg"

Write-Progress -Activity "$name" -Status "Packing..."
$result = Invoke-Expression $expression

if ($LASTEXITCODE -ne 0) {
Write-Output "$name failed to pack."
break
}else {
Write-Output "$name packed successfully."
}
}
Binary file modified docs/_assets/legend-custom-template.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_assets/tooltip-custom-template.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 0 additions & 4 deletions docs/samples/axes/customSeparatorsInterval/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
{{ full_name | get_vm_from_docs }}
```

## LogarithmicPoint.cs

{{~ "~/../samples/ViewModelsSamples/Axes/Logarithmic/LogarithmicPoint.cs" | render_file_as_code ~}}

{{~ if xaml ~}}
## XAML
{{~ end ~}}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 27 additions & 1 deletion docs/samples/axes/matchScale/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,30 @@ Once we run our app again, we can see that our scale works as expected:
<img src="{{ assets_url }}/docs/{{ unique_name }}/doubley.png" alt="sample image" />
</div>

{{ render this "~/shared/relatedTo.md" }}
## Scale separators to 1 inch sample

In the following example, we will force the axis separators to be 1 inch long (2.54 cm).

{{~ render_params_file_as_code this "~/../samples/ViewModelsSamples/Axes/MatchScale/InchScaleExtensions.cs" ~}}

:::tip
The `GetPixelsPerInch()` function, returns always `96`, this is a standard value, but varies depending on the screen,
and the OS, in a real app you must get the device DPI/PPI, this differs between UI frameworks, please check the
docs of your target UI framework.
:::

Finally we need to use our `InchSeparator()` extension in our chart:

```c#
// where myChart is a reference to chart in the UI.
InchScaleExtensions.InchSeparator(myChart);
```

And that's it, now our separators will be one inch long always, no matter the chart size, the data on it, or the zooming
and panning level.

<div class="text-center">
<img src="{{ assets_url }}/docs/{{ unique_name }}/inch-long-separator.jpg" alt="sample image" style="max-width: 650px" />
</div>

{{ render this "~/shared/relatedTo.md" }}
29 changes: 21 additions & 8 deletions docs/samples/general/customLegends/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ You can quickly change the position, the font, the text size or the background c
{{~ render_params_file_as_code this "~/../samples/BlazorSample/Pages/Axes/Multiple.razor" ~}}
{{~ end ~}}

## View model
#### View model

```c#
[ObservableObject]
Expand All @@ -41,18 +41,31 @@ public partial class ViewModel

![custom]({{ assets_url }}/docs/_assets/legend-custom-style.png)

## Legend control from scratch
# Override the default legend behavior

You can also create your own legend, the recommended way is to use the LiveCharts API (example bellow) but you can
use anything as legend as soon as it implements the `IChartLegend<T>` interface. At the following example we build
a custom control to render legends in our charts using the LiveCharts API.
You can inherit from `SKDefaultLegend` and override the `GetLayout()` method to define your own template,
in the next example we set a larger miniature compared with the default size.

## CustomLegend.cs
#### CustomLegend.cs

{{~ render_params_file_as_code this "~/../samples/ViewModelsSamples/General/TemplatedLegends/CustomLegend.cs" ~}}

## View
#### LegendItem.cs

{{~ render_params_file_as_code this "~/../samples/ViewModelsSamples/General/TemplatedLegends/LegendItem.cs" ~}}

#### View

{{~ render_params_file_as_code this "~/../samples/$PlatformSamplesFolder/General/TemplatedLegends/$PlatformViewFile" ~}}

![custom legend]({{ assets_url }}/docs/_assets/legend-custom-template.png)
![custom legend]({{ assets_url }}/docs/_assets/legend-custom-template.png)

# Legend control from scratch

You can also create your own legend, the recommended way is to use the LiveCharts API but you can
use anything as legend as soon as it implements the `IChartLegend` interface; You can use the [SKDefaultLegend source code](https://github.com/beto-rodriguez/LiveCharts2/blob/master/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultLegend.cs) as a guide to build your own implementation, this class is the default legend used by the library.

Instead of using the LiveCharts API you can use your UI framework,
see [#1558](https://github.com/beto-rodriguez/LiveCharts2/issues/1558) for more info, in that ticket, there is an example
that implements the `IChartTooltip` interface on a WPF control, then LiveCharts uses this WPF control as the tooltip, even
that example implements `IChartTooltip`, there are no big differences from creating a control that implements `IChartLegend`.
26 changes: 14 additions & 12 deletions docs/samples/general/customTooltips/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,12 @@ Will result in:
The PieSeries class uses the `ToolTipLabelFormatter` property to configure the text inside the tooltip.
:::

# Tooltip control from scratch

You can also create your own tooltip, the recommended way is to use the LiveCharts API (example bellow) but you can
use anything as tooltip as soon as it implements the `IChartTooltip<T>` interface. AT the following example we build
a custom control to render tooltips in our charts using the LiveCharts API.
# Override the default tooltip behavior

:::tip
The next tooltip is drawn by the library, LiveCharts can only draw inside the control bounds, in some cases it could
cause issues like [#912](https://github.com/beto-rodriguez/LiveCharts2/issues/912).
You can also inherit from `SKDefaultTooltip` and override the parts you need to make the tooltip behave as your app needs,
in the next example, we draw a geometry in the tooltip based on the point that is shown in the tooltip.

Alternatively, you can build your own Tooltips and use the power of your UI framework,
see [#1558](https://github.com/beto-rodriguez/LiveCharts2/issues/1558) for more info.
:::
![custom tooltip]({{ assets_url }}/docs/_assets/tooltip-custom-template.gif)

#### CustomTooltip.cs

Expand All @@ -188,7 +181,16 @@ see [#1558](https://github.com/beto-rodriguez/LiveCharts2/issues/1558) for more

{{~ render_params_file_as_code this "~/../samples/$PlatformSamplesFolder/General/TemplatedTooltips/$PlatformViewFile" ~}}

![custom tooltip]({{ assets_url }}/docs/_assets/tooltip-custom-template.gif)
# Tooltip control from scratch

You can also create your own tooltip, the recommended way is to use the LiveCharts API but you can
use anything as tooltip as soon as it implements the `IChartTooltip` interface.

The LiveCharts API can only draw inside the control bounds, in some cases it could
cause issues like [#912](https://github.com/beto-rodriguez/LiveCharts2/issues/912), you can use the [SKDefaultTooltip source code](https://github.com/beto-rodriguez/LiveCharts2/blob/master/src/skiasharp/LiveChartsCore.SkiaSharp/SKCharts/SKDefaultTooltip.cs) as a guide to build your own implementation, this class is the default tooltip used by the library.

Alternatively, you can build your own Tooltips and use the power of your UI framework,
see [#1558](https://github.com/beto-rodriguez/LiveCharts2/issues/1558) for more info.

# Override Series.FindPointsInPosition

Expand Down
2 changes: 1 addition & 1 deletion docs/samples/general/drawOnCanvas/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
This article adds geometries directly to the canvas, this is intended to explain how geometries and animations
are handled in the library, but in general the recommended way to draw a custom element in the chart is to use the
`Visual` class, for more info please see the [visual elements article](https://livecharts.dev/docs/{{ platform }}/{{ version }}/samples.general.visualElements).
::
:::

{{ render this "~/shared/genericSampleJustGifHeader.md" }}

Expand Down
Binary file added docs/samples/pies/angularGauge/needle-rect.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 98 additions & 1 deletion docs/samples/pies/angularGauge/template.md
Original file line number Diff line number Diff line change
@@ -1 +1,98 @@
{{ render this "~/shared/genericSampleJustGif.md" }}
{{ render this "~/shared/genericSampleJustGifHeader.md" }}

#### View model

```
{{ full_name | get_vm_from_docs }}
```

{{~ if xaml ~}}
#### XAML
{{~ end ~}}

{{~ if winforms ~}}
#### Form code behind
{{~ end ~}}

{{~ if blazor~}}
#### HTML
{{~ end~}}

```
{{ full_name | get_view_from_docs }}
```

# Custom needle

You can inherit from `NeedleGeometry` to change the aspect of the needle, for example in the next code snippet,
the `SmallNeedle` class inherits from `NeedleGeometry`, then in the constructor it sets the `ScaleTransform`
property to `0.6` in the `X` and `Y` axis, this will make the needle 40% smaller.

{{~ render_params_file_as_code this "~/../samples/ViewModelsSamples/Pies/AngularGauge/SmallNeedle.cs" ~}}

Finally we need to use this new needle in our gauge, in the example above change the type `NeedleVisual`
to `NeedleVisual<SmallNeedle>`.

```c#
public partial class ViewModel
{
// ...
public NeedleVisual<SmallNeedle> Needle { get; set; }

public ViewModel()
{
Needle = new NeedleVisual<SmallNeedle>
{
Value = 45
};

// ...
}

// ...
}
```

Run the app again, now the needle is 40% smaller.

You can also override the `Draw()` method and use SkiaSharp to create your own needle, in the next snippet,
we are drawing a rectangle using SkiaSharp to represent the needle:

{{~ render_params_file_as_code this "~/../samples/ViewModelsSamples/Pies/AngularGauge/CustomNeedle.cs" ~}}

Finally we need to use this new needle in our gauge:"

```c#
public partial class ViewModel
{
// ...
public NeedleVisual<CustomNeedle> Needle { get; set; }

public ViewModel()
{
Needle = new NeedleVisual<CustomNeedle>
{
Value = 45
};

// ...
}

// ...
}
```

Run the app again, now there is a rectangle as our needle:

<div class="text-center">
<img src="{{ assets_url }}/docs/{{ unique_name }}/needle-rect.png" alt="sample image" />
</div>

:::tip
You can draw anything with SkiaSharp, this article does not explain how to do it.
If you need help, you can see the default [NeedleGeometry source code](https://github.com/beto-rodriguez/LiveCharts2/blob/master/src/skiasharp/LiveChartsCore.SkiaSharp/Drawing/Geometries/NeedleGeometry.cs), or you can follow any SkiaSharp guide.
:::

{{ render this "~/shared/relatedTo.md" }}
63 changes: 63 additions & 0 deletions samples/ViewModelsSamples/Axes/MatchScale/InchScaleExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using LiveChartsCore;
using LiveChartsCore.Drawing;
using LiveChartsCore.Kernel.Sketches;

namespace ViewModelsSamples.Axes.MatchScale;

public static class InchScaleExtensions
{
// the DrawMarginDefined event is called once the chart // mark
// has defined the area where the series will be drawn // mark
// ignoring the axes, titles, and legends // mark
// this is where we modify the axes limits to define our custom scale // mark
public static void InchSeparator(this ICartesianChartView chart) =>
((CartesianChartEngine)chart.CoreChart).DrawMarginDefined += OnDrawMarginDefined;

// we will force the axis step to be 1 inch long // mark
private static void OnDrawMarginDefined(CartesianChartEngine chart)
{
var dataPerInch = GetDataPerInch((ICartesianChartView)chart.View);

// knowing the data per inch, we can set an step that will, in this case 1 inch
var inches = 1d;

var x = chart.XAxes[0];
var xMin = x.MinLimit ?? x.DataBounds.Min;
var xMax = x.MaxLimit ?? x.DataBounds.Max;
var xStep = inches * dataPerInch.X;

x.SetLimits(xMin, xMax, xStep, notify: false);

var y = chart.YAxes[0];
var yMin = y.MinLimit ?? y.DataBounds.Min;
var yMax = y.MaxLimit ?? y.DataBounds.Max;
var yStep = inches * dataPerInch.Y;

y.SetLimits(yMin, yMax, yStep, notify: false);

// it is important to use notify: false // mark
// to avoid the chart to update once we set the limits. // mark
}

private static LvcPointD GetDataPerInch(ICartesianChartView chart)
{
var p0 = chart.ScaleDataToPixels(new(0, 0));
var p1 = chart.ScaleDataToPixels(new(1, 1));

// calculate the distance between 0,0 and 1,1 in pixels
var pux = Math.Abs(p0.X - p1.X);
var puy = Math.Abs(p0.Y - p1.Y);

var ppi = GetPixelsPerInch();

// calculate the data per inch
var dpix = ppi / pux;
var dpiy = ppi / puy;

return new LvcPointD(dpix, dpiy);
}

// this is an example, in a real scenario you should get the screen PPI
private static double GetPixelsPerInch() => 96.0;
}
Loading

0 comments on commit 937a814

Please sign in to comment.