651 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			651 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Drawing;
 | 
						|
using System.Linq;
 | 
						|
using System.Text.Json.Nodes;
 | 
						|
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;
 | 
						|
 | 
						|
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;
 | 
						|
        private readonly 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 const int MinOechsle = 50;
 | 
						|
        private const int MaxOechsle = 140;
 | 
						|
 | 
						|
        private List<GraphEntry> GraphEntries = [];
 | 
						|
        private GraphEntry? SelectedGraphEntry;
 | 
						|
 | 
						|
        public ChartWindow(int year, int avnr) {
 | 
						|
            InitializeComponent();
 | 
						|
            Year = year;
 | 
						|
            AvNr = avnr;
 | 
						|
            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() {
 | 
						|
            await Context.PaymentVariants.LoadAsync();
 | 
						|
 | 
						|
            var attrVariants = Context.DeliveryParts
 | 
						|
                .Where(d => d.Year == Year)
 | 
						|
                .Select(d => $"{d.SortId}{d.AttrId}")
 | 
						|
                .Distinct()
 | 
						|
                .ToList()
 | 
						|
                .Union(Context.WineVarieties.Select(v => v.SortId))
 | 
						|
                .Order()
 | 
						|
                .ToList();
 | 
						|
            var data = EditBillingData.FromJson(PaymentVar.Data, attrVariants);
 | 
						|
            GraphEntries = [ ..data.GetPaymentGraphEntries(Context), ..data.GetQualityGraphEntries(Context)];
 | 
						|
 | 
						|
            var contracts = ContractSelection.GetContractsForYear(Context, Year);
 | 
						|
            ControlUtils.RenewItemsSource(ContractInput, contracts, g => (g as ContractSelection)?.ToString());
 | 
						|
            ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.Id, null, ControlUtils.RenewSourceDefault.First);
 | 
						|
 | 
						|
            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;
 | 
						|
                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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        private void FillInputs() {
 | 
						|
            GraphNum.Text = SelectedGraphEntry?.Id.ToString();
 | 
						|
 | 
						|
            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;
 | 
						|
        }
 | 
						|
 | 
						|
        protected override async Task OnRenewContext() {
 | 
						|
            await RefreshGraphList();
 | 
						|
        }
 | 
						|
 | 
						|
        private void InitPlot() {
 | 
						|
            if (SelectedGraphEntry?.GebundenGraph != null) {
 | 
						|
                GebundenPlot = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry.GebundenGraph.DataX, SelectedGraphEntry.GebundenGraph.DataY);
 | 
						|
                GebundenPlot.LineColor = ColorGebunden;
 | 
						|
                GebundenPlot.MarkerColor = ColorGebunden;
 | 
						|
                GebundenPlot.MarkerSize = 9;
 | 
						|
            }
 | 
						|
 | 
						|
            DataPlot = OechslePricePlot.Plot.AddScatter(SelectedGraphEntry!.DataGraph.DataX, SelectedGraphEntry!.DataGraph.DataY);
 | 
						|
            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(MinOechsle - 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 Oechsle (LDW)");
 | 
						|
            OechslePricePlot.Plot.AddVerticalLine(73, Color.Orange, 2, label: "73 Oechsle (QUW)");
 | 
						|
            OechslePricePlot.Plot.AddVerticalLine(84, Color.Green, 2, label: "84 Oechsle (KAB)");
 | 
						|
        }
 | 
						|
 | 
						|
        private void HideGradationLines() {
 | 
						|
            OechslePricePlot.Plot.Clear(typeof(VLine));
 | 
						|
        }
 | 
						|
 | 
						|
        private void ShowLegend() {
 | 
						|
            OechslePricePlot.Plot.Legend(true, Alignment.UpperRight);
 | 
						|
        }
 | 
						|
 | 
						|
        private void HideLegend() {
 | 
						|
            OechslePricePlot.Plot.Legend(false, Alignment.UpperRight);
 | 
						|
        }
 | 
						|
 | 
						|
        private void OechsleInput_TextChanged(object sender, TextChangedEventArgs evt) {
 | 
						|
            if (ActiveGraph == null) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            bool success = int.TryParse(OechsleInput.Text, out int oechsle);
 | 
						|
 | 
						|
            SecondaryMarkedPoint = -1;
 | 
						|
            ChangeMarker(SecondaryMarkedPointPlot, false);
 | 
						|
 | 
						|
            if (success) {
 | 
						|
                if (oechsle >= MinOechsle && oechsle <= MaxOechsle) {
 | 
						|
                    PrimaryMarkedPoint = oechsle - MinOechsle;
 | 
						|
                    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, 4)}€/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, BillingData.CurveMode.Oe, MinOechsle, 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) {
 | 
						|
            await SaveGraphs();
 | 
						|
        }
 | 
						|
 | 
						|
        private async Task SaveGraphs() {
 | 
						|
            var payment = new JsonObject();
 | 
						|
            var curves = new JsonArray();
 | 
						|
 | 
						|
            foreach (var entry in GraphEntries) {
 | 
						|
                curves.Add(entry.ToJson());
 | 
						|
                foreach (var contract in entry.Contracts) {
 | 
						|
                    payment[$"{contract.Variety?.SortId}/{contract.Attribute?.AttrId}"] = $"curve:{entry.Id}";
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            var data = new JsonObject {
 | 
						|
                ["mode"] = "elwig",
 | 
						|
                ["version"] = 1,
 | 
						|
                ["payment"] = payment,
 | 
						|
                ["curves"] = curves
 | 
						|
            };
 | 
						|
 | 
						|
 | 
						|
            MessageBox.Show(data.ToJsonString());
 | 
						|
 | 
						|
            EntityEntry<PaymentVar>? tr = null;
 | 
						|
            try {
 | 
						|
                PaymentVar.Data = data.ToJsonString();
 | 
						|
                tr = Context.Update(PaymentVar);
 | 
						|
 | 
						|
                await Context.SaveChangesAsync();
 | 
						|
                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, "Graph speichern", MessageBoxButton.OK, MessageBoxImage.Error);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        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();
 | 
						|
 | 
						|
            //var x = OechslePricePlot.Plot.GetPlottables().OfType<ScatterPlot>();
 | 
						|
            //MessageBox.Show($"SelectionChanged\nLength: {x.ToList().Count}, Ys: {string.Join(", ", ((ScatterPlot)x.First()).Ys)}");
 | 
						|
        }
 | 
						|
 | 
						|
        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, RoutedEventArgs e) {
 | 
						|
            var r = ContractInput.SelectedItems.Cast<ContractSelection>();
 | 
						|
            SelectedGraphEntry!.Contracts = r.ToList();
 | 
						|
            // FIXME when using arrow keys, selection does not work nicely
 | 
						|
            GraphList.Items.Refresh();
 | 
						|
        }
 | 
						|
 | 
						|
        private void GebundenType_Checked(object sender, RoutedEventArgs e) {
 | 
						|
            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();
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |