ChartWindow: Upgrade to Scottplot 5

This commit is contained in:
2024-01-22 21:41:01 +01:00
parent 6cee604448
commit 3642c5ac07
4 changed files with 233 additions and 123 deletions

View File

@ -32,7 +32,7 @@
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2210.55" /> <PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2210.55" />
<PackageReference Include="NJsonSchema" Version="11.0.0" /> <PackageReference Include="NJsonSchema" Version="11.0.0" />
<PackageReference Include="RazorLight" Version="2.3.1" /> <PackageReference Include="RazorLight" Version="2.3.1" />
<PackageReference Include="ScottPlot.WPF" Version="4.1.68" /> <PackageReference Include="ScottPlot.WPF" Version="5.0.19" />
<PackageReference Include="System.IO.Ports" Version="8.0.0" /> <PackageReference Include="System.IO.Ports" Version="8.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
</ItemGroup> </ItemGroup>

View File

@ -1,4 +1,3 @@
using ScottPlot;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -16,15 +15,15 @@ namespace Elwig.Helpers.Billing {
Precision = precision; Precision = precision;
MinX = minX; MinX = minX;
MaxX = maxX; MaxX = maxX;
DataX = DataGen.Range(minX, maxX + 1); DataX = Enumerable.Range(minX, maxX - minX + 1).Select(n => (double)n).ToArray();
DataY = DataGen.Zeros(maxX - minX + 1); DataY = new double[DataX.Length];
} }
public Graph(Dictionary<double, decimal> data, int precision, int minX, int maxX) { public Graph(Dictionary<double, decimal> data, int precision, int minX, int maxX) {
Precision = precision; Precision = precision;
MinX = minX; MinX = minX;
MaxX = maxX; MaxX = maxX;
DataX = DataGen.Range(minX, maxX + 1); DataX = Enumerable.Range(minX, maxX - minX + 1).Select(n => (double)n).ToArray();
DataY = DataX.Select(i => (double)BillingData.GetCurveValueAt(data, i)).ToArray(); DataY = DataX.Select(i => (double)BillingData.GetCurveValueAt(data, i)).ToArray();
} }

View File

