using System.Windows.Media; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using Livia.Models.Data; using Livia.Utility; using Livia.Utility.DependencyInjection; using Livia.ViewModels.Utility; using Microsoft.Extensions.DependencyInjection; namespace Livia.ViewModels; public class RoiExpanderGroupSelectionChangedMessage(string? groupId, string? id) { public string? GroupId { get; } = groupId; public string? Id { get; } = id; } public class RoiExpanderGroupControlViewModel : ObservableRecipient, ILiviaModuleViewModel, IRecipient { public string Name { get; } //ID for mutual exclusion public string GroupId { get; } public string Id { get; } public float SelectedVolume { get => _selectedVolume; private set => SetProperty(ref _selectedVolume, value); } public float TotalVolume { get => _totalVolume; private set => SetProperty(ref _totalVolume, value); } public SelectableObservableCollection RoiViewModelCollection { get; } = new(); public int SelectedCount { get => _selectedCount; private set => SetProperty(ref _selectedCount, value); } public int TotalCount { get => _totalCount; private set => SetProperty(ref _totalCount, value); } public bool Visible { get => _visible; private set => SetProperty(ref _visible, value); } public bool ShowHeader { get => _showHeader; set => SetProperty(ref _showHeader, value); } public List? Regions { get; set; } public int ZIndex { get; set; } public Color Color { get; } public string RoiTabId { get; set; } = string.Empty; public static readonly HashSet DefaultDeselectRoiSet = []; private float _selectedVolume; private float _totalVolume; private int _totalCount; private int _selectedCount; private bool _visible; private bool _showHeader = true; private readonly bool _isTwoSided; private readonly bool _defaultChecked; private static readonly Dictionary GroupIdState = new(); public RoiExpanderGroupControlViewModel(string name, string id, Color color, bool isTwoSided) { Name = LiviaUtility.ParseServerString(name); Color = color; _isTwoSided = isTwoSided; //We no longer need them to be mutually exclusive //GroupId = string.Concat(id.Where(char.IsLetter)); GroupId = id; Id = id; _defaultChecked = !DefaultDeselectRoiSet.Contains(Id); WeakReferenceMessenger.Default.RegisterAll(this); } public async Task LoadData(DataBlock dataBlock) { //init dict if (_defaultChecked) GroupIdState[GroupId] = Id; if (Regions != null) { SolidColorBrush colorBrush = new(Color); List list = []; foreach (RoiData data in Regions) { RoiExpanderControlViewModel viewModel = ActivatorUtilities.CreateInstance(ServiceProviderFactory.ServiceProvider, _isTwoSided); viewModel.Color = colorBrush; viewModel.RoiData = data; viewModel.ZIndex = ZIndex; viewModel.RoiTabId = RoiTabId; await viewModel.LoadData(dataBlock); list.Add(viewModel); } RoiViewModelCollection.AddRange(list); foreach (RoiExpanderControlViewModel viewModel in list) { viewModel.PropertyChanged += (_, args) => { if (args.PropertyName != nameof(RoiExpanderControlViewModel.IsChecked) && args.PropertyName != nameof(RoiExpanderControlViewModel.Volume)) return; UpdateCount(); //switch group if (!viewModel.IsChecked || !GroupIdState.TryGetValue(GroupId, out string? oldId)) return; if (oldId == Id) return; GroupIdState[GroupId] = Id; WeakReferenceMessenger.Default.Send(new RoiExpanderGroupSelectionChangedMessage(GroupId, Id)); }; viewModel.IsChecked = _defaultChecked; } } Visible = RoiViewModelCollection.Items.Count != 0; TotalCount = RoiViewModelCollection.Items.Count; TotalVolume = RoiViewModelCollection.Items.Select(data => data.Volume).Sum(); UpdateCount(); } public void Init() { } private void UpdateCount() { SelectedCount = RoiViewModelCollection.Items.Count(data => data.IsChecked); SelectedVolume = RoiViewModelCollection.Items.Where(data => data.IsChecked).Select(data => data.Volume).Sum(); } public void Receive(RoiExpanderGroupSelectionChangedMessage message) { if (GroupId != message.GroupId) return; bool newValue = Id == message.Id; if (newValue == RoiViewModelCollection.CheckBoxChecked) return; RoiViewModelCollection.CheckBoxChecked = newValue; UpdateCount(); } public void ClearData() { foreach (RoiExpanderControlViewModel viewModel in RoiViewModelCollection.Items) { viewModel.ClearData(); } RoiViewModelCollection.Items.Clear(); WeakReferenceMessenger.Default.UnregisterAll(this); } }