658 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			658 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Drawing;
 | |
| using System.Linq;
 | |
| using System.Threading.Tasks;
 | |
| using System.Windows;
 | |
| using System.Windows.Controls;
 | |
| using System.Windows.Input;
 | |
| using Elwig.Controls;
 | |
| using Elwig.Helpers;
 | |
| using Elwig.Helpers.Billing;
 | |
| using Elwig.Models.Entities;
 | |
| using Microsoft.EntityFrameworkCore;
 | |
| using Microsoft.EntityFrameworkCore.ChangeTracking;
 | |
| using ScottPlot;
 | |
| using ScottPlot.Plottable;
 | |
| using Xceed.Wpf.Toolkit.Primitives;
 | |
| 
 | |
| namespace Elwig.Windows {
 | |
|     public partial class ChartWindow : ContextWindow {
 | |
| 
 | |
|         public static readonly Color ColorUngebunden = Color.Blue;
 | |
|         public static readonly Color ColorGebunden = Color.Gold;
 | |
| 
 | |
|         public readonly int Year;
 | |
|         public readonly int AvNr;
 | |
|         public Season Season;
 | |
|         private PaymentVar PaymentVar;
 | |
| 
 | |
|         private ScatterPlot DataPlot;
 | |
|         private ScatterPlot? GebundenPlot;
 | |
|         private MarkerPlot HighlightedPointPlot;
 | |
|         private MarkerPlot PrimaryMarkedPointPlot;
 | |
|         private MarkerPlot SecondaryMarkedPointPlot;
 | |
|         private Tooltip TooltipPlot;
 | |
| 
 | |
|         private (Graph? graph, int index) LastHighlighted = (null, -1);
 | |
|         private (Graph? graph, int index) Highlighted = (null, -1);
 | |
|         private Graph? ActiveGraph = null;
 | |
|         private int PrimaryMarkedPoint = -1;
 | |
|         private int SecondaryMarkedPoint = -1;
 | |
|         private bool HoverChanged = false;
 | |
|         private bool HoverActive = false;
 | |
|         private bool FillingInputs = false;
 | |
| 
 | |
|         private const int MinOechsle = 50;
 | |
|         private const int MinOechsleGebunden = 73;
 | |
|         private const int MaxOechsle = 140;
 | |
| 
 | |
|         private List<GraphEntry> GraphEntries = [];
 | |
|         private GraphEntry? SelectedGraphEntry;
 | |
| 
 | |
|         public ChartWindow(int year, int avnr) {
 | |
|             InitializeComponent();
 | |
|             Year = year;
 | |
|             AvNr = avnr;
 | |
|             Season = Context.Seasons.Find(year) ?? throw new ArgumentException("Season not found");
 | |
|             PaymentVar = Context.PaymentVariants.Find(year, avnr) ?? throw new ArgumentException("PaymentVar not found");
 | |
|             Title = $"{PaymentVar?.Name} - Lese {year} - Elwig";
 | |
|         }
 | |
| 
 | |
|         private void Window_Loaded(object sender, RoutedEventArgs evt) {
 | |
|             OechslePricePlot.IsEnabled = false;
 | |
|         }
 | |
| 
 | |
|         private async Task RefreshGraphList() {
 | |
|             PaymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found");
 | |
|             Season = await Context.Seasons.FindAsync(Year) ?? throw new ArgumentException("Season not found");
 | |
| 
 | |
|             var attrVariants = (await Context.DeliveryParts
 | |
|                 .Where(d => d.Year == Year)
 | |
|                 .Select(d => $"{d.SortId}{d.AttrId}")
 | |
|                 .Distinct()
 | |
|                 .ToListAsync())
 | |
|                 .Union(Context.WineVarieties.Select(v => v.SortId))
 | |
|                 .Order()
 | |
|                 .ToList();
 | |
|             var data = EditBillingData.FromJson(PaymentVar.Data, attrVariants);
 | |
|             GraphEntries = [ ..data.GetPaymentGraphEntries(Context, Season), ..data.GetQualityGraphEntries(Context, Season)];
 | |
| 
 | |
|             var contracts = ContractSelection.GetContractsForYear(Context, Year);
 | |
|             FillingInputs = true;
 | |
|             ControlUtils.RenewItemsSource(ContractInput, contracts, g => (g as ContractSelection)?.Listing);
 | |
|             FillingInputs = false;
 | |
|             ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.Id, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
 | |
|             SelectedGraphEntry = GraphList.SelectedItem as GraphEntry;
 | |
| 
 | |
|             RefreshInputs();
 | |
|         }
 | |
| 
 | |
|         private void RefreshInputs() {
 | |
|             ResetPlot();
 | |
|             if (SelectedGraphEntry != null) {
 | |
|                 CopyButton.IsEnabled = true;
 | |
|                 DeleteButton.IsEnabled = true;
 | |
|                 //EnableUnitTextBox(OechsleInput);
 | |
|                 GebundenTypeFixed.IsEnabled = true;
 | |
|                 GebundenTypeGraph.IsEnabled = true;
 | |
|                 GebundenTypeNone.IsEnabled = true;
 | |
|                 ContractInput.IsEnabled = true;
 | |
|                 AbgewertetInput.IsEnabled = true;
 | |
|                 EnableOptionButtons();
 | |
|                 FillInputs();
 | |
|             } else {
 | |
|                 CopyButton.IsEnabled = false;
 | |
|                 DeleteButton.IsEnabled = false;
 | |
|                 DisableUnitTextBox(OechsleInput);
 | |
|                 DisableOptionButtons();
 | |
|             }
 | |
|             if (!PaymentVar.TestVariant) {
 | |
|                 AddButton.IsEnabled = false;
 | |
|                 CopyButton.IsEnabled = false;
 | |
|                 DeleteButton.IsEnabled = false;
 | |
|                 DisableUnitTextBox(OechsleInput);
 | |
|                 DisableUnitTextBox(PriceInput);
 | |
|                 GebundenTypeFixed.IsEnabled = false;
 | |
|                 GebundenTypeGraph.IsEnabled = false;
 | |
|                 GebundenTypeNone.IsEnabled = false;
 | |
|                 ContractInput.IsEnabled = false;
 | |
|                 AbgewertetInput.IsEnabled = false;
 | |
|             }
 | |
|             GC.Collect();
 | |
|         }
 | |
| 
 | |
|         private void FillInputs() {
 | |
|             FillingInputs = true;
 | |
| 
 | |
|             if (SelectedGraphEntry?.GebundenFlatBonus != null) {
 | |
|                 GebundenTypeFixed.IsChecked = true;
 | |
|             } else if (SelectedGraphEntry?.GebundenGraph != null) {
 | |
|                 GebundenTypeGraph.IsChecked = true;
 | |
|             } else {
 | |
|                 GebundenTypeNone.IsChecked = true;
 | |
|             }
 | |
| 
 | |
|             ControlUtils.SelectCheckComboBoxItems(ContractInput, SelectedGraphEntry?.Contracts ?? [], i => (i as ContractSelection)?.Listing);
 | |
| 
 | |
|             InitPlot();
 | |
|             OechslePricePlot.IsEnabled = true;
 | |
|             FillingInputs = false;
 | |
|         }
 | |
| 
 | |
|         protected override async Task OnRenewContext() {
 | |
|             await RefreshGraphList();
 | |
|         }
 | |
| 
 | |
|         private void InitPlot() {
 | |
|             if (SelectedGraphEntry?.GebundenGraph != null) {
 | |
|                 GebundenPlot = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry.GebundenGraph.DataX, SelectedGraphEntry.GebundenGraph.DataY, label: "Gebunden");
 | |
|                 GebundenPlot.LineColor = ColorGebunden;
 | |
|                 GebundenPlot.MarkerColor = ColorGebunden;
 | |
|                 GebundenPlot.MarkerSize = 9;
 | |
|             }
 | |
| 
 | |
|             DataPlot = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry!.DataGraph.DataX, SelectedGraphEntry!.DataGraph.DataY, label: "Ungebunden");
 | |
|             DataPlot.LineColor = ColorUngebunden;
 | |
|             DataPlot.MarkerColor = ColorUngebunden;
 | |
|             DataPlot.MarkerSize = 9;
 | |
| 
 | |
|             if (SelectedGraphEntry?.GebundenGraph == null) {
 | |
|                 ChangeActiveGraph(SelectedGraphEntry?.DataGraph);
 | |
|             }
 | |
| 
 | |
|             OechslePricePlot.RightClicked -= OechslePricePlot.DefaultRightClickEvent;
 | |
|             OechslePricePlot.Configuration.DoubleClickBenchmark = false;
 | |
|             //OechslePricePlot.Plot.XAxis.ManualTickSpacing(1);
 | |
|             OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1);
 | |