@ -7,10 +7,11 @@
xmlns:local="clr-namespace:Elwig.Windows" xmlns:local="clr-namespace:Elwig.Windows"
xmlns:ctrl="clr-namespace:Elwig.Controls" xmlns:ctrl="clr-namespace:Elwig.Controls"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:ScottPlot="clr-namespace:ScottPlot;assembly=ScottPlot.WPF" xmlns:ScottPlot="clr-namespace:ScottPlot.WPF;assembly=ScottPlot.WPF"
mc:Ignorable="d" mc:Ignorable="d"
Title="Auszahlung - Elwig" Height="700" Width="1500" MinWidth="1000" MinHeight="500" Title="Auszahlung - Elwig" Height="700" Width="1500" MinWidth="1000" MinHeight="500"
Loaded="Window_Loaded"> Loaded="Window_Loaded"
Closing="Window_Closing">
<Window.Resources> <Window.Resources>
<Style TargetType="Label"> <Style TargetType="Label">
@ -88,7 +89,7 @@
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
</ListBox> </ListBox>
<Button x:Name="SaveButton" Content="Speichern" IsEnabled="True" <Button x:Name="SaveButton" Content="Speichern" IsEnabled="False"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="10,5,35,15" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="10,5,35,15" Grid.Column="0" Grid.Row="2"
Click="SaveButton_Click"/> Click="SaveButton_Click"/>
@ -103,7 +104,7 @@
Click="DeleteButton_Click"/> Click="DeleteButton_Click"/>
<Grid Grid.Row="1" Grid.Column="1"> <Grid Grid.Row="1" Grid.Column="1">
<ScottPlot:WpfPlot x:Name="OechslePricePlot" MouseMove="OechslePricePlot_MouseMove" MouseDown="OechslePricePlot_MouseDown" IsEnabled="False"/> <ScottPlot:WpfPlot x:Name="OechslePricePlot" MouseWheel="OechslePricePlot_MouseWheel" MouseMove="OechslePricePlot_MouseMove" MouseDown="OechslePricePlot_MouseDown" IsEnabled="False"/>
</Grid> </Grid>
<Grid Grid.Row="1" Grid.Column="2" Margin="0,0,5,36"> <Grid Grid.Row="1" Grid.Column="2" Margin="0,0,5,36">

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@ -12,27 +11,34 @@ using Elwig.Helpers.Billing;
using Elwig.Models.Entities; using Elwig.Models.Entities;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.ChangeTracking;
using ScottPlot.Plottables;
using ScottPlot; using ScottPlot;
using ScottPlot.Plottable;
using Xceed.Wpf.Toolkit.Primitives; using Xceed.Wpf.Toolkit.Primitives;
using ScottPlot.Control;
namespace Elwig.Windows { namespace Elwig.Windows {
public partial class ChartWindow : ContextWindow { public partial class ChartWindow : ContextWindow {
public static readonly Color ColorUngebunden = Color.Blue; public static readonly Color ColorUngebunden = Colors.Blue;
public static readonly Color ColorGebunden = Color.Gold; public static readonly Color ColorGebunden = Colors.Gold;
public readonly int Year; public readonly int Year;
public readonly int AvNr; public readonly int AvNr;
public Season Season; public Season Season;
private PaymentVar PaymentVar; private PaymentVar PaymentVar;
private bool HasChanged = false;
private ScatterPlot DataPlot; private Scatter DataPlot;
private ScatterPlot? GebundenPlot; private Scatter? GebundenPlot;
private MarkerPlot HighlightedPointPlot; private Marker HighlightedPointPlot;
private MarkerPlot PrimaryMarkedPointPlot; private Marker PrimaryMarkedPointPlot;
private MarkerPlot SecondaryMarkedPointPlot; private Marker SecondaryMarkedPointPlot;
private Tooltip TooltipPlot; private Text TooltipPlot;
private LegendItem UngebundenLegend;
private LegendItem GebundenLegend;
private LegendItem LDWLegend;
private LegendItem QUWLegend;
private LegendItem KABLegend;
private (Graph? graph, int index) LastHighlighted = (null, -1); private (Graph? graph, int index) LastHighlighted = (null, -1);
private (Graph? graph, int index) Highlighted = (null, -1); private (Graph? graph, int index) Highlighted = (null, -1);
@ -44,7 +50,7 @@ namespace Elwig.Windows {
private bool FillingInputs = false; private bool FillingInputs = false;
private List<GraphEntry> GraphEntries = []; private List<GraphEntry> GraphEntries = [];
private GraphEntry? SelectedGraphEntry; private GraphEntry? SelectedGraphEntry => (GraphEntry)GraphList.SelectedItem;
public ChartWindow(int year, int avnr) { public ChartWindow(int year, int avnr) {
InitializeComponent(); InitializeComponent();
@ -53,10 +59,26 @@ namespace Elwig.Windows {
Season = Context.Seasons.Find(year) ?? throw new ArgumentException("Season not found"); Season = Context.Seasons.Find(year) ?? throw new ArgumentException("Season not found");
PaymentVar = Context.PaymentVariants.Find(year, avnr) ?? throw new ArgumentException("PaymentVar not found"); PaymentVar = Context.PaymentVariants.Find(year, avnr) ?? throw new ArgumentException("PaymentVar not found");
Title = $"{PaymentVar?.Name} - Lese {year} - Elwig"; Title = $"{PaymentVar?.Name} - Lese {year} - Elwig";
LockContext = true;
} }
private void Window_Loaded(object sender, RoutedEventArgs evt) { private void Window_Loaded(object sender, RoutedEventArgs evt) {
OechslePricePlot.IsEnabled = false; }
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
if (HasChanged) {
var r = MessageBox.Show("Soll das Fenster wirklich geschlossen werden? Nicht gespeicherte Änderungen werden NICHT übernommen!", "Schließen bestätigen",
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r != MessageBoxResult.Yes) {
e.Cancel = true;
return;
}
}
}
private void SetHasChanged(bool hasChanged = true) {
HasChanged = hasChanged;
SaveButton.IsEnabled = hasChanged;
} }
private async Task RefreshGraphList() { private async Task RefreshGraphList() {
@ -79,7 +101,6 @@ namespace Elwig.Windows {
ControlUtils.RenewItemsSource(ContractInput, contracts, g => (g as ContractSelection)?.Listing); ControlUtils.RenewItemsSource(ContractInput, contracts, g => (g as ContractSelection)?.Listing);
FillingInputs = false; FillingInputs = false;
ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.Id, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.Id, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
SelectedGraphEntry = GraphList.SelectedItem as GraphEntry;
RefreshInputs(); RefreshInputs();
} }
@ -89,7 +110,6 @@ namespace Elwig.Windows {
if (SelectedGraphEntry != null) { if (SelectedGraphEntry != null) {
CopyButton.IsEnabled = true; CopyButton.IsEnabled = true;
DeleteButton.IsEnabled = true; DeleteButton.IsEnabled = true;
//EnableUnitTextBox(OechsleInput);
GebundenTypeFixed.IsEnabled = true; GebundenTypeFixed.IsEnabled = true;
GebundenTypeGraph.IsEnabled = true; GebundenTypeGraph.IsEnabled = true;
GebundenTypeNone.IsEnabled = true; GebundenTypeNone.IsEnabled = true;
@ -144,55 +164,98 @@ namespace Elwig.Windows {
} }
private void InitPlot() { private void InitPlot() {
UngebundenLegend = new LegendItem() {
Label = "Ungebunden",
LineWidth = 1,
LineColor = ColorUngebunden,
Marker = new MarkerStyle(MarkerShape.FilledCircle, 5, ColorUngebunden)
};
GebundenLegend = new LegendItem() {
Label = "Gebunden",
LineWidth = 1,
LineColor = ColorGebunden,
Marker = new MarkerStyle(MarkerShape.FilledCircle, 5, ColorGebunden)
};
LDWLegend = new LegendItem() {
Label = "68 °Oe (LDW)",
LineWidth = 2,
LineColor = Colors.Red,
Marker = MarkerStyle.None
};
QUWLegend = new LegendItem() {
Label = "73 °Oe (QUW)",
LineWidth = 2,
LineColor = Colors.Orange,
Marker = MarkerStyle.None
};
KABLegend = new LegendItem() {
Label = "84 °Oe (KAB)",
LineWidth = 2,
LineColor = Colors.Green,
Marker = MarkerStyle.None
};
RefreshGradationLines();
if (SelectedGraphEntry?.GebundenGraph != null) { if (SelectedGraphEntry?.GebundenGraph != null) {
GebundenPlot = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry.GebundenGraph.DataX, SelectedGraphEntry.GebundenGraph.DataY, label: "Gebunden"); GebundenPlot = OechslePricePlot.Plot.Add.Scatter(SelectedGraphEntry.GebundenGraph.DataX, SelectedGraphEntry.GebundenGraph.DataY);
GebundenPlot.LineColor = ColorGebunden; GebundenPlot.LineStyle.Color = ColorGebunden;
GebundenPlot.MarkerColor = ColorGebunden; GebundenPlot.Color = ColorGebunden;
GebundenPlot.MarkerSize = 9; GebundenPlot.MarkerStyle = new MarkerStyle(MarkerShape.FilledCircle, 9, ColorGebunden);
} }
DataPlot = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry!.DataGraph.DataX, SelectedGraphEntry!.DataGraph.DataY, label: "Ungebunden"); DataPlot = OechslePricePlot.Plot.Add.Scatter(SelectedGraphEntry!.DataGraph.DataX, SelectedGraphEntry!.DataGraph.DataY);
DataPlot.LineColor = ColorUngebunden; DataPlot.LineStyle.Color = ColorUngebunden;
DataPlot.MarkerColor = ColorUngebunden; DataPlot.Color = ColorUngebunden;
DataPlot.MarkerSize = 9; DataPlot.MarkerStyle = new MarkerStyle(MarkerShape.FilledCircle, 9, ColorUngebunden);
if (SelectedGraphEntry?.GebundenGraph == null) { if (SelectedGraphEntry?.GebundenGraph == null) {
ChangeActiveGraph(SelectedGraphEntry?.DataGraph); ChangeActiveGraph(SelectedGraphEntry?.DataGraph);
} }
OechslePricePlot.RightClicked -= OechslePricePlot.DefaultRightClickEvent; OechslePricePlot.Interaction.Enable(new PlotActions() {
OechslePricePlot.Configuration.DoubleClickBenchmark = false; ZoomIn = StandardActions.ZoomIn,
ZoomOut = StandardActions.ZoomOut,
PanUp = StandardActions.PanUp,
PanDown = StandardActions.PanDown,
PanLeft = StandardActions.PanLeft,
PanRight = StandardActions.PanRight,
DragPan = StandardActions.DragPan,
DragZoom = StandardActions.DragZoom,
DragZoomRectangle = StandardActions.DragZoomRectangle,
ZoomRectangleClear = StandardActions.ZoomRectangleClear,
ZoomRectangleApply = StandardActions.ZoomRectangleApply,
AutoScale = StandardActions.AutoScale,
});
//OechslePricePlot.Plot.XAxis.ManualTickSpacing(1); //OechslePricePlot.Plot.XAxis.ManualTickSpacing(1);
OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1); //OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1);
OechslePricePlot.Plot.SetAxisLimits(Math.Min(GraphEntry.MinX, GraphEntry.MinXGeb) - 1, GraphEntry.MaxX + 1, -0.1, 2); OechslePricePlot.Plot.Axes.SetLimits(Math.Min(GraphEntry.MinX, GraphEntry.MinXGeb) - 1, GraphEntry.MaxX + 1, -0.1, 2);
OechslePricePlot.Plot.Layout(padding: 0); //OechslePricePlot.Plot.Layout(padding: 0);
OechslePricePlot.Plot.XAxis2.Layout(padding: 0); //OechslePricePlot.Plot.XAxis2.Layout(padding: 0);
OechslePricePlot.Plot.YAxis.Layout(padding: 0); //OechslePricePlot.Plot.YAxis.Layout(padding: 0);
OechslePricePlot.Plot.YAxis2.Layout(padding: 0); //OechslePricePlot.Plot.YAxis2.Layout(padding: 0);
HighlightedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0); HighlightedPointPlot = OechslePricePlot.Plot.Add.Marker(0, 0, MarkerShape.OpenCircle, 10, Colors.Red);
HighlightedPointPlot.Color = Color.Red;
HighlightedPointPlot.MarkerSize = 10;
HighlightedPointPlot.MarkerShape = MarkerShape.openCircle;
HighlightedPointPlot.IsVisible = false; HighlightedPointPlot.IsVisible = false;
PrimaryMarkedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0); PrimaryMarkedPointPlot = OechslePricePlot.Plot.Add.Marker(0, 0, MarkerShape.FilledCircle, 6, Colors.Red);
PrimaryMarkedPointPlot.Color = Color.Red;
PrimaryMarkedPointPlot.MarkerSize = 6;
PrimaryMarkedPointPlot.MarkerShape = MarkerShape.filledCircle;
PrimaryMarkedPointPlot.IsVisible = false; PrimaryMarkedPointPlot.IsVisible = false;
SecondaryMarkedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0); SecondaryMarkedPointPlot = OechslePricePlot.Plot.Add.Marker(0, 0, MarkerShape.FilledCircle, 6, Colors.Red);
SecondaryMarkedPointPlot.Color = Color.Red;
SecondaryMarkedPointPlot.MarkerSize = 6;
SecondaryMarkedPointPlot.MarkerShape = MarkerShape.filledCircle;
SecondaryMarkedPointPlot.IsVisible = false; SecondaryMarkedPointPlot.IsVisible = false;
OechslePricePlot.Refresh(); OechslePricePlot.Refresh();
RefreshFreeZoom(); RefreshFreeZoom();
RefreshGradationLines(); OechslePricePlot.Refresh();
} }
private void ResetPlot() { private void ResetPlot() {
@ -201,22 +264,20 @@ namespace Elwig.Windows {
ChangeActiveGraph(null); ChangeActiveGraph(null);
HideGradationLines(); HideGradationLines();
OechslePricePlot.Plot.Remove(DataPlot); OechslePricePlot.Plot.Remove(DataPlot);
if (GebundenPlot != null) {
OechslePricePlot.Plot.Remove(GebundenPlot); OechslePricePlot.Plot.Remove(GebundenPlot);
GebundenPlot = null;
}
OechslePricePlot.Plot.Clear(); OechslePricePlot.Plot.Clear();
OechslePricePlot.Reset(); OechslePricePlot.Reset();
OechslePricePlot.Refresh(); OechslePricePlot.Refresh();
} }
private void ChangeMarker(MarkerPlot point, bool visible, double x = 0, double y = 0) { private void ChangeMarker(Marker point, bool visible, double x = 0, double y = 0) {
point.X = x; point.Location = new Coordinates(x, y);
point.Y = y;
point.IsVisible = visible; point.IsVisible = visible;
} }
private void LinearIncreaseGraph(int begin, int end, double inc) {
}
private void EnableActionButtons() { private void EnableActionButtons() {
if (PaymentVar.TestVariant) { if (PaymentVar.TestVariant) {
LeftFlatButton.IsEnabled = true; LeftFlatButton.IsEnabled = true;
@ -246,18 +307,32 @@ namespace Elwig.Windows {
} }
private void LockZoom() { private void LockZoom() {
OechslePricePlot.Plot.XAxis.SetBoundary(GraphEntry.MinX - 1, GraphEntry.MaxX + 1); ScottPlot.AxisRules.MaximumBoundary BoundaryRule = new(
OechslePricePlot.Plot.YAxis.SetBoundary(-0.1, 2); xAxis: OechslePricePlot.Plot.Axes.Bottom,
OechslePricePlot.Plot.XAxis.SetZoomOutLimit(GraphEntry.MaxX - GraphEntry.MinX + 2); yAxis: OechslePricePlot.Plot.Axes.Left,
OechslePricePlot.Plot.YAxis.SetZoomOutLimit(2.1); limits: new AxisLimits(GraphEntry.MinX - 1, GraphEntry.MaxX + 1, -0.1, 2));
OechslePricePlot.Plot.SetAxisLimits(GraphEntry.MinX - 1, GraphEntry.MaxX + 1, -0.1, 2);
ScottPlot.AxisRules.MaximumSpan SpanRule = new(
xAxis: OechslePricePlot.Plot.Axes.Bottom,
yAxis: OechslePricePlot.Plot.Axes.Left,
xSpan: GraphEntry.MaxX - GraphEntry.MinX + 2,
ySpan: 2.1);
OechslePricePlot.Plot.Axes.Rules.Clear();
OechslePricePlot.Plot.Axes.Rules.Add(BoundaryRule);
OechslePricePlot.Plot.Axes.Rules.Add(SpanRule);
OechslePricePlot.Plot.Axes.SetLimits(GraphEntry.MinX - 1, GraphEntry.MaxX + 1, -0.1, 2);
} }
private void UnlockZoom() { private void UnlockZoom() {
OechslePricePlot.Plot.XAxis.SetBoundary(); ScottPlot.AxisRules.MaximumSpan SpanRule = new(
OechslePricePlot.Plot.YAxis.SetBoundary(); xAxis: OechslePricePlot.Plot.Axes.Bottom,
OechslePricePlot.Plot.XAxis.SetZoomOutLimit((GraphEntry.MaxX - GraphEntry.MinX) * 1.5); yAxis: OechslePricePlot.Plot.Axes.Left,
OechslePricePlot.Plot.YAxis.SetZoomOutLimit(3.5); xSpan: (GraphEntry.MaxX - GraphEntry.MinX) * 1.5,
ySpan: 3.5);
OechslePricePlot.Plot.Axes.Rules.Clear();
OechslePricePlot.Plot.Axes.Rules.Add(SpanRule);
} }
private void EnableOptionButtons() { private void EnableOptionButtons() {
@ -277,7 +352,7 @@ namespace Elwig.Windows {
} }
private void RefreshGradationLines() { private void RefreshGradationLines() {
if (GradationLinesInput.IsChecked == true && SelectedGraphEntry != null && !OechslePricePlot.Plot.GetPlottables().OfType<VLine>().Any()) { if (GradationLinesInput.IsChecked == true && SelectedGraphEntry != null && !OechslePricePlot.Plot.PlottableList.OfType<VerticalLine>().Any()) {
ShowGradationLines(); ShowGradationLines();
ShowLegend(); ShowLegend();
} else if (GradationLinesInput.IsChecked == false) { } else if (GradationLinesInput.IsChecked == false) {
@ -288,21 +363,29 @@ namespace Elwig.Windows {
} }
private void ShowGradationLines() { private void ShowGradationLines() {
OechslePricePlot.Plot.AddVerticalLine(68, Color.Red, 2, label: "68 °Oe (LDW)"); OechslePricePlot.Plot.Add.VerticalLine(68, 2, Colors.Red);
OechslePricePlot.Plot.AddVerticalLine(73, Color.Orange, 2, label: "73 °Oe (QUW)"); OechslePricePlot.Plot.Add.VerticalLine(73, 2, Colors.Orange);
OechslePricePlot.Plot.AddVerticalLine(84, Color.Green, 2, label: "84 °Oe (KAB)"); OechslePricePlot.Plot.Add.VerticalLine(84, 2, Colors.Green);
} }
private void HideGradationLines() { private void HideGradationLines() {
OechslePricePlot.Plot.Clear(typeof(VLine)); OechslePricePlot.Plot.PlottableList.RemoveAll(p => p is VerticalLine);
} }
private void ShowLegend() { private void ShowLegend() {
OechslePricePlot.Plot.Legend(true, Alignment.UpperLeft); OechslePricePlot.Plot.Legend.Location = Alignment.UpperLeft;
OechslePricePlot.Plot.Legend.IsVisible = true;
OechslePricePlot.Plot.Legend.ManualItems.Add(LDWLegend);
OechslePricePlot.Plot.Legend.ManualItems.Add(QUWLegend);
OechslePricePlot.Plot.Legend.ManualItems.Add(KABLegend);
OechslePricePlot.Plot.Legend.ManualItems.Add(UngebundenLegend);
if (SelectedGraphEntry?.GebundenGraph != null) OechslePricePlot.Plot.Legend.ManualItems.Add(GebundenLegend);
} }
private void HideLegend() { private void HideLegend() {
OechslePricePlot.Plot.Legend(false, Alignment.UpperLeft); OechslePricePlot.Plot.Legend.IsVisible = false;
OechslePricePlot.Plot.Legend.ManualItems.Clear();
} }
private void OechsleInput_TextChanged(object sender, TextChangedEventArgs evt) { private void OechsleInput_TextChanged(object sender, TextChangedEventArgs evt) {
@ -323,19 +406,18 @@ namespace Elwig.Windows {
PriceInput.Text = ActiveGraph.GetPriceAt(PrimaryMarkedPoint).ToString(); PriceInput.Text = ActiveGraph.GetPriceAt(PrimaryMarkedPoint).ToString();
EnableActionButtons(); EnableActionButtons();
OechslePricePlot.Render(); OechslePricePlot.Refresh();
EnableUnitTextBox(PriceInput); EnableUnitTextBox(PriceInput);
return; return;
} }
} }
PrimaryMarkedPoint = -1; PrimaryMarkedPoint = -1;
//ChangeActiveGraph(null);
ChangeMarker(PrimaryMarkedPointPlot, false); ChangeMarker(PrimaryMarkedPointPlot, false);
DisableActionButtons(); DisableActionButtons();
PriceInput.Text = ""; PriceInput.Text = "";
DisableUnitTextBox(PriceInput); DisableUnitTextBox(PriceInput);
OechslePricePlot.Render(); OechslePricePlot.Refresh();
DisableUnitTextBox(PriceInput); DisableUnitTextBox(PriceInput);
} }
@ -343,7 +425,8 @@ namespace Elwig.Windows {
if (PrimaryMarkedPoint != -1 && ActiveGraph != null) { if (PrimaryMarkedPoint != -1 && ActiveGraph != null) {
if (double.TryParse(PriceInput.Text, out double price)) { if (double.TryParse(PriceInput.Text, out double price)) {
ActiveGraph.SetPriceAt(PrimaryMarkedPoint, price); ActiveGraph.SetPriceAt(PrimaryMarkedPoint, price);
PrimaryMarkedPointPlot.Y = price; PrimaryMarkedPointPlot.Location = new Coordinates(PrimaryMarkedPointPlot.Location.X, price);
SetHasChanged();
OechslePricePlot.Refresh(); OechslePricePlot.Refresh();
CheckGebundenTypeFixed(); CheckGebundenTypeFixed();
} }
@ -355,7 +438,8 @@ namespace Elwig.Windows {
return; return;
} }
ActiveGraph.FlattenGraphLeft(PrimaryMarkedPoint); ActiveGraph.FlattenGraphLeft(PrimaryMarkedPoint);
OechslePricePlot.Render(); SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed(); CheckGebundenTypeFixed();
} }
@ -364,7 +448,8 @@ namespace Elwig.Windows {
return; return;
} }
ActiveGraph.FlattenGraphRight(PrimaryMarkedPoint); ActiveGraph.FlattenGraphRight(PrimaryMarkedPoint);
OechslePricePlot.Render(); SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed(); CheckGebundenTypeFixed();
} }
@ -373,7 +458,8 @@ namespace Elwig.Windows {
return; return;
} }
ActiveGraph.InterpolateGraph(PrimaryMarkedPoint, SecondaryMarkedPoint); ActiveGraph.InterpolateGraph(PrimaryMarkedPoint, SecondaryMarkedPoint);
OechslePricePlot.Render(); SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed(); CheckGebundenTypeFixed();
} }
@ -386,7 +472,8 @@ namespace Elwig.Windows {
return; return;
} }
ActiveGraph.LinearIncreaseGraphToEnd(PrimaryMarkedPoint, priceIncrease.Value); ActiveGraph.LinearIncreaseGraphToEnd(PrimaryMarkedPoint, priceIncrease.Value);
OechslePricePlot.Render(); SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed(); CheckGebundenTypeFixed();
} }
@ -396,7 +483,7 @@ namespace Elwig.Windows {
} }
if (HoverActive) { if (HoverActive) {
if (PaymentVar.TestVariant && Keyboard.IsKeyDown(Key.LeftCtrl)) { if (PaymentVar.TestVariant && Keyboard.IsKeyDown(System.Windows.Input.Key.LeftCtrl)) {
if (PrimaryMarkedPoint == -1 || ActiveGraph == null || ActiveGraph != Highlighted.graph) { if (PrimaryMarkedPoint == -1 || ActiveGraph == null || ActiveGraph != Highlighted.graph) {
return; return;
} }
@ -410,7 +497,7 @@ namespace Elwig.Windows {
} }
PrimaryMarkedPoint = Highlighted.index; PrimaryMarkedPoint = Highlighted.index;
ChangeActiveGraph(Highlighted.graph); if (ActiveGraph != Highlighted.graph) ChangeActiveGraph(Highlighted.graph);
ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint)); ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint));
@ -435,32 +522,21 @@ namespace Elwig.Windows {
} }
} }
private (double, double, int)? MouseOnPlot(ScatterPlot? plot) {
if (plot == null) {
return null;
}
(double mouseCoordX, double mouseCoordY) = OechslePricePlot.GetMouseCoordinates();
(double mousePixelX, double mousePixelY) = OechslePricePlot.GetMousePixel();
double xyRatio = OechslePricePlot.Plot.XAxis.Dims.PxPerUnit / OechslePricePlot.Plot.YAxis.Dims.PxPerUnit;
(double pointX, double pointY, int pointIndex) = plot.GetPointNearest(mouseCoordX, mouseCoordY, xyRatio);
(double pointPixelX, double pointPixelY) = OechslePricePlot.Plot.GetPixel(pointX, pointY);
if (Math.Abs(mousePixelX - pointPixelX) < 3 && Math.Abs(mousePixelY - pointPixelY) < 3) {
return (pointX, pointY, pointIndex);
} else {
return null;
}
}
private void OechslePricePlot_MouseMove(object sender, MouseEventArgs e) { private void OechslePricePlot_MouseMove(object sender, MouseEventArgs e) {
MouseChange(e);
}
private void OechslePricePlot_MouseWheel(object sender, MouseWheelEventArgs e) {
MouseChange(e);
}
private void MouseChange(MouseEventArgs e) {
if (GraphList.SelectedItem == null) { if (GraphList.SelectedItem == null) {
return; return;
} }
(double x, double y, int index)? mouseOnData = MouseOnPlot(DataPlot); (double x, double y, int index)? mouseOnData = MouseOnPlot(DataPlot, e.GetPosition(OechslePricePlot));
(double x, double y , int index)? mouseOnGebunden = MouseOnPlot(GebundenPlot); (double x, double y, int index)? mouseOnGebunden = MouseOnPlot(GebundenPlot, e.GetPosition(OechslePricePlot));
Highlighted = LastHighlighted; Highlighted = LastHighlighted;
@ -469,31 +545,57 @@ namespace Elwig.Windows {
HighlightedPointPlot.IsVisible = true; HighlightedPointPlot.IsVisible = true;
HoverChanged = true ^ HoverActive; HoverChanged = true ^ HoverActive;
HoverActive = true; HoverActive = true;
HandleTooltip(mouseOnData.Value.x, mouseOnData.Value.y, mouseOnData.Value.index, SelectedGraphEntry!.DataGraph); HandleTooltip(mouseOnData.Value.x, mouseOnData.Value.y, mouseOnData.Value.index, SelectedGraphEntry!.DataGraph, e.GetPosition(OechslePricePlot), e is MouseWheelEventArgs);
} else if (mouseOnGebunden != null) { } else if (mouseOnGebunden != null) {
ChangeMarker(HighlightedPointPlot, true, mouseOnGebunden.Value.x, mouseOnGebunden.Value.y); ChangeMarker(HighlightedPointPlot, true, mouseOnGebunden.Value.x, mouseOnGebunden.Value.y);
HighlightedPointPlot.IsVisible = true; HighlightedPointPlot.IsVisible = true;
HoverChanged = true ^ HoverActive; HoverChanged = true ^ HoverActive;
HoverActive = true; HoverActive = true;
HandleTooltip(mouseOnGebunden.Value.x, mouseOnGebunden.Value.y, mouseOnGebunden.Value.index, SelectedGraphEntry!.GebundenGraph!); HandleTooltip(mouseOnGebunden.Value.x, mouseOnGebunden.Value.y, mouseOnGebunden.Value.index, SelectedGraphEntry!.GebundenGraph!, e.GetPosition(OechslePricePlot), e is MouseWheelEventArgs);
} else { } else {
ChangeMarker(HighlightedPointPlot, false); ChangeMarker(HighlightedPointPlot, false);
HoverChanged = false ^ HoverActive; HoverChanged = false ^ HoverActive;
HoverActive = false; HoverActive = false;
OechslePricePlot.Plot.Remove(TooltipPlot); OechslePricePlot.Plot.PlottableList.Remove(TooltipPlot);
OechslePricePlot.Render(); OechslePricePlot.Refresh();
} }
} }
private void HandleTooltip(double pointX, double pointY, int pointIndex, Graph g) { private (double, double, int)? MouseOnPlot(Scatter? plot, Point p) {
if (LastHighlighted != Highlighted || HoverChanged) { if (plot == null) {
OechslePricePlot.Plot.Remove(TooltipPlot); return null;
}
OechslePricePlot.Refresh();
Pixel mousePixel = new(p.X, p.Y);
Coordinates mouseLocation = OechslePricePlot.Plot.GetCoordinates(mousePixel);
DataPoint nearestPoint = plot.Data.GetNearest(mouseLocation, OechslePricePlot.Plot.LastRender, 3);
if (nearestPoint.IsReal) {
return (nearestPoint.X, nearestPoint.Y, nearestPoint.Index);
} else {
return null;
}
}
private void HandleTooltip(double pointX, double pointY, int pointIndex, Graph g, Point p, bool force) {
if (force || LastHighlighted != Highlighted || HoverChanged) {
OechslePricePlot.Plot.PlottableList.Remove(TooltipPlot);
if (TooltipInput.IsChecked == true) { if (TooltipInput.IsChecked == true) {
TooltipPlot = OechslePricePlot.Plot.AddTooltip($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, Season.Precision)}€/kg)", pointX, pointY); Pixel mousePixel = new(p.X, p.Y - 30);
Coordinates mouseLocation = OechslePricePlot.Plot.GetCoordinates(mousePixel);
TooltipPlot = OechslePricePlot.Plot.Add.Text($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, Season.Precision)}€/kg", mouseLocation.X, mouseLocation.Y);
TooltipPlot.Label.FontSize = 12;
TooltipPlot.Label.Bold = true;
TooltipPlot.Label.BorderColor = Colors.Black;
TooltipPlot.Label.BorderWidth = 2;
TooltipPlot.Label.BackColor = Colors.White;
TooltipPlot.Label.Padding = 10;
TooltipPlot.Label.Alignment = Alignment.MiddleLeft;
} }
LastHighlighted = (g, pointIndex); LastHighlighted = (g, pointIndex);
HoverChanged = false; HoverChanged = false;
OechslePricePlot.Render(); OechslePricePlot.Refresh();
} }
} }
@ -504,6 +606,7 @@ namespace Elwig.Windows {
private void AddButton_Click(object sender, RoutedEventArgs e) { private void AddButton_Click(object sender, RoutedEventArgs e) {
GraphEntry newGraphEntry = new(GetMaxGraphId() + 1, Season.Precision, BillingData.CurveMode.Oe); GraphEntry newGraphEntry = new(GetMaxGraphId() + 1, Season.Precision, BillingData.CurveMode.Oe);
GraphEntries.Add(newGraphEntry); GraphEntries.Add(newGraphEntry);
SetHasChanged();
GraphList.Items.Refresh(); GraphList.Items.Refresh();
GraphList.SelectedItem = newGraphEntry; GraphList.SelectedItem = newGraphEntry;
} }
@ -513,6 +616,7 @@ namespace Elwig.Windows {
GraphEntry newGraphEntry = SelectedGraphEntry.Copy(GetMaxGraphId() + 1); GraphEntry newGraphEntry = SelectedGraphEntry.Copy(GetMaxGraphId() + 1);
GraphEntries.Add(newGraphEntry); GraphEntries.Add(newGraphEntry);
SetHasChanged();
GraphList.Items.Refresh(); GraphList.Items.Refresh();
GraphList.SelectedItem = newGraphEntry; GraphList.SelectedItem = newGraphEntry;
} }
@ -521,12 +625,14 @@ namespace Elwig.Windows {
if (SelectedGraphEntry == null) return; if (SelectedGraphEntry == null) return;
var r = MessageBox.Show( var r = MessageBox.Show(
$"Soll der Graph {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.Contracts}) wirklich gelöscht werden?", $"Soll der Graph {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.ContractsStringSimple}) wirklich gelöscht werden?",
"Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); "Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r == MessageBoxResult.Yes) { if (r == MessageBoxResult.Yes) {
GraphEntries.Remove(SelectedGraphEntry); GraphEntries.Remove(SelectedGraphEntry);
SetHasChanged();
GraphList.Items.Refresh(); GraphList.Items.Refresh();
OechslePricePlot.IsEnabled = false;
} }
} }
@ -548,6 +654,7 @@ namespace Elwig.Windows {
MessageBox.Show(str, "Auszahlungsvariante speichern", MessageBoxButton.OK, MessageBoxImage.Error); MessageBox.Show(str, "Auszahlungsvariante speichern", MessageBoxButton.OK, MessageBoxImage.Error);
} }
LockContext = true; LockContext = true;
SetHasChanged(false);
} }
private void EnableUnitTextBox(UnitTextBox u) { private void EnableUnitTextBox(UnitTextBox u) {
@ -565,7 +672,7 @@ namespace Elwig.Windows {
private void ChangeActiveGraph(Graph? g) { private void ChangeActiveGraph(Graph? g) {
if (g != null && g == SelectedGraphEntry?.DataGraph) { if (g != null && g == SelectedGraphEntry?.DataGraph) {
EnableUnitTextBox(OechsleInput); EnableUnitTextBox(OechsleInput);
ChangeLineWidth(DataPlot, 4); if (SelectedGraphEntry?.GebundenGraph != null) ChangeLineWidth(DataPlot, 4);
ChangeLineWidth(GebundenPlot, 1); ChangeLineWidth(GebundenPlot, 1);
} else if (g != null && g == SelectedGraphEntry?.GebundenGraph) { } else if (g != null && g == SelectedGraphEntry?.GebundenGraph) {
EnableUnitTextBox(OechsleInput); EnableUnitTextBox(OechsleInput);
@ -582,14 +689,13 @@ namespace Elwig.Windows {
ActiveGraph = g; ActiveGraph = g;
} }
private void ChangeLineWidth(ScatterPlot? p, double lineWidth) { private void ChangeLineWidth(Scatter? p, double lineWidth) {
if (p != null) { if (p != null) {
p.LineWidth = lineWidth; p.LineWidth = (float)lineWidth;
} }
} }
private void GraphList_SelectionChanged(object sender, SelectionChangedEventArgs e) { private void GraphList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
SelectedGraphEntry = GraphList.SelectedItem as GraphEntry;
RefreshInputs(); RefreshInputs();
} }
@ -631,8 +737,10 @@ namespace Elwig.Windows {
} }
private void AbgewertetInput_Changed(object sender, RoutedEventArgs e) { private void AbgewertetInput_Changed(object sender, RoutedEventArgs e) {
if (FillingInputs) return;
if (SelectedGraphEntry == null) return; if (SelectedGraphEntry == null) return;
SelectedGraphEntry.Abgewertet = AbgewertetInput.IsChecked == true; SelectedGraphEntry.Abgewertet = AbgewertetInput.IsChecked == true;
SetHasChanged();
} }
private void GebundenType_Checked(object sender, RoutedEventArgs e) { private void GebundenType_Checked(object sender, RoutedEventArgs e) {
@ -652,6 +760,7 @@ namespace Elwig.Windows {
SelectedGraphEntry.AddGebundenGraph(); SelectedGraphEntry.AddGebundenGraph();
DisableUnitTextBox(GebundenFlatBonus); DisableUnitTextBox(GebundenFlatBonus);
} }
SetHasChanged();
RefreshInputs(); RefreshInputs();
} }
@ -661,8 +770,9 @@ namespace Elwig.Windows {
GebundenTypeFixed.IsChecked = true; GebundenTypeFixed.IsChecked = true;
GebundenFlatBonus.Text = $"{bonus}"; GebundenFlatBonus.Text = $"{bonus}";
EnableUnitTextBox(GebundenFlatBonus); EnableUnitTextBox(GebundenFlatBonus);
} else { } else if (SelectedGraphEntry?.GebundenGraph != null) {
GebundenTypeGraph.IsChecked = true; GebundenTypeGraph.IsChecked = true;
GebundenFlatBonus.Text = "";
DisableUnitTextBox(GebundenFlatBonus); DisableUnitTextBox(GebundenFlatBonus);
} }
FillingInputs = false; FillingInputs = false;