Skip to content

Commit

Permalink
Merge pull request #1056 from beto-rodriguez/dev
Browse files Browse the repository at this point in the history
beta.800
  • Loading branch information
beto-rodriguez authored Jun 12, 2023
2 parents b89e371 + c36864c commit b3cfef4
Show file tree
Hide file tree
Showing 319 changed files with 12,205 additions and 8,854 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -344,4 +344,9 @@ healthchecksdb
samples/XamarinSample/XamarinSample/XamarinSample.Android/XamarinSample.Android.csproj
samples/XamarinSample/XamarinSample/XamarinSample.Android/Resources/Resource.designer.cs
nuget.exe

# Yes it is recommended to share the *.snk, but there are few reasons
# other than the ones mentioned in the next link that makes me want to keep this private, also singed.
# https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/strong-naming#create-strong-named-net-libraries
*LiveCharts.snk
build/pack.singed.ps1
545 changes: 118 additions & 427 deletions LiveCharts.sln

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/pack.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
param([string]$configuration = "Release", [string]$nupkgOutputPath = "./nupkg")
param([string]$configuration = "Debug", [string]$nupkgOutputPath = "./nupkg")

[Project[]]$projects = @(
[Project]::new("./src/LiveChartsCore/LiveChartsCore.csproj")
Expand Down
7 changes: 7 additions & 0 deletions build/pack.singed.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
& $PSScriptRoot\pack.ps1 Release

& dotnet nuget push **/*.nupkg --api-key oy2o6gainuded3gc42sq2gddywqhhhiu3cxtns4lokf5hu --source https://api.nuget.org/v3/index.json --skip-duplicate

## this should only be ran once?
## dotnet nuget add source --username beto-rodriguez --password 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 --store-password-in-clear-text --name github "https://nuget.pkg.github.com/beto-rodriguez/index.json"
& dotnet nuget push **/*.nupkg --api-key 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 --source "github" --skip-duplicate
161 changes: 0 additions & 161 deletions docs/cartesianChart/columnseries.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,165 +180,4 @@ to create backgrounds for columns, take a look at the following sample:
}
};</code></pre>

## Plotting custom types

You can teach LiveCharts to plot anything, imagine the case where we have an array of the `City` class defined bellow:

<pre><code>public class City
{
public string Name { get; set; }
public double Population { get; set; }
public double LandArea { get; set; }
}</code></pre>

You can register this type **globally**, this means that every time LiveCharts finds a `City` instance in a chart
it will use the mapper we registered, global mappers are unique for a type, if you need to plot multiple
properties then you should use local mappers.

<pre><code>// Ideally you should call this when your application starts
// If you need help to decide where to add this code
// please see the installation guide in this docs.

// in this case we have an array of the City class
// we need to compare the Population property of every city in our array

LiveCharts.Configure(config =>
config
.HasMap&lt;City>((city, point) =>
{
// in this lambda function we take an instance of the City class (see city parameter)
// and the point in the chart for that instance (see point parameter)
// LiveCharts will call this method for every instance of our City class array,
// now we need to populate the point coordinates from our City instance to our point

// in this case we will use the Population property as our primary value (normally the Y coordinate)
point.PrimaryValue = (float)city.Population;

// then the secondary value (normally the X coordinate)
// will be the index of city in our cities array
point.SecondaryValue = point.Context.Index;

// but you can use another property of the city class as the X coordinate
// for example lets use the LandArea property to create a plot that compares
// Population and LandArea in chart:

// point.SecondaryValue = (float)city.LandArea;
})
.HasMap&lt;Foo>(...) // you can register more types here using our fluent syntax
.HasMap&lt;Bar>(...)
);</code></pre>

Now we are ready to plot cities all over our application:

<pre><code>Series = new[]
{
new ColumnSeries&lt;City>
{
Name = "Population",
TooltipLabelFormatter = point => $"{point.Model.Name} {point.PrimaryValue:N2}M",
Values = new[]
{
new City { Name = "Tokyo", Population = 4, LandArea = 3 },
new City { Name = "New York", Population = 6, LandArea = 4 },
new City { Name = "Seoul", Population = 2, LandArea = 1 },
new City { Name = "Moscow", Population = 8, LandArea = 7 },
new City { Name = "Shanghai", Population = 3, LandArea = 2 },
new City { Name = "Guadalajara", Population = 4, LandArea = 5 }
}
}
};</code></pre>

![image]({{ assets_url }}/docs/_assets/columnct.png)

Alternatively you could create a **local** mapper that will only work for a specific series, global mappers will be
ignored when the series `Mapping` property is not null.

<pre><code>var cities = new[]
{
new City { Name = "Tokyo", Population = 4, LandArea = 3 },
new City { Name = "New York", Population = 6, LandArea = 4 },
new City { Name = "Seoul", Population = 2, LandArea = 1 },
new City { Name = "Moscow", Population = 8, LandArea = 7 },
new City { Name = "Shanghai", Population = 3, LandArea = 2 },
new City { Name = "Guadalajara", Population = 4, LandArea = 5 }
};

Series = new[]
{
// this series draws the Population property in the Y axis
new ColumnSeries&lt;City>
{
Name = "Population",
TooltipLabelFormatter = (point) => $"{point.Model.Name} population: {point.PrimaryValue:N2}M",
Values = cities,
Mapping = (city, point) =>
{
point.PrimaryValue = (float)city.Population;
point.SecondaryValue = point.Context.Index;
}
},

// draws the LandArea property in the Y axis
new ColumnSeries&lt;City>
{
Name = "Population",
TooltipLabelFormatter = (point) => $"{point.Model.Name} area: {point.PrimaryValue:N2}KM2",
Values = cities,
Mapping = (city, point) =>
{
point.PrimaryValue = (float)city.LandArea;
point.SecondaryValue = point.Context.Index;
}
}
};</code></pre>