|             OechslePricePlot.Plot.SetAxisLimits(Math.Min(MinOechsle, MinOechsleGebunden) - 1, MaxOechsle + 1, -0.1, 2);
 | |
|             
 | |
|             OechslePricePlot.Plot.Layout(padding: 0);
 | |
|             OechslePricePlot.Plot.XAxis2.Layout(padding: 0);
 | |
|             OechslePricePlot.Plot.YAxis.Layout(padding: 0);
 | |
|             OechslePricePlot.Plot.YAxis2.Layout(padding: 0);
 | |
| 
 | |
|             HighlightedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0);
 | |
|             HighlightedPointPlot.Color = Color.Red;
 | |
|             HighlightedPointPlot.MarkerSize = 10;
 | |
|             HighlightedPointPlot.MarkerShape = MarkerShape.openCircle;
 | |
|             HighlightedPointPlot.IsVisible = false;
 | |
| 
 | |
|             PrimaryMarkedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0);
 | |
|             PrimaryMarkedPointPlot.Color = Color.Red;
 | |
|             PrimaryMarkedPointPlot.MarkerSize = 6;
 | |
|             PrimaryMarkedPointPlot.MarkerShape = MarkerShape.filledCircle;
 | |
|             PrimaryMarkedPointPlot.IsVisible = false;
 | |
