Files
elwig/Elwig/Windows/ChartWindow.xaml.cs
Lorenz Stechauner 95927c3f1a
All checks were successful
Test / Run tests (push) Successful in 2m42s
ChartWindow: Remove old commented-out code
2025-01-16 09:09:28 +01:00

821 lines
35 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Models.Entities;
using ScottPlot.Plottables;
using ScottPlot;
namespace Elwig.Windows {
public partial class ChartWindow : ContextWindow {
public static readonly Color ColorUngebunden = Colors.Blue;
public static readonly Color ColorGebunden = Colors.Gold;
public readonly int Year;
public readonly int AvNr;
public Season Season;
public string CurrencySymbol;
private PaymentVar PaymentVar;
private bool HasChanged = false;
private bool Updating = false;
private Scatter DataPlot;
private Scatter? GebundenPlot;
private Marker HighlightedPointPlot;
private Marker PrimaryMarkedPointPlot;
private Marker SecondaryMarkedPointPlot;
private Text TooltipPlot;
private static readonly LegendItem
UngebundenLegend = new() {
LabelText = "Ungebunden", LineWidth = 1, LineColor = ColorUngebunden,
MarkerStyle = new(MarkerShape.FilledCircle, 5, ColorUngebunden)
},
GebundenLegend = new() {
LabelText = "Gebunden", LineWidth = 1, LineColor = ColorGebunden,
MarkerStyle = new(MarkerShape.FilledCircle, 5, ColorGebunden)
},
LdwLegend = new() {
LabelText = "68 °Oe (LDW)", LineWidth = 2, LineColor = Colors.Red, MarkerStyle = MarkerStyle.None
},
QuwLegend = new() {
LabelText = "73 °Oe (QUW)", LineWidth = 2, LineColor = Colors.Orange, MarkerStyle = MarkerStyle.None
},
KabLegend = new() {
LabelText = "84 °Oe (KAB)", LineWidth = 2, LineColor = Colors.Green, MarkerStyle = MarkerStyle.None
};
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 List<GraphEntry> GraphEntries = [];
private GraphEntry? SelectedGraphEntry => (GraphEntry)GraphList.SelectedItem;
private List<Varibute> Vaributes = [];
private bool AllVaributesAssigned => Vaributes.All(v => v.AssignedGraphId != null);
private bool AllVaributesAssignedAbgew => Vaributes.All(v => v.AssignedAbgewGraphId != null);
public ChartWindow(int year, int avnr) {
InitializeComponent();
Year = year;
AvNr = avnr;
using var ctx = new AppDbContext();
Season = ctx.Seasons.Find(year) ?? throw new ArgumentException("Season not found");
CurrencySymbol = Season.Currency.Symbol ?? Season.Currency.Code;
PriceInput.Unit = $"{CurrencySymbol}/kg";
GebundenFlatBonus.Unit = $"{CurrencySymbol}/kg";
PaymentVar = ctx.PaymentVariants.Find(year, avnr) ?? throw new ArgumentException("PaymentVar not found");
Title = $"{PaymentVar?.Name} - Lese {year} - Elwig";
LockContext = true;
}
private void Window_Loaded(object sender, RoutedEventArgs evt) {
}
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(AppDbContext ctx) {
PaymentVar = await ctx.PaymentVariants.FindAsync(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found");
Season = await ctx.Seasons.FindAsync(Year) ?? throw new ArgumentException("Season not found");
CurrencySymbol = Season.Currency.Symbol ?? Season.Currency.Code;
PriceInput.Unit = $"{CurrencySymbol}/kg";
GebundenFlatBonus.Unit = $"{CurrencySymbol}/kg";
try {
var data = EditBillingData.FromJson(PaymentVar.Data, Utils.GetVaributes(ctx, Year));
var paymentEntries = data.GetPaymentGraphEntries(ctx, Season);
GraphEntries = [
..paymentEntries,
..data.GetQualityGraphEntries(ctx, Season, paymentEntries.Any() ? paymentEntries.Max(e => e.Id) : 0)
];
} catch (KeyNotFoundException ex) {
var key = ex.Message.Split('\'')[1].Split('\'')[0];
MessageBox.Show($"Fehler beim Laden der Auszahlungsvariante:\n\n" +
$"Mit unbekanntem Attribut '{key}' kann nicht umgegangen werden.", "Fehler",
MessageBoxButton.OK, MessageBoxImage.Error);
} catch (ArgumentException) {
MessageBox.Show($"Fehler beim Laden der Auszahlungsvariante:\n\n" +
$"Die Daten der Auszahlungsvariante entsprechen nicht dem benötigtem Format.", "Fehler",
MessageBoxButton.OK, MessageBoxImage.Error);
} catch (Exception ex) {
MessageBox.Show("Fehler beim Laden der Auszahlungsvariante:\n\n" + ex.Message, "Fehler",
MessageBoxButton.OK, MessageBoxImage.Error);
}
Vaributes = Utils.GetVaributeList(ctx, Year);
GraphEntries.ForEach(e => {
e.Vaributes.ForEach(v => {
var found = Vaributes.Find(a => a.Variety?.SortId == v.Variety?.SortId && a.Attribute?.AttrId == v.Attribute?.AttrId && a.Cultivation?.CultId == v.Cultivation?.CultId);
if (found == null) return;
if (e.Abgewertet) {
found.AssignedAbgewGraphId = e.Id;
} else {
found.AssignedGraphId = e.Id;
}
});
});
FillingInputs = true;
ControlUtils.RenewItemsSource(VaributeInput, Vaributes);
FillingInputs = false;
ControlUtils.RenewItemsSource(GraphList, GraphEntries, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
RefreshInputs();
}
private void RefreshInputs() {
ResetPlot();
if (SelectedGraphEntry != null) {
CopyButton.IsEnabled = true;
DeleteButton.IsEnabled = true;
EnableTextBox(OechsleInput);
GebInput.IsEnabled = SelectedGraphEntry?.GebundenGraph != null;
GebundenTypeFixed.IsEnabled = true;
GebundenTypeGraph.IsEnabled = true;
GebundenTypeNone.IsEnabled = true;
VaributeInput.IsEnabled = true;
AbgewertetInput.IsEnabled = true;
EnableOptionButtons();
FillInputs();
} else {
CopyButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
DisableTextBox(OechsleInput);
GebInput.IsEnabled = false;
DisableOptionButtons();
}
if (!PaymentVar.TestVariant) {
AddButton.IsEnabled = false;
CopyButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
DisableTextBox(PriceInput);
GebundenTypeFixed.IsEnabled = false;
GebundenTypeGraph.IsEnabled = false;
GebundenTypeNone.IsEnabled = false;
VaributeInput.IsEnabled = false;
AbgewertetInput.IsEnabled = false;
}
GC.Collect();
}
private void FillInputs() {
FillingInputs = true;
AbgewertetInput.IsChecked = SelectedGraphEntry?.Abgewertet;
if (SelectedGraphEntry?.GebundenFlatBonus is double bonus) {
GebundenTypeFixed.IsChecked = true;
GebundenFlatBonus.Text = $"{bonus}";
} else if (SelectedGraphEntry?.GebundenGraph != null) {
GebundenTypeGraph.IsChecked = true;
GebundenFlatBonus.Text = "";
} else {
GebundenTypeNone.IsChecked = true;
GebundenFlatBonus.Text = "";
}
ControlUtils.SelectItems(VaributeInput, SelectedGraphEntry?.Vaributes ?? []);
InitPlot();
ChangeActiveGraph(SelectedGraphEntry?.DataGraph);
OechsleInput.Text = "73";
OechslePricePlot.IsEnabled = true;
FillingInputs = false;
}
protected override async Task OnRenewContext(AppDbContext ctx) {
await RefreshGraphList(ctx);
}
private void InitPlot() {
RefreshGradationLines();
if (SelectedGraphEntry?.GebundenGraph != null) {
GebundenPlot = OechslePricePlot.Plot.Add.Scatter(SelectedGraphEntry.GebundenGraph.DataX, SelectedGraphEntry.GebundenGraph.DataY);
GebundenPlot.LineStyle.Color = ColorGebunden;
GebundenPlot.Color = ColorGebunden;
GebundenPlot.MarkerStyle = new MarkerStyle(MarkerShape.FilledCircle, 9, ColorGebunden);
}
DataPlot = OechslePricePlot.Plot.Add.Scatter(SelectedGraphEntry!.DataGraph.DataX, SelectedGraphEntry!.DataGraph.DataY);
DataPlot.LineStyle.Color = ColorUngebunden;
DataPlot.Color = ColorUngebunden;
DataPlot.MarkerStyle = new MarkerStyle(MarkerShape.FilledCircle, 9, ColorUngebunden);
OechslePricePlot.Plot.Axes.SetLimits(Math.Min(GraphEntry.MinX, GraphEntry.MinXGeb) - 1, GraphEntry.MaxX + 1, -0.1, 1.5);
HighlightedPointPlot = OechslePricePlot.Plot.Add.Marker(0, 0, MarkerShape.OpenCircle, 10, Colors.Red);
HighlightedPointPlot.IsVisible = false;
PrimaryMarkedPointPlot = OechslePricePlot.Plot.Add.Marker(0, 0, MarkerShape.FilledCircle, 6, Colors.Red);
PrimaryMarkedPointPlot.IsVisible = false;
SecondaryMarkedPointPlot = OechslePricePlot.Plot.Add.Marker(0, 0, MarkerShape.FilledCircle, 6, Colors.Red);
SecondaryMarkedPointPlot.IsVisible = false;
OechslePricePlot.Refresh();
RefreshFreeZoom();
OechslePricePlot.Refresh();
}
private void ResetPlot() {
PrimaryMarkedPoint = -1;
SecondaryMarkedPoint = -1;
ChangeActiveGraph(null);
HideGradationLines();
OechslePricePlot.Plot.Remove(DataPlot);
if (GebundenPlot != null) {
OechslePricePlot.Plot.Remove(GebundenPlot);
GebundenPlot = null;
}
OechslePricePlot.Plot.Clear();
OechslePricePlot.Reset();
OechslePricePlot.Refresh();
}
private void ChangeMarker(Marker point, bool visible, double x = 0, double y = 0) {
point.Location = new Coordinates(x, y);
point.IsVisible = visible;
}
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() {
ScottPlot.AxisRules.MaximumBoundary BoundaryRule = new(
xAxis: OechslePricePlot.Plot.Axes.Bottom,
yAxis: OechslePricePlot.Plot.Axes.Left,
limits: new AxisLimits(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, 1.5);
}
private void UnlockZoom() {
ScottPlot.AxisRules.MaximumSpan SpanRule = new(
xAxis: OechslePricePlot.Plot.Axes.Bottom,
yAxis: OechslePricePlot.Plot.Axes.Left,
xSpan: (GraphEntry.MaxX - GraphEntry.MinX) * 1.5,
ySpan: 3.5);
OechslePricePlot.Plot.Axes.Rules.Clear();
OechslePricePlot.Plot.Axes.Rules.Add(SpanRule);
}
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.PlottableList.OfType<VerticalLine>().Any()) {
ShowGradationLines();
ShowLegend();
} else if (GradationLinesInput.IsChecked == false) {
HideGradationLines();
HideLegend();
}
OechslePricePlot.Refresh();
}
private void ShowGradationLines() {
OechslePricePlot.Plot.Add.VerticalLine(68, 2, Colors.Red);
OechslePricePlot.Plot.Add.VerticalLine(73, 2, Colors.Orange);
OechslePricePlot.Plot.Add.VerticalLine(84, 2, Colors.Green);
}
private void HideGradationLines() {
OechslePricePlot.Plot.PlottableList.RemoveAll(p => p is VerticalLine);
}
private void ShowLegend() {
OechslePricePlot.Plot.Legend.Alignment = 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() {
OechslePricePlot.Plot.Legend.IsVisible = false;
OechslePricePlot.Plot.Legend.ManualItems.Clear();
}
private void UpdateSelectedPoint() {
if (ActiveGraph == null || SelectedGraphEntry == null)
return;
SecondaryMarkedPoint = -1;
ChangeMarker(SecondaryMarkedPointPlot, false);
if (int.TryParse(OechsleInput.Text, out int oe)) {
if (oe >= ActiveGraph.MinX && oe <= ActiveGraph.MaxX) {
PrimaryMarkedPoint = oe - ActiveGraph.MinX;
ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint));
PriceInput.Text = Math.Round(ActiveGraph.GetPriceAt(PrimaryMarkedPoint), Season.Precision).ToString();
EnableActionButtons();
OechslePricePlot.Refresh();
EnableTextBox(PriceInput);
return;
}
}
PrimaryMarkedPoint = -1;
ChangeMarker(PrimaryMarkedPointPlot, false);
DisableActionButtons();
PriceInput.Text = "";
DisableTextBox(PriceInput);
OechslePricePlot.Refresh();
DisableTextBox(PriceInput);
}
private void OechsleInput_TextChanged(object sender, TextChangedEventArgs evt) {
UpdateSelectedPoint();
}
private void GebInput_Changed(object sender, RoutedEventArgs evt) {
if (Updating)
return;
var sel = GebInput.IsChecked == true ? SelectedGraphEntry?.GebundenGraph : SelectedGraphEntry?.DataGraph;
if (sel != ActiveGraph) ChangeActiveGraph(sel);
UpdateSelectedPoint();
}
private void PriceInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (PrimaryMarkedPoint != -1 && ActiveGraph != null && PriceInput.IsKeyboardFocusWithin == true) {
var res = Validator.CheckDecimal(PriceInput, true, 2, Season.Precision);
if (res.IsValid && double.TryParse(PriceInput.Text, out double price)) {
ActiveGraph.SetPriceAt(PrimaryMarkedPoint, price);
PrimaryMarkedPointPlot.Location = new Coordinates(PrimaryMarkedPointPlot.Location.X, price);
SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed();
}
}
}
private void LeftFlatButton_Click(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPoint == -1 || ActiveGraph == null) {
return;
}
ActiveGraph.FlattenGraphLeft(PrimaryMarkedPoint);
SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed();
}
private void RightFlatButton_Click(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPoint == -1 || ActiveGraph == null) {
return;
}
ActiveGraph.FlattenGraphRight(PrimaryMarkedPoint);
SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed();
}
private void InterpolateButton_Click(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPoint == SecondaryMarkedPoint || PrimaryMarkedPoint == -1 || SecondaryMarkedPoint == -1 || ActiveGraph == null) {
return;
}
ActiveGraph.InterpolateGraph(PrimaryMarkedPoint, SecondaryMarkedPoint);
SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed();
}
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);
SetHasChanged();
OechslePricePlot.Refresh();
CheckGebundenTypeFixed();
}
private void OechslePricePlot_MouseDown(object sender, MouseEventArgs e) {
if (GraphList.SelectedItem == null)
return;
if (HoverActive) {
if (PaymentVar.TestVariant && Keyboard.IsKeyDown(System.Windows.Input.Key.LeftCtrl)) {
if (SecondaryMarkedPoint == -1 || ActiveGraph == null || ActiveGraph != Highlighted.Graph)
return;
SecondaryMarkedPoint = Highlighted.Index;
ChangeMarker(SecondaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(SecondaryMarkedPoint), ActiveGraph.GetPriceAt(SecondaryMarkedPoint));
InterpolateButton.IsEnabled = true;
return;
}
Updating = true;
PrimaryMarkedPoint = Highlighted.Index;
if (ActiveGraph != Highlighted.Graph)
ChangeActiveGraph(Highlighted.Graph);
Updating = false;
if (PrimaryMarkedPoint == -1 || ActiveGraph == null)
return;
ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint));
Updating = true;
OechsleInput.Text = Highlighted.Graph!.GetOechsleAt(Highlighted.Index).ToString();
GebInput.IsChecked = Highlighted.Graph == SelectedGraphEntry?.GebundenGraph;
PriceInput.Text = Math.Round(Highlighted.Graph.GetPriceAt(Highlighted.Index), Season.Precision).ToString();
Updating = false;
EnableActionButtons();
} else {
PrimaryMarkedPoint = -1;
SecondaryMarkedPoint = -1;
if (SelectedGraphEntry!.GebundenGraph != null) {
ChangeActiveGraph(null);
}
ChangeMarker(PrimaryMarkedPointPlot, false);
ChangeMarker(SecondaryMarkedPointPlot, false);
OechsleInput.Text = "";
GebInput.IsChecked = false;
PriceInput.Text = "";
DisableTextBox(PriceInput);
DisableActionButtons();
}
}
private void OechslePricePlot_MouseMove(object sender, MouseEventArgs e) {
MouseChange(e);
}
private void OechslePricePlot_MouseWheel(object sender, MouseWheelEventArgs e) {
MouseChange(e);
}
private Coordinates GetMouseCoordinates(Point p) {
Pixel px = new(p.X, p.Y);
var source = PresentationSource.FromVisual(this);
if (source?.CompositionTarget != null) {
var matrix = source.CompositionTarget.TransformToDevice;
px.X *= (float)matrix.M11;
px.Y *= (float)matrix.M22;
}
return OechslePricePlot.Plot.GetCoordinates(px);
}
private void MouseChange(MouseEventArgs e) {
if (GraphList.SelectedItem == null) {
return;
}
var mouseOnData = MouseOnPlot(DataPlot, GetMouseCoordinates(e.GetPosition(OechslePricePlot)));
var mouseOnGebunden = MouseOnPlot(GebundenPlot, GetMouseCoordinates(e.GetPosition(OechslePricePlot)));
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, e.GetPosition(OechslePricePlot), e is MouseWheelEventArgs);
} 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!, e.GetPosition(OechslePricePlot), e is MouseWheelEventArgs);
} else {
ChangeMarker(HighlightedPointPlot, false);
HoverChanged = false ^ HoverActive;
HoverActive = false;
OechslePricePlot.Plot.PlottableList.Remove(TooltipPlot);
OechslePricePlot.Refresh();
}
}
private (double X, double Y, int Index)? MouseOnPlot(Scatter? plot, Coordinates c) {
if (plot == null)
return null;
OechslePricePlot.Refresh();
DataPoint nearestPoint = plot.Data.GetNearest(c, OechslePricePlot.Plot.LastRender, 5);
return nearestPoint.IsReal ? (nearestPoint.X, nearestPoint.Y, nearestPoint.Index) : 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) {
Coordinates mouseLocation = GetMouseCoordinates(new(p.X, p.Y - 30));
TooltipPlot = OechslePricePlot.Plot.Add.Text($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, Season.Precision)} {CurrencySymbol}/kg", mouseLocation.X, mouseLocation.Y);
TooltipPlot.LabelFontSize = 12;
TooltipPlot.LabelBold = true;
TooltipPlot.LabelBorderColor = Colors.Black;
TooltipPlot.LabelBorderWidth = 2;
TooltipPlot.LabelBackgroundColor = Colors.White;
TooltipPlot.LabelPadding = 10;
TooltipPlot.LabelAlignment = Alignment.MiddleLeft;
}
LastHighlighted = (g, pointIndex);
HoverChanged = false;
OechslePricePlot.Refresh();
}
}
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);
GraphEntries.Add(newGraphEntry);
SetHasChanged();
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);
SetHasChanged();
GraphList.Items.Refresh();
GraphList.SelectedItem = newGraphEntry;
}
private void DeleteButton_Click(object sender, RoutedEventArgs e) {
if (SelectedGraphEntry == null) return;
var r = MessageBox.Show(
$"Soll die Kurve {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.VaributeStringSimple}) wirklich gelöscht werden?",
"Kurve löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r == MessageBoxResult.Yes) {
GraphEntries.Remove(SelectedGraphEntry);
SetHasChanged();
GraphList.Items.Refresh();
OechslePricePlot.IsEnabled = false;
}
}
private async void SaveButton_Click(object sender, RoutedEventArgs e) {
SaveButton.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
try {
using (var ctx = new AppDbContext()) {
var origData = BillingData.FromJson(PaymentVar.Data);
var data = BillingData.FromGraphEntries(GraphEntries, origData, Utils.GetVaributes(ctx, Year),
AllVaributesAssigned, AllVaributesAssignedAbgew);
PaymentVar.Data = data.ToJsonString();
ctx.Update(PaymentVar);
await ctx.SaveChangesAsync();
}
LockContext = false;
App.HintContextChange();
} catch (Exception exc) {
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);
SaveButton.IsEnabled = true;
return;
} finally {
Mouse.OverrideCursor = null;
}
LockContext = true;
SetHasChanged(false);
}
private void EnableTextBox(TextBox u) {
if (PaymentVar.TestVariant || u == OechsleInput) {
u.IsEnabled = true;
u.IsReadOnly = false;
}
}
private void DisableTextBox(TextBox u) {
u.IsEnabled = false;
u.IsReadOnly = true;
}
private void ChangeActiveGraph(Graph? g) {
if (g != null && g == SelectedGraphEntry?.DataGraph) {
EnableTextBox(OechsleInput);
if (SelectedGraphEntry?.GebundenGraph != null) ChangeLineWidth(DataPlot, 4);
ChangeLineWidth(GebundenPlot, 1);
GebInput.IsEnabled = SelectedGraphEntry?.GebundenGraph != null;
GebInput.IsChecked = false;
} else if (g != null && g == SelectedGraphEntry?.GebundenGraph) {
EnableTextBox(OechsleInput);
ChangeLineWidth(GebundenPlot, 4);
ChangeLineWidth(DataPlot, 1);
GebInput.IsEnabled = SelectedGraphEntry?.GebundenGraph != null;
GebInput.IsChecked = true;
} else {
DisableTextBox(OechsleInput);
DisableTextBox(PriceInput);
OechsleInput.Text = "";
GebInput.IsEnabled = false;
GebInput.IsChecked = false;
PriceInput.Text = "";
ChangeLineWidth(DataPlot, 1);
ChangeLineWidth(GebundenPlot, 1);
}
ActiveGraph = g;
}
private void ChangeLineWidth(Scatter? p, double lineWidth) {
if (p != null) {
p.LineWidth = (float)lineWidth;
}
}
private void GraphList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
RefreshInputs();
}
private void GebundenFlatBonus_TextChanged(object sender, TextChangedEventArgs e) {
if (FillingInputs) return;
var r = Validator.CheckDecimal(GebundenFlatBonus, true, 2, Season.Precision);
if (r.IsValid && SelectedGraphEntry != null) {
SelectedGraphEntry.GebundenFlatBonus = double.Parse(GebundenFlatBonus.Text);
ResetPlot();
InitPlot();
}
}
private void VaributeInput_Changed(object sender, SelectionChangedEventArgs evt) {
if (FillingInputs) return;
var isOpen = VaributeInput.IsDropDownOpen;
foreach (var i in evt.AddedItems) {
if (i is not Varibute v) continue;
if (RemoveVaributeFromOthers(v.ToString())) {
if (AbgewertetInput.IsChecked == true) {
v.AssignedAbgewGraphId = SelectedGraphEntry?.Id;
} else {
v.AssignedGraphId = SelectedGraphEntry?.Id;
}
} else {
VaributeInput.SelectedItems.Remove(v);
}
}
foreach (var i in evt.RemovedItems) {
if (i is not Varibute v) continue;
if (AbgewertetInput.IsChecked == true) {
v.AssignedAbgewGraphId = null;
} else {
v.AssignedGraphId = null;
}
}
SelectedGraphEntry!.Vaributes = VaributeInput.SelectedItems.Cast<Varibute>().ToList();
SetHasChanged();
GraphList.Items.Refresh();
VaributeInput.Items.Refresh();
VaributeInput.IsDropDownOpen = isOpen;
}
private bool RemoveVaributeFromOthers(string? varibute) {
if (varibute == null) return true;
foreach (var ge in GraphEntries) {
if (ge != SelectedGraphEntry && ge.Abgewertet == SelectedGraphEntry?.Abgewertet) {
var toRemove = ge.Vaributes.Where(c => c.Listing.Equals(varibute)).ToList();
if (toRemove.Count == 0) continue;
var r = MessageBox.Show($"Achtung: {string.Join(", ", toRemove)} ist bereits in Kurve {ge.Id} in Verwendung!\nSoll die Zuweisung dort entfernt werden?", "Entfernen bestätigen",
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r != MessageBoxResult.Yes) {
return false;
}
ge.Vaributes.RemoveAll(c => c.Listing.Equals(varibute));
}
}
return true;
}
private void AbgewertetInput_Changed(object sender, RoutedEventArgs e) {
if (FillingInputs) return;
if (SelectedGraphEntry == null) return;
SelectedGraphEntry.Abgewertet = AbgewertetInput.IsChecked == true;
SetHasChanged();
GraphList.Items.Refresh();
}
private void GebundenType_Checked(object sender, RoutedEventArgs e) {
if (FillingInputs) return;
if (SelectedGraphEntry == null) {
DisableTextBox(GebundenFlatBonus);
return;
}
if (GebundenTypeNone.IsChecked == true) {
SelectedGraphEntry.RemoveGebundenGraph();
DisableTextBox(GebundenFlatBonus);
} else if (GebundenTypeFixed.IsChecked == true) {
SelectedGraphEntry.GebundenFlatBonus = double.TryParse(GebundenFlatBonus.Text, out var val) ? val : 0.1;
SelectedGraphEntry.AddGebundenGraph();
EnableTextBox(GebundenFlatBonus);
} else if (GebundenTypeGraph.IsChecked == true) {
SelectedGraphEntry.AddGebundenGraph();
DisableTextBox(GebundenFlatBonus);
}
SetHasChanged();
RefreshInputs();
}
private void CheckGebundenTypeFixed() {
FillingInputs = true;
if (SelectedGraphEntry?.GebundenFlatBonus is double bonus) {
GebundenTypeFixed.IsChecked = true;
GebundenFlatBonus.Text = $"{bonus}";
EnableTextBox(GebundenFlatBonus);
} else if (SelectedGraphEntry?.GebundenGraph != null) {
GebundenTypeGraph.IsChecked = true;
GebundenFlatBonus.Text = "";
DisableTextBox(GebundenFlatBonus);
}
FillingInputs = false;
}
}
}