331 lines
12 KiB
C#
331 lines
12 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
using Livia.Models;
|
|
using Livia.Models.Data;
|
|
using Livia.Utility;
|
|
using Livia.Utility.DependencyInjection;
|
|
using Livia.ViewModels.Utility;
|
|
using Livia.Views.Utility;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace Livia.ViewModels;
|
|
|
|
public class RoiExpanderControlViewModel : ObservableRecipient, ILiviaModuleViewModel, IRecipient<TwoColumnModeToggleMessage>, IRecipient<LocationDisplayModeToggleMessage>, IRecipient<UnfoldToggleMessage>,
|
|
IRecipient<RoiExpanderToggleMessage>, IRecipient<LocateRoiMessage>, IRecipient<ShowBoundaryToggleMessage>, ISelectableItem
|
|
{
|
|
public const int BlinkTime = 3000;
|
|
|
|
public bool IsChecked
|
|
{
|
|
get => _checked;
|
|
set
|
|
{
|
|
SetProperty(ref _checked, value);
|
|
WeakReferenceMessenger.Default.Send(new RoiExpanderToggleMessage(Name, value));
|
|
}
|
|
}
|
|
|
|
public string Name { get => _name; private set => SetProperty(ref _name, value); }
|
|
public bool NoLocationData => RoiData.Locations.Count == 0;
|
|
public bool ShowButtons => SubGroups.Count == 0 && !NoLocationData;
|
|
public float Volume { get => _volume; private set => SetProperty(ref _volume, value); }
|
|
public SolidColorBrush Color { get => _color; set => SetProperty(ref _color, value); }
|
|
public bool IsTwoSided { get; }
|
|
public bool TwoColumnMode { get => _twoColumnMode; set => SetProperty(ref _twoColumnMode, value); }
|
|
public bool UnfoldButtonState { get => _unfoldButtonState; set => SetProperty(ref _unfoldButtonState, value); }
|
|
public RoiLocationDisplayMode CurrentRoiLocationDisplayMode { get => _currentRoiLocationDisplayMode; set => SetProperty(ref _currentRoiLocationDisplayMode, value); }
|
|
public RoiData RoiData { get; set; }
|
|
public int ZIndex { get; set; }
|
|
|
|
public ObservableCollection<RoiLocationDataControlViewModel> Locations { get; } = [];
|
|
public ObservableCollection<RoiExpanderGroupControlViewModel> SubGroups { get; } = [];
|
|
public ObservableCollection<RoiLocationDataControlViewModel> LeftLocations { get; } = [];
|
|
public ObservableCollection<RoiLocationDataControlViewModel> RightLocations { get; } = [];
|
|
public ObservableCollection<RoiLocationDataControlViewModel> TwoSideLocations { get; } = [];
|
|
public IImageSeries MaskImageSeries { get; } = new Dicom3DImageSeries();
|
|
public BitmapImage? MosaicMask { get; private set; }
|
|
public bool IsBlinking { get => _isBlinking; set => SetProperty(ref _isBlinking, value); }
|
|
public bool OtherIsBlinking { get => _otherIsBlinking; set => SetProperty(ref _otherIsBlinking, value); }
|
|
public string RoiTabId { get; set; } = string.Empty;
|
|
|
|
private string _name = string.Empty;
|
|
private float _volume;
|
|
private bool _checked = true;
|
|
private bool _twoColumnMode;
|
|
private bool _unfoldButtonState;
|
|
private SolidColorBrush _color = new(Colors.White);
|
|
private RoiLocationDisplayMode _currentRoiLocationDisplayMode = RoiLocationDisplayMode.Volume; //default to volume
|
|
private bool _isBlinking;
|
|
private bool _otherIsBlinking;
|
|
private readonly IRoiLegendManager _roiLegendManager;
|
|
private readonly IDataBlockLoader _dataBlockLoader;
|
|
private readonly IWarningSystem _warningSystem;
|
|
private static readonly object DictionaryInsertLock = new();
|
|
|
|
public RoiExpanderControlViewModel(bool isTwoSided, IRoiLegendManager roiLegendManager, IDataBlockLoader dataBlockLoader, IWarningSystem warningSystem)
|
|
{
|
|
IsTwoSided = isTwoSided;
|
|
_roiLegendManager = roiLegendManager;
|
|
_dataBlockLoader = dataBlockLoader;
|
|
_warningSystem = warningSystem;
|
|
MaskImageSeries.IsMask = true;
|
|
|
|
//only two-sided column cares about this
|
|
if (isTwoSided)
|
|
WeakReferenceMessenger.Default.Register<TwoColumnModeToggleMessage>(this);
|
|
|
|
WeakReferenceMessenger.Default.Register<LocationDisplayModeToggleMessage>(this);
|
|
WeakReferenceMessenger.Default.Register<UnfoldToggleMessage>(this);
|
|
WeakReferenceMessenger.Default.Register<RoiExpanderToggleMessage>(this);
|
|
WeakReferenceMessenger.Default.Register<LocateRoiMessage>(this);
|
|
WeakReferenceMessenger.Default.Register<ShowBoundaryToggleMessage>(this);
|
|
}
|
|
|
|
public void ToggleUnfold()
|
|
{
|
|
WeakReferenceMessenger.Default.Send(new UnfoldToggleMessage(!UnfoldButtonState));
|
|
}
|
|
|
|
public void ToggleRoiLocationsDisplayMode()
|
|
{
|
|
WeakReferenceMessenger.Default.Send(new LocationDisplayModeToggleMessage((RoiLocationDisplayMode)(((int)CurrentRoiLocationDisplayMode + 1) % Enum.GetNames(typeof(RoiLocationDisplayMode)).Length)));
|
|
}
|
|
|
|
public void ToggleTwoColumnMode()
|
|
{
|
|
WeakReferenceMessenger.Default.Send(new TwoColumnModeToggleMessage(!TwoColumnMode));
|
|
}
|
|
|
|
private IEnumerable<RoiLocationDataControlViewModel> GetAllLocations()
|
|
{
|
|
foreach (RoiLocationDataControlViewModel viewModel in Locations)
|
|
{
|
|
yield return viewModel;
|
|
}
|
|
|
|
foreach (RoiLocationDataControlViewModel viewModel in LeftLocations)
|
|
{
|
|
yield return viewModel;
|
|
}
|
|
|
|
foreach (RoiLocationDataControlViewModel viewModel in RightLocations)
|
|
{
|
|
yield return viewModel;
|
|
}
|
|
|
|
foreach (RoiLocationDataControlViewModel viewModel in TwoSideLocations)
|
|
{
|
|
yield return viewModel;
|
|
}
|
|
}
|
|
|
|
public void Receive(UnfoldToggleMessage message)
|
|
{
|
|
UnfoldButtonState = message.Value;
|
|
foreach (RoiLocationDataControlViewModel viewModel in GetAllLocations())
|
|
{
|
|
viewModel.IsExpanded = message.Value;
|
|
}
|
|
}
|
|
|
|
public void Receive(TwoColumnModeToggleMessage message)
|
|
{
|
|
TwoColumnMode = message.Value;
|
|
}
|
|
|
|
public void Receive(LocationDisplayModeToggleMessage message)
|
|
{
|
|
CurrentRoiLocationDisplayMode = message.Value;
|
|
foreach (RoiLocationDataControlViewModel viewModel in GetAllLocations())
|
|
{
|
|
viewModel.UpdateDisplayString(message.Value);
|
|
}
|
|
}
|
|
|
|
public void Receive(RoiExpanderToggleMessage message)
|
|
{
|
|
if (SubGroups.SelectMany(group => group.RoiViewModelCollection.Items).Select(vm => vm.Name).Contains(message.Value.Item1))
|
|
{
|
|
Volume = SubGroups.Select(vm => vm.SelectedVolume).Sum();
|
|
}
|
|
|
|
//if (Name != message.Value.Item1)
|
|
// return;
|
|
|
|
//if (IsChecked == message.Value.Item2)
|
|
// return;
|
|
|
|
//IsChecked = message.Value.Item2;
|
|
}
|
|
|
|
public ReportModulesRoiData GenerateModulesRoiData()
|
|
{
|
|
List<string> unfoldList = new();
|
|
//TODO::this is disabled for now. Will cause error in server.
|
|
//if (TwoColumnMode)
|
|
//{
|
|
// unfoldList = (from roiLocationDataControlViewModel in TwoSideLocations
|
|
// where roiLocationDataControlViewModel.IsExpanded
|
|
// select roiLocationDataControlViewModel.Name).ToList();
|
|
// unfoldList.AddRange(from roiLocationDataControlViewModel in LeftLocations
|
|
// where roiLocationDataControlViewModel.IsExpanded
|
|
// select roiLocationDataControlViewModel.Name);
|
|
// unfoldList.AddRange(from roiLocationDataControlViewModel in RightLocations
|
|
// where roiLocationDataControlViewModel.IsExpanded
|
|
// select roiLocationDataControlViewModel.Name);
|
|
//}
|
|
//else
|
|
//{
|
|
// unfoldList = (from roiLocationDataControlViewModel in Locations
|
|
// where roiLocationDataControlViewModel.IsExpanded
|
|
// select roiLocationDataControlViewModel.Name).ToList();
|
|
//}
|
|
|
|
ReportModulesRoiData result = new()
|
|
{
|
|
Name = RoiData.FileName,
|
|
Unfold = unfoldList
|
|
};
|
|
return result;
|
|
}
|
|
|
|
public async Task LoadData(DataBlock dataBlock)
|
|
{
|
|
Volume = RoiData.Volume;
|
|
Name = LiviaUtility.ParseServerString(RoiData.Name);
|
|
|
|
//load sub groups
|
|
if (RoiData.SubGroups != null)
|
|
{
|
|
foreach (RoiGroup roiGroup in RoiData.SubGroups)
|
|
{
|
|
Color color = (Color)ColorConverter.ConvertFromString(roiGroup.Color);
|
|
if (RoiSummaryControlViewModel.RoiTabIdToTabIndexDictionary == null || !RoiSummaryControlViewModel.RoiTabIdToTabIndexDictionary.TryGetValue(RoiTabId, out int tabIndex))
|
|
continue;
|
|
_roiLegendManager.AddItem(tabIndex, roiGroup.Id, roiGroup.Name, roiGroup.FullName, color);
|
|
|
|
if (roiGroup.Regions.Count == 0)
|
|
continue;
|
|
|
|
RoiExpanderGroupControlViewModel viewModel = ActivatorUtilities.CreateInstance<RoiExpanderGroupControlViewModel>(ServiceProviderFactory.ServiceProvider, roiGroup.Name, roiGroup.Id, color, IsTwoSided);
|
|
viewModel.RoiTabId = RoiTabId;
|
|
viewModel.Regions = roiGroup.Regions;
|
|
viewModel.ShowHeader = false;
|
|
await viewModel.LoadData(dataBlock);
|
|
SubGroups.Add(viewModel);
|
|
|
|
}
|
|
|
|
Volume = SubGroups.Select(vm => vm.SelectedVolume).Sum();
|
|
}
|
|
else
|
|
{
|
|
//add data to list according to their side
|
|
foreach (LocationData locationInfo in RoiData.Locations)
|
|
{
|
|
Locations.Add(new RoiLocationDataControlViewModel(locationInfo));
|
|
|
|
if (!IsTwoSided)
|
|
continue;
|
|
|
|
if (locationInfo.Name.Contains("_左"))
|
|
{
|
|
LeftLocations.Add(new RoiLocationDataControlViewModel(locationInfo));
|
|
}
|
|
else if (locationInfo.Name.Contains("_右"))
|
|
{
|
|
RightLocations.Add(new RoiLocationDataControlViewModel(locationInfo));
|
|
}
|
|
else
|
|
{
|
|
TwoSideLocations.Add(new RoiLocationDataControlViewModel(locationInfo));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RoiData.Mask != null)
|
|
{
|
|
await MaskImageSeries.LoadData(Path.Combine(dataBlock.ResultPath, "mosaic", RoiData.Mask));
|
|
|
|
//save to dictionary
|
|
if (!string.IsNullOrEmpty(RoiTabId))
|
|
{
|
|
Dictionary<string, ConcurrentBag<RoiExpanderControlViewModel>> dictionary = _dataBlockLoader.GetSharedData<Dictionary<string, ConcurrentBag<RoiExpanderControlViewModel>>>("roiCollection");
|
|
lock (DictionaryInsertLock)
|
|
{
|
|
dictionary.AddToCollectionWithKey(RoiTabId, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RoiData.MosaicMask != null)
|
|
{
|
|
MosaicMask = await LiviaUtility.LoadBitmapAsync(Path.Combine(dataBlock.ResultPath, "mosaic", RoiData.MosaicMask));
|
|
}
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
}
|
|
|
|
public void Receive(LocateRoiMessage message)
|
|
{
|
|
if (message.Value == this)
|
|
{
|
|
if (MaskImageSeries.MaskJumpToIndex is null or < 0)
|
|
{
|
|
_warningSystem.ShowDialog(WarningWindowKind.Warning, false, "UnableToLocateRegionWarning");
|
|
return;
|
|
}
|
|
|
|
IsChecked = true;
|
|
WeakReferenceMessenger.Default.Send(new ImageRotationViewerIndexChangeMessage("structure", MaskImageSeries.MaskJumpToIndex.Value + 1));
|
|
|
|
IsBlinking = true;
|
|
Task.Run(async () =>
|
|
{
|
|
await Task.Delay(BlinkTime);
|
|
IsBlinking = false;
|
|
});
|
|
}
|
|
else
|
|
{
|
|
//hide all other images to see better
|
|
OtherIsBlinking = true;
|
|
Task.Run(async () =>
|
|
{
|
|
await Task.Delay(BlinkTime);
|
|
OtherIsBlinking = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
public void ToggleShowBoundary()
|
|
{
|
|
WeakReferenceMessenger.Default.Send(new ShowBoundaryToggleMessage(!MaskImageSeries.ShowBoundary));
|
|
}
|
|
|
|
public void Receive(ShowBoundaryToggleMessage message)
|
|
{
|
|
MaskImageSeries.ShowBoundary = message.Value;
|
|
}
|
|
|
|
public void ClearData()
|
|
{
|
|
foreach (RoiExpanderGroupControlViewModel viewModel in SubGroups)
|
|
{
|
|
viewModel.ClearData();
|
|
}
|
|
|
|
MaskImageSeries.Dispose();
|
|
MosaicMask = null;
|
|
WeakReferenceMessenger.Default.UnregisterAll(this);
|
|
}
|
|
}
|
|
|