| 
 | |
|             SecondaryMarkedPointPlot = OechslePricePlot.Plot.AddPoint(0, 0);
 | |
|             SecondaryMarkedPointPlot.Color = Color.Red;
 | |
|             SecondaryMarkedPointPlot.MarkerSize = 6;
 | |
|             SecondaryMarkedPointPlot.MarkerShape = MarkerShape.filledCircle;
 | |
|             SecondaryMarkedPointPlot.IsVisible = false;
 | |
| 
 | |
|             OechslePricePlot.Refresh();
 | |
| 
 | |
|             RefreshFreeZoom();
 | |
|             RefreshGradationLines();
 | |
|         }
 | |
| 
 | |
|         private void ResetPlot() {
 | |
|             PrimaryMarkedPoint = -1;
 | |
|             SecondaryMarkedPoint = -1;
 | |
|             ChangeActiveGraph(null);
 | |
|             HideGradationLines();
 | |
|             OechslePricePlot.Plot.Remove(DataPlot);
 | |
|             OechslePricePlot.Plot.Remove(GebundenPlot);
 | |
|             OechslePricePlot.Plot.Clear();
 | |
|             OechslePricePlot.Reset();
 | |
|             OechslePricePlot.Refresh();
 | |
|         }
 | |
| 
 | |
|         private void ChangeMarker(MarkerPlot point, bool visible, double x = 0, double y = 0) {
 | |
|             point.X = x;
 | |
|             point.Y = y;
 | |
|             point.IsVisible = visible;
 | |
|         }
 | |
| 
 | |