![image]({{ assets_url }}/docs/_assets/columnctl.png)

## Custom geometries

You can use any geometry to represent a point in a line series.

![image]({{ assets_url }}/docs/_assets/barscustom.png)

<pre><code>Series = new List&lt;ISeries>
{
// use the second type argument to specify the geometry to draw for every point
// there are already many predefined geometries in the
// LiveChartsCore.SkiaSharpView.Drawing.Geometries namespace
new ColumnSeries&lt;double, LiveChartsCore.SkiaSharpView.Drawing.Geometries.OvalGeometry>
{
Values = new List&lt;double> { 4, 2, 0, 5, 2, 6 },
Fill = new SolidColorPaint(SKColors.CornflowerBlue)
},

// you can also define your own geometry using SVG
new ColumnSeries&lt;double, MyGeometry>
{
Values = new List&lt;double> { 3, 2, 3, 4, 5, 3 },
Stroke = null,
Fill = new SolidColorPaint(SKColors.Coral, 5)
}
};</code></pre>

Where `MyGeometry` class is our custom shape, you can draw anything `SkiaSharp` supports at this point,
but in this case we will draw an SVG path, we inherit from `SVGPathGeometry`, and for performance reasons
we use a static variable to parse the SVG path, this ways the parse operation only runs once.

<pre><code>public class MyGeometry : SVGPathGeometry
{
// the static field is important to prevent the svg path is parsed multiple times // mark
// Icon from Google Material Icons font.
// https://fonts.google.com/icons?selected=Material%20Icons%20Outlined%3Amy_location%3A
public static SKPath svgPath = SKPath.ParseSvgPathData(
"M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 " +
"11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 " +
"3.13 7 7-3.13 7-7 7z");

public MyGeometry()
: base(svgPath)
{

}
}</code></pre>

{{ render this "~/shared/series2.md" }}
112 changes: 1 addition & 111 deletions docs/cartesianChart/financialseries.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,114 +123,4 @@ Series = new ISeries[]
}
};</code></pre>

## Plotting custom types

You can teach LiveCharts to plot anything, imagine the case where we have an array of the `Stock` class defined bellow:

<pre><code>public class Stock
{
public DateTime Date { get; set; }
public double Open { get; set; }
public double Close { get; set; }
public double High { get; set; }
public double Low { get; set; }
}</code></pre>

You can register this type **globally**, this means that every time LiveCharts finds a `Stock` instance in a chart
it will use the mapper we registered, global mappers are unique for a type, if you need to plot multiple
properties then you should use local mappers.

<pre><code>// Ideally you should call this when your application starts
// If you need help to decide where to add this code
// please see the installation guide in this docs.

// in this case we have an array of the Stock class

LiveCharts.Configure(config =>
config
.HasMap&lt;Stock>((stock, point) =>
{
// in this lambda function we take an instance of the City class (see city parameter)
// and the point in the chart for that instance (see point parameter)
// LiveCharts will call this method for every instance of our City class array,
// now we need to populate the point coordinates from our City instance to our point

point.SecondaryValue = stock.Date.Ticks; // use the date for the X axis (secondary)

// now LiveCharts uses Primary (high), Tertiary (open)
// Quaternary (close) and Quinary (low) planes to represent
// a financial point:

point.PrimaryValue = (float)stock.High;
point.TertiaryValue = (float)stock.Open;
point.QuaternaryValue = (float)stock.Close;
point.QuinaryValue = (float)stock.Low;
})
.HasMap&lt;Foo>(...) // you can register more types here using our fluent syntax
.HasMap&lt;Bar>(...)
);</code></pre>

Now we are ready to plot stock all over our application:

<pre><code>var stockData = new[]
{
new Stock
{
Date = new DateTime(2021, 1, 1),
Open = 200f,
Close = 280f,
High = 290f,
Low = 180f
},
new Stock
{
Date = new DateTime(2021, 1, 2),
Open = 280f,
Close = 220f,
High = 320f,
Low = 210f
}
};

XAxes = new[]
{
// set the UnitWidth to "days" to support date time scaled points.
new Axis
{
UnitWidth = TimeSpan.FromDays(1).Ticks,
LabelsRotation = 20,
Labeler = p => new DateTime((long)p).ToShortDateString(),
MinStep = TimeSpan.FromDays(1).Ticks
}
};

Series = new[]
{
new CandlesticksSeries&lt;Stock>
{
TooltipLabelFormatter =
(p) => $"H: {p.PrimaryValue:N2}, O: {p.TertiaryValue:N2}, C: {p.QuaternaryValue:N2}, L: {p.QuinaryValue:N2}",
Values = stockData
}
};</code></pre>

![image]({{ assets_url }}/docs/_assets/financialct.png)

Alternatively you could create a **local** mapper that will only work for a specific series, global mappers will be
ignored when the series `Mapping` property is not null.

<pre><code>Series = new[]
{
new CandlesticksSeries&lt;Stock>
{
Mapping = (stock, point) =>
{
point.SecondaryValue = stock.Date.Ticks;
point.PrimaryValue = (float)stock.High;
point.TertiaryValue = (float)stock.Open;
point.QuaternaryValue = (float)stock.Close;
point.QuinaryValue = (float)stock.Low;
},
Values = stockData
}
};</code></pre>
{{ render this "~/shared/series2.md" }}
Loading

0 comments on commit b3cfef4

Please sign in to comment.