diff --git a/GSS2.UI.Core/ViewModels/AmineContentSeparatorCalibrationViewModel.cs b/GSS2.UI.Core/ViewModels/AmineContentSeparatorCalibrationViewModel.cs index 7b87c95..fe3fa49 100644 --- a/GSS2.UI.Core/ViewModels/AmineContentSeparatorCalibrationViewModel.cs +++ b/GSS2.UI.Core/ViewModels/AmineContentSeparatorCalibrationViewModel.cs @@ -28,9 +28,9 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase private CancellationTokenSource? _captureImagesTaskCts = null; [ObservableProperty] private ObservableCollection _records; - [ObservableProperty] private SeparatorRecord _currentRecord; + [ObservableProperty] private SeparatorRecord? _selectedRecord; + [ObservableProperty] private SeparatorRecord _editingRecord; [ObservableProperty] private bool _isMenuOpen = false; - [ObservableProperty] private bool _isNewRecord = false; [ObservableProperty] private int _mainSectionsCurrentIndex = 0; [ObservableProperty] private bool _mainSectionCanScrollBackward = false; @@ -59,31 +59,33 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase Records = new ObservableCollection(_context.SeparatorRecords.Include(r => r.Images)); - if (Records.Count() > 0) - { - CurrentRecord = Records.First(); - IsNewRecord = false; - } - else - { - CurrentRecord = new SeparatorRecord() + SelectedRecord = Records.FirstOrDefault(); + if (SelectedRecord is null) + EditingRecord = new() { Type = "", Batch = "", Images = new() }; - IsNewRecord = true; - } + else + EditingRecord = CopyRecord(SelectedRecord); _logger.LogInformation("Initialized"); } - partial void OnRecordsChanged(ObservableCollection? oldValue, ObservableCollection newValue) + partial void OnSelectedRecordChanged(SeparatorRecord? value) { - oldValue?.CollectionChanged -= OnRecordsCollectionChanged; - newValue?.CollectionChanged += OnRecordsCollectionChanged; + if (SelectedRecord is null) + EditingRecord = new() + { + Type = "", + Batch = "", + Images = new() + }; + else + EditingRecord = CopyRecord(SelectedRecord); } - partial void OnCurrentRecordChanged(SeparatorRecord value) + partial void OnEditingRecordChanged(SeparatorRecord value) { var images = value.Images .ToAsyncEnumerable() @@ -92,40 +94,19 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase .Select(kv => new KeyValuePair(new Bitmap(kv.Key!), kv.Value)); Images = new(images.ToBlockingEnumerable()); - - IsNewRecord = _context.Entry(value).State == EntityState.Detached; - } - - private void OnRecordsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs ea) - { - Console.WriteLine($"RecordsCollectionChanged {ea.Action}"); } [RelayCommand] private void ToggleMenu() => IsMenuOpen = !IsMenuOpen; [RelayCommand] private void CloseMenu() => IsMenuOpen = false; - [RelayCommand] - private void CreateRecord() - { - var record = new SeparatorRecord() - { - Type = "", - Batch = "", - Images = new() - }; - CurrentRecord = record; - IsNewRecord = true; - } + [RelayCommand] private void CreateRecord() => SelectedRecord = null; [RelayCommand] private void DeleteRecord() { - var deletedRecord = CurrentRecord; - var deletedIsNewRecord = IsNewRecord; - IsNewRecord = true; + var deletedRecord = SelectedRecord; CreateRecord(); - - if (!deletedIsNewRecord) + if (deletedRecord is not null) { Records.Remove(deletedRecord); _context.SeparatorRecords.Remove(deletedRecord); @@ -136,26 +117,89 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase [RelayCommand] private void SaveRecord() { - for (int i = 0; i < CurrentRecord.Images.Count(); i++) + if (SelectedRecord is null) { - var image = CurrentRecord.Images[i]; - if (_context.Entry(image).State == EntityState.Detached) - { - var attachedImage = _context.ImageRecords.Add(image); - CurrentRecord.Images.RemoveAt(i); - CurrentRecord.Images.Insert(i, attachedImage.Entity); - } - } - if (_context.Entry(CurrentRecord).State == EntityState.Detached) - { - var attachedRecord = _context.SeparatorRecords.Add(CurrentRecord); - CurrentRecord = attachedRecord.Entity; - } - if (IsNewRecord) - Records.Add(CurrentRecord); + var newEntity = CopyRecord(EditingRecord); - _context.SaveChanges(); - IsNewRecord = false; + for (int i = 0; i < newEntity.Images.Count(); i++) + { + var image = newEntity.Images[i]; + if (_context.Entry(image).State is not EntityState.Detached) + continue; + + var attachedImage = _context.ImageRecords.Add(image); + newEntity.Images.RemoveAt(i); + newEntity.Images.Insert(i, attachedImage.Entity); + } + if (_context.Entry(newEntity).State is EntityState.Detached) + { + var attachedRecord = _context.SeparatorRecords.Add(newEntity); + newEntity = attachedRecord.Entity; + } + + _context.SaveChanges(); + + Records.Add(newEntity); + SelectedRecord = newEntity; + } + else + { + SelectedRecord.Type = EditingRecord.Type; + SelectedRecord.Batch = EditingRecord.Batch; + + var imagesToRemove = SelectedRecord.Images + .Where(e => EditingRecord.Images.All(i => i.Id != e.Id)) + .ToList(); + + foreach (var image in imagesToRemove) + SelectedRecord.Images.Remove(image); + + foreach (var editedImage in EditingRecord.Images) + { + var existing = EditingRecord.Images + .FirstOrDefault(i => i.Id == editedImage.Id); + + if (existing is null) + { + SelectedRecord.Images.Add( + new ImageRecord + { + ImagePath = editedImage.ImagePath, + VisibleIntensity = editedImage.VisibleIntensity, + Uv365Intensity = editedImage.Uv365Intensity, + Uv254Intensity = editedImage.Uv254Intensity + } + ); + } + else + { + existing.ImagePath = editedImage.ImagePath; + existing.VisibleIntensity = editedImage.VisibleIntensity; + existing.Uv365Intensity = editedImage.Uv365Intensity; + existing.Uv254Intensity = editedImage.Uv254Intensity; + } + } + + for (int i = 0; i < SelectedRecord.Images.Count(); i++) + { + var image = SelectedRecord.Images[i]; + if (_context.Entry(image).State is not EntityState.Detached) + continue; + + var attachedImage = _context.ImageRecords.Add(image); + SelectedRecord.Images.RemoveAt(i); + SelectedRecord.Images.Insert(i, attachedImage.Entity); + } + if (_context.Entry(SelectedRecord).State is EntityState.Detached) + { + var attachedRecord = _context.SeparatorRecords.Add(SelectedRecord); + var index = Records.IndexOf(SelectedRecord); + Records[index] = attachedRecord.Entity; + SelectedRecord = attachedRecord.Entity; + } + + _context.SaveChanges(); + } } [RelayCommand] private void SwitchMainSection() => MainSectionsCurrentIndex = MainSectionsCurrentIndex == 0 ? 1 : 0; @@ -169,7 +213,7 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase _captureImagesTaskCts = new CancellationTokenSource(); var cancellationToken = _captureImagesTaskCts.Token; - CaptureImagesTask = new Task(async () => + CaptureImagesTask = Task.Run(async () => { _illuminatorService.TurnOn(); (double visible, double uv365, double uv254)[] intensities = @@ -196,6 +240,7 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase foreach (var (i, intensity) in intensities.Enumerate()) { + _logger.LogInformation("Capturing images: {} / {} ({};{};{})", i + 1, intensities.Count(), intensity.visible, intensity.uv365, intensity.uv254); cancellationToken.ThrowIfCancellationRequested(); Dispatcher.UIThread.Invoke(() => ImagesCapturingProgress = $"Получение изображений: {i + 1} / {intensities.Count()}"); @@ -239,8 +284,8 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase Dispatcher.UIThread.Invoke(() => { - CurrentRecord.Images.Clear(); - CurrentRecord.Images.AddRange(imageRecords); + EditingRecord.Images.Clear(); + EditingRecord.Images.AddRange(imageRecords); Images.Clear(); Images = new(images.ToBlockingEnumerable()); @@ -264,11 +309,29 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase }); } }, cancellationToken); - - CaptureImagesTask.Start(); } [RelayCommand] private void CencelImageCapturing() => _captureImagesTaskCts?.Cancel(); [RelayCommand] private void ImagesSectionPrevious() => ImagesSectionCurrentIndex--; [RelayCommand] private void ImagesSectionNext() => ImagesSectionCurrentIndex++; + + private static SeparatorRecord CopyRecord(SeparatorRecord source) + { + return new SeparatorRecord + { + Id = source.Id, + Type = source.Type, + Batch = source.Batch, + Images = source.Images + .Select(i => new ImageRecord + { + Id = i.Id, + ImagePath = i.ImagePath, + VisibleIntensity = i.VisibleIntensity, + Uv365Intensity = i.Uv365Intensity, + Uv254Intensity = i.Uv254Intensity + }) + .ToList() + }; + } } \ No newline at end of file diff --git a/GSS2.UI.Core/Views/AmineContentSeparatorCalibrationView.axaml b/GSS2.UI.Core/Views/AmineContentSeparatorCalibrationView.axaml index 41e4e30..93a2a5a 100644 --- a/GSS2.UI.Core/Views/AmineContentSeparatorCalibrationView.axaml +++ b/GSS2.UI.Core/Views/AmineContentSeparatorCalibrationView.axaml @@ -116,7 +116,7 @@ Margin="10,0,0,0" VerticalAlignment="Center" FontSize="18" - Text="{Binding CurrentRecord.Id, StringFormat='Id: {0}'}" /> + Text="{Binding EditingRecord.Id, StringFormat='Id: {0}'}" /> @@ -171,7 +171,7 @@ @@ -531,7 +531,7 @@ Command="{Binding CreateRecordCommand}" Content="Новая запись" /> - +