|         private void LinearIncreaseGraph(int begin, int end, double inc) {
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private void EnableActionButtons() {
 | |
|             if (PaymentVar.TestVariant) {
 | |
|                 LeftFlatButton.IsEnabled = true;
 | |
|                 RightFlatButton.IsEnabled = true;
 | |
|                 LinearIncreaseButton.IsEnabled = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void DisableActionButtons() {
 | |
|             LeftFlatButton.IsEnabled = false;
 | |
|             RightFlatButton.IsEnabled = false;
 | |
|             InterpolateButton.IsEnabled = false;
 | |
|             LinearIncreaseButton.IsEnabled = false;
 | |
|         }
 | |
| 
 | |
|         private void FreeZoomInput_Changed(object sender, RoutedEventArgs evt) {
 | |
|             RefreshFreeZoom();
 | |
|         }
 | |
| 
 | |
|         private void RefreshFreeZoom() {
 | |
|             if (FreeZoomInput.IsChecked == true) {
 | |
|                 UnlockZoom();
 | |
|             } else {
 | |
|                 LockZoom();
 | |
|             }
 | |
|             OechslePricePlot.Refresh();
 | |
|         }
 | |
| 
 | |
|         private void LockZoom() {
 | |
|             OechslePricePlot.Plot.XAxis.SetBoundary(MinOechsle - 1, MaxOechsle + 1);
 | |
|             OechslePricePlot.Plot.YAxis.SetBoundary(-0.1, 2);
 | |
|             OechslePricePlot.Plot.XAxis.SetZoomOutLimit(MaxOechsle - MinOechsle + 2);
 | |
|             OechslePricePlot.Plot.YAxis.SetZoomOutLimit(2.1);
 | |
|             OechslePricePlot.Plot.SetAxisLimits(MinOechsle - 1, MaxOechsle + 1, -0.1, 2);
 | |
|         }
 | |
| 
 | |
|         private void UnlockZoom() {
 | |
|             OechslePricePlot.Plot.XAxis.SetBoundary();
 | |
|             OechslePricePlot.Plot.YAxis.SetBoundary();
 | |
|             OechslePricePlot.Plot.XAxis.SetZoomOutLimit((MaxOechsle - MinOechsle) * 1.5);
 | |
|             OechslePricePlot.Plot.YAxis.SetZoomOutLimit(3.5);
 | |
|         }
 | |
| 
 | |
|         private void EnableOptionButtons() {
 | |
|             FreeZoomInput.IsEnabled = true;
 | |
|             GradationLinesInput.IsEnabled = true;
 | |
|             TooltipInput.IsEnabled = true;
 | |
|         }
 | |
| 
 | |
|         private void DisableOptionButtons() {
 | |
|             FreeZoomInput.IsEnabled = false;
 | |
|             GradationLinesInput.IsEnabled = false;
 | |
|             TooltipInput.IsEnabled = false;
 | |
|         }
 | |
| 
 | |
|         private void GradationLinesInput_Changed(object sender, RoutedEventArgs evt) {
 | |
|             RefreshGradationLines();
 | |
|         }
 | |
| 
 | |
|         private void RefreshGradationLines() {
 | |
|             if (GradationLinesInput.IsChecked == true && SelectedGraphEntry != null && !OechslePricePlot.Plot.GetPlottables().OfType<VLine>().Any()) {
 | |
|                 ShowGradationLines();
 | |
|                 ShowLegend();
 | |
|             } else if (GradationLinesInput.IsChecked == false) {
 | |
|                 HideGradationLines();
 | |
|                 HideLegend();
 | |
|             }
 | |
|             OechslePricePlot.Refresh();
 | |
|         }
 | |
| 
 | |
|         private void ShowGradationLines() {
 | |
|             OechslePricePlot.Plot.AddVerticalLine(68, Color.Red,    2, label: "68 °Oe (LDW)");
 | |
|             OechslePricePlot.Plot.AddVerticalLine(73, Color.Orange, 2, label: "73 °Oe (QUW)");
 | |
|             OechslePricePlot.Plot.AddVerticalLine(84, Color.Green,  2, label: "84 °Oe (KAB)");
 | |
|         }
 | |
| 
 | |
|         private void HideGradationLines() {
 | |
|             OechslePricePlot.Plot.Clear(typeof(VLine));
 | |
|         }
 | |
| 
 | |
|         private void ShowLegend() {
 | |
|             OechslePricePlot.Plot.Legend(true, Alignment.UpperLeft);
 | |
|         }
 | |
| 
 | |
|         private void HideLegend() {
 | |
|             OechslePricePlot.Plot.Legend(false, Alignment.UpperLeft);
 | |
|         }
 | |
| 
 | |
|         private void OechsleInput_TextChanged(object sender, TextChangedEventArgs evt) {
 | |
|             if (ActiveGraph == null || SelectedGraphEntry == null) {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             bool success = int.TryParse(OechsleInput.Text, out int oechsle);
 | |
| 
 | |
|             SecondaryMarkedPoint = -1;
 | |
|             ChangeMarker(SecondaryMarkedPointPlot, false);
 | |
| 
 | |
|             if (success) { 
 | |
|                 if (oechsle >= ActiveGraph.MinX && oechsle <= ActiveGraph.MaxX) {
 | |
|                     PrimaryMarkedPoint = oechsle - ActiveGraph.MinX;
 | |
|                     ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint));
 | |
| 
 | |
|                     PriceInput.Text = ActiveGraph.GetPriceAt(PrimaryMarkedPoint).ToString();
 | |
| 
 | |
|                     EnableActionButtons();
 | |
|                     OechslePricePlot.Render();
 | |
|                     EnableUnitTextBox(PriceInput);
 | |
|                     return;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             PrimaryMarkedPoint = -1;
 | |
|             //ChangeActiveGraph(null);
 | |
|             ChangeMarker(PrimaryMarkedPointPlot, false);
 | |
|             DisableActionButtons();
 | |
|             PriceInput.Text = "";
 | |
|             DisableUnitTextBox(PriceInput);
 | |
|             OechslePricePlot.Render();
 | |
|             DisableUnitTextBox(PriceInput);
 | |
|         }
 | |
| 
 | |
|         private void PriceInput_TextChanged(object sender, TextChangedEventArgs evt) {
 | |
|             if (PrimaryMarkedPoint != -1 && ActiveGraph != null) {
 | |
|                 bool success = double.TryParse(PriceInput.Text, out double price);
 | |
| 
 | |
|                 if (success) {
 | |
|                     ActiveGraph.SetPriceAt(PrimaryMarkedPoint, price);
 | |
|                     PrimaryMarkedPointPlot.Y = price;
 | |
|                     OechslePricePlot.Refresh();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void LeftFlatButton_Click(object sender, RoutedEventArgs evt) {
 | |
|             if (PrimaryMarkedPoint == -1 || ActiveGraph == null) {
 | |
|                 return;
 | |
|             }
 | |
|             ActiveGraph.FlattenGraphLeft(PrimaryMarkedPoint);
 | |
|             OechslePricePlot.Render();
 | |
|         }
 | |
| 
 | |
|         private void RightFlatButton_Click(object sender, RoutedEventArgs evt) {
 | |
|             if (PrimaryMarkedPoint == -1 || ActiveGraph == null) {
 | |
|                 return;
 | |
|             }
 | |
|             ActiveGraph.FlattenGraphRight(PrimaryMarkedPoint);
 | |
|             OechslePricePlot.Render();
 | |
|         }
 | |
| 
 | |
|         private void InterpolateButton_Click(object sender, RoutedEventArgs evt) {
 | |
|             if (PrimaryMarkedPoint == SecondaryMarkedPoint || PrimaryMarkedPoint == -1 || SecondaryMarkedPoint == -1 || ActiveGraph == null) {
 | |
|                 return;
 | |
|             }
 | |
|             ActiveGraph.InterpolateGraph(PrimaryMarkedPoint, SecondaryMarkedPoint);
 | |
|             OechslePricePlot.Render();
 | |
|         }
 | |
| 
 | |
|         private void LinearIncreaseButton_Click(object sender, RoutedEventArgs e) { 
 | |
|             if (PrimaryMarkedPoint == -1 || ActiveGraph == null) {
 | |
|                 return;
 | |
|             }
 | |
|             double? priceIncrease = Utils.ShowLinearPriceIncreaseDialog();
 | |
|             if (priceIncrease == null) {
 | |
|                 return;
 | |
|             }
 | |
|             ActiveGraph.LinearIncreaseGraphToEnd(PrimaryMarkedPoint, priceIncrease.Value);
 | |
|             OechslePricePlot.Render();
 | |
|         }
 | |
| 
 | |
|         private void OechslePricePlot_MouseDown(object sender, MouseEventArgs e) {
 | |
|             if (GraphList.SelectedItem == null) {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             if (HoverActive) {
 | |
|                 if (PaymentVar.TestVariant && Keyboard.IsKeyDown(Key.LeftCtrl)) {
 | |
|                     if (PrimaryMarkedPoint == -1 || ActiveGraph == null || ActiveGraph != Highlighted.graph) {
 | |
|                         return;
 | |
|                     }
 | |
|                     SecondaryMarkedPoint = Highlighted.index;
 | |
| 
 | |
|                     ChangeMarker(SecondaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(SecondaryMarkedPoint), ActiveGraph.GetPriceAt(SecondaryMarkedPoint));
 | |
| 
 | |
|                     InterpolateButton.IsEnabled = true;
 | |
| 
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 PrimaryMarkedPoint = Highlighted.index;
 | |
|                 ChangeActiveGraph(Highlighted.graph);
 | |
| 
 | |
|                 ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint));
 | |
| 
 | |
|                 OechsleInput.Text = Highlighted.graph.GetOechsleAt(Highlighted.index).ToString();
 | |
|                 PriceInput.Text = Highlighted.graph.GetPriceAt(Highlighted.index).ToString();
 | |
| 
 | |
|                 EnableActionButtons();
 | |
|             } else {
 | |
|                 PrimaryMarkedPoint = -1;
 | |
|                 SecondaryMarkedPoint = -1;
 | |
|                 if (SelectedGraphEntry!.GebundenGraph != null) {
 | |
|                     ChangeActiveGraph(null);
 | |
|                 }
 | |
|                 ChangeMarker(PrimaryMarkedPointPlot, false);
 | |
|                 ChangeMarker(SecondaryMarkedPointPlot, false);
 | |
| 
 | |
|                 OechsleInput.Text = "";
 | |
|                 PriceInput.Text = "";
 | |
|                 DisableUnitTextBox(PriceInput);
 | |
| 
 | |
|                 DisableActionButtons();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         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) {
 | |
|             if (GraphList.SelectedItem == null) {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             (double x, double y, int index)? mouseOnData = MouseOnPlot(DataPlot);
 | |
|             (double x, double y , int index)? mouseOnGebunden = MouseOnPlot(GebundenPlot);
 | |
| 
 | |
|             Highlighted = LastHighlighted;
 | |
| 
 | |
|             if (mouseOnData != null) {
 | |
|                 ChangeMarker(HighlightedPointPlot, true, mouseOnData.Value.x, mouseOnData.Value.y);
 | |
|                 HighlightedPointPlot.IsVisible = true;
 | |
|                 HoverChanged = true ^ HoverActive;
 | |
|                 HoverActive = true;
 | |
|                 HandleTooltip(mouseOnData.Value.x, mouseOnData.Value.y, mouseOnData.Value.index, SelectedGraphEntry!.DataGraph);
 | |
|             } else if (mouseOnGebunden != null) {
 | |
|                 ChangeMarker(HighlightedPointPlot, true, mouseOnGebunden.Value.x, mouseOnGebunden.Value.y);
 | |
|                 HighlightedPointPlot.IsVisible = true;
 | |
|                 HoverChanged = true ^ HoverActive;
 | |
|                 HoverActive = true;
 | |
|                 HandleTooltip(mouseOnGebunden.Value.x, mouseOnGebunden.Value.y, mouseOnGebunden.Value.index, SelectedGraphEntry!.GebundenGraph!);
 | |
|             } else {
 | |
|                 ChangeMarker(HighlightedPointPlot, false);
 | |
|                 HoverChanged = false ^ HoverActive;
 | |
|                 HoverActive = false;
 | |
|                 OechslePricePlot.Plot.Remove(TooltipPlot);
 | |
|                 OechslePricePlot.Render();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void HandleTooltip(double pointX, double pointY, int pointIndex, Graph g) {
 | |
|             if (LastHighlighted != Highlighted || HoverChanged) {
 | |
|                 OechslePricePlot.Plot.Remove(TooltipPlot);
 | |
|                 if (TooltipInput.IsChecked == true) {
 | |
|                     TooltipPlot = OechslePricePlot.Plot.AddTooltip($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, Season.Precision)}€/kg)", pointX, pointY);
 | |
|                 }
 | |
|                 LastHighlighted = (g, pointIndex);
 | |
|                 HoverChanged = false;
 | |
|                 OechslePricePlot.Render();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private int GetMaxGraphId() {
 | |
|             return GraphEntries.Count == 0 ? 0 : GraphEntries.Select(g => g.Id).Max();
 | |
|         }
 | |
| 
 | |
|         private void AddButton_Click(object sender, RoutedEventArgs e) {
 | |
|             GraphEntry newGraphEntry = new(GetMaxGraphId() + 1, Season.Precision, BillingData.CurveMode.Oe, MinOechsle, MinOechsleGebunden, MaxOechsle);
 | |
|             GraphEntries.Add(newGraphEntry);
 | |
|             GraphList.Items.Refresh();
 | |
|             GraphList.SelectedItem = newGraphEntry;
 | |
|         }
 | |
| 
 | |
|         private void CopyButton_Click(object sender, RoutedEventArgs e) {
 | |
|             if (SelectedGraphEntry == null) return;
 | |
| 
 | |
|             GraphEntry newGraphEntry = SelectedGraphEntry.Copy(GetMaxGraphId() + 1);
 | |
|             GraphEntries.Add(newGraphEntry);
 | |
|             GraphList.Items.Refresh();
 | |
|             GraphList.SelectedItem = newGraphEntry;
 | |
|         }
 | |
| 
 | |
|         private void DeleteButton_Click(object sender, RoutedEventArgs e) {
 | |
|             if (SelectedGraphEntry == null) return;
 | |
| 
 | |
|             var r = MessageBox.Show(
 | |
|                 $"Soll der Graph {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.Contracts}) wirklich gelöscht werden?",
 | |
|                 "Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
 | |
| 
 | |
|             if (r == MessageBoxResult.Yes) {
 | |
|                 GraphEntries.Remove(SelectedGraphEntry);
 | |
|                 GraphList.Items.Refresh();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private async void SaveButton_Click(object sender, RoutedEventArgs e) {
 | |
|             var origData = BillingData.FromJson(PaymentVar.Data);
 | |
|             var data = origData.FromGraphEntries(GraphEntries);
 | |
| 
 | |
|             EntityEntry<PaymentVar>? tr = null;
 | |
|             try {
 | |
|                 PaymentVar.Data = data.ToJsonString();
 | |
|                 tr = Context.Update(PaymentVar);
 | |
|                 await Context.SaveChangesAsync();
 | |
|                 LockContext = false;
 | |
|                 await App.HintContextChange();
 | |
|             } catch (Exception exc) {
 | |
|                 if (tr != null) await tr.ReloadAsync();
 | |
|                 var str = "Der Eintrag konnte nicht in der Datenbank gespeichert werden!\n\n" + exc.Message;
 | |
|                 if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
 | |
|                 MessageBox.Show(str, "Auszahlungsvariante speichern", MessageBoxButton.OK, MessageBoxImage.Error);
 | |
|             }
 | |
|             LockContext = true;
 | |
|         }
 | |
| 
 | |
|         private void EnableUnitTextBox(UnitTextBox u) {
 | |
|             if (PaymentVar.TestVariant) {
 | |
|                 u.IsEnabled = true;
 | |
|                 u.TextBox.IsReadOnly = false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void DisableUnitTextBox(UnitTextBox u) {
 | |
|             u.IsEnabled = false;
 | |
|             u.TextBox.IsReadOnly = true;
 | |
|         }
 | |
| 
 | |
|         private void ChangeActiveGraph(Graph? g) {
 | |
|             if (g != null && g == SelectedGraphEntry?.DataGraph) {
 | |
|                 EnableUnitTextBox(OechsleInput);
 | |
|                 ChangeLineWidth(DataPlot, 4);
 | |
|                 ChangeLineWidth(GebundenPlot, 1);
 | |
|             } else if (g != null && g == SelectedGraphEntry?.GebundenGraph) {
 | |
|                 EnableUnitTextBox(OechsleInput);
 | |
|                 ChangeLineWidth(GebundenPlot, 4);
 | |
|                 ChangeLineWidth(DataPlot, 1);
 | |
|             } else {
 | |
|                 DisableUnitTextBox(OechsleInput);
 | |
|                 DisableUnitTextBox(PriceInput);
 | |
|                 OechsleInput.Text = "";
 | |
|                 PriceInput.Text = "";
 | |
|                 ChangeLineWidth(DataPlot, 1);
 | |
|                 ChangeLineWidth(GebundenPlot, 1);
 | |
|             }
 | |
|             ActiveGraph = g;
 | |
|         }
 | |
| 
 | |
|         private void ChangeLineWidth(ScatterPlot? p, double lineWidth) {
 | |
|             if (p != null) {
 | |
|                 p.LineWidth = lineWidth;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void GraphList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
 | |
|             SelectedGraphEntry = GraphList.SelectedItem as GraphEntry;
 | |
|             RefreshInputs();
 | |
|         }
 | |
| 
 | |
|         private void PriceInput_LostFocus(object sender, RoutedEventArgs e) {
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private void OechsleInput_LostFocus(object sender, RoutedEventArgs e) {
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private void GebundenFlatBonus_TextChanged(object sender, TextChangedEventArgs e) {
 | |
|             var r = Validator.CheckDecimal(GebundenFlatBonus.TextBox, true, 2, 8);
 | |
|             if (r.IsValid) {
 | |
|                 SelectedGraphEntry?.SetGebundenFlatBonus(decimal.Parse(GebundenFlatBonus.Text));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void ContractInput_Changed(object sender, ItemSelectionChangedEventArgs e) {
 | |
|             if (FillingInputs) return;
 | |
|             if (e.IsSelected == true) {
 | |
|                 RemoveContractFromOtherGraphEntries(e.Item.ToString());
 | |
|             }
 | |
|             var r = ContractInput.SelectedItems.Cast<ContractSelection>();
 | |
|             SelectedGraphEntry!.Contracts = r.ToList();
 | |
|             GraphList.Items.Refresh();
 | |
|         }
 | |
| 
 | |
|         private void RemoveContractFromOtherGraphEntries(string? contract) {
 | |
|             if (contract == null) return;
 | |
|             foreach (var ge in GraphEntries) {
 | |
|                 if (ge != SelectedGraphEntry) {
 | |
|                     ge.Contracts.RemoveAll(c => c.Listing.Equals(contract));
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void AbgewertetInput_Changed(object sender, RoutedEventArgs e) {
 | |
|             if (SelectedGraphEntry == null) return;
 | |
|             SelectedGraphEntry.Abgewertet = AbgewertetInput.IsChecked == true;
 | |
|         }
 | |
| 
 | |
|         private void GebundenType_Checked(object sender, RoutedEventArgs e) {
 | |
|             if (FillingInputs) return;
 | |
|             if (SelectedGraphEntry == null) {
 | |
|                 DisableUnitTextBox(GebundenFlatBonus);
 | |
|                 return;
 | |
|             } else if (GebundenTypeNone.IsChecked == true) {
 | |
|                 SelectedGraphEntry.SetGebundenFlatBonus(null);
 | |
|                 SelectedGraphEntry.RemoveGebundenGraph();
 | |
|                 DisableUnitTextBox(GebundenFlatBonus);
 | |
|                 RefreshInputs();
 | |
|             } else if (GebundenTypeFixed.IsChecked == true) {
 | |
|                 SelectedGraphEntry.SetGebundenFlatBonus(0);
 | |
|                 SelectedGraphEntry.RemoveGebundenGraph();
 | |
|                 EnableUnitTextBox(GebundenFlatBonus);
 | |
|                 RefreshInputs();
 | |
|             } else if (GebundenTypeGraph.IsChecked == true) {
 | |
|                 GebundenFlatBonus.Text = "";
 | |
|                 SelectedGraphEntry.SetGebundenFlatBonus(null);
 | |
|                 SelectedGraphEntry.AddGebundenGraph();
 | |
|                 DisableUnitTextBox(GebundenFlatBonus);
 | |
|                 RefreshInputs();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |