Files
XplorePlane/XplorePlane/ViewModels/Cnc/CncNodeViewModel.cs
T
2026-04-22 01:59:33 +08:00

554 lines
20 KiB
C#

using Prism.Mvvm;
using System;
using System.Collections.ObjectModel;
using XplorePlane.Models;
namespace XplorePlane.ViewModels.Cnc
{
/// <summary>
/// CNC node ViewModel with editable properties and tree children.
/// </summary>
public class CncNodeViewModel : BindableBase
{
private readonly Action<CncNodeViewModel, CncNode> _modelChangedCallback;
private CncNode _model;
private string _icon;
private bool _isExpanded = true;
public CncNodeViewModel(CncNode model, Action<CncNodeViewModel, CncNode> modelChangedCallback)
{
_model = model ?? throw new ArgumentNullException(nameof(model));
_modelChangedCallback = modelChangedCallback ?? throw new ArgumentNullException(nameof(modelChangedCallback));
_icon = GetIconForNodeType(model.NodeType);
Children = new ObservableCollection<CncNodeViewModel>();
}
public ObservableCollection<CncNodeViewModel> Children { get; }
public CncNode Model => _model;
public Guid Id => _model.Id;
public int Index => _model.Index;
public string Name
{
get => _model.Name;
set => UpdateModel(_model with { Name = value ?? string.Empty });
}
public CncNodeType NodeType => _model.NodeType;
public string NodeTypeDisplay => NodeType.ToString();
public string Icon
{
get => _icon;
private set => SetProperty(ref _icon, value);
}
public bool IsExpanded
{
get => _isExpanded;
set => SetProperty(ref _isExpanded, value);
}
public bool HasChildren => Children.Count > 0;
public bool IsReferencePoint => _model is ReferencePointNode;
public bool IsSaveNode => _model is SaveNodeNode;
public bool IsSaveNodeWithImage => _model is SaveNodeWithImageNode;
public bool IsSavePosition => _model is SavePositionNode;
public bool IsInspectionModule => _model is InspectionModuleNode;
public bool IsInspectionMarker => _model is InspectionMarkerNode;
public bool IsPauseDialog => _model is PauseDialogNode;
public bool IsWaitDelay => _model is WaitDelayNode;
public bool IsCompleteProgram => _model is CompleteProgramNode;
public bool IsPositionChild => _model is InspectionModuleNode or InspectionMarkerNode;
public bool IsMotionSnapshotNode => _model is ReferencePointNode or SaveNodeNode or SaveNodeWithImageNode or SavePositionNode;
public string RelationTag => _model switch
{
SavePositionNode => "位置",
InspectionModuleNode => "检测模块",
InspectionMarkerNode => "检测标记",
_ => string.Empty
};
public double XM
{
get => _model switch
{
ReferencePointNode rp => rp.XM,
SaveNodeNode sn => sn.MotionState.XM,
SaveNodeWithImageNode sni => sni.MotionState.XM,
SavePositionNode sp => sp.MotionState.XM,
_ => 0d
};
set => UpdateMotion(value, MotionAxis.XM);
}
public double YM
{
get => _model switch
{
ReferencePointNode rp => rp.YM,
SaveNodeNode sn => sn.MotionState.YM,
SaveNodeWithImageNode sni => sni.MotionState.YM,
SavePositionNode sp => sp.MotionState.YM,
_ => 0d
};
set => UpdateMotion(value, MotionAxis.YM);
}
public double ZT
{
get => _model switch
{
ReferencePointNode rp => rp.ZT,
SaveNodeNode sn => sn.MotionState.ZT,
SaveNodeWithImageNode sni => sni.MotionState.ZT,
SavePositionNode sp => sp.MotionState.ZT,
_ => 0d
};
set => UpdateMotion(value, MotionAxis.ZT);
}
public double ZD
{
get => _model switch
{
ReferencePointNode rp => rp.ZD,
SaveNodeNode sn => sn.MotionState.ZD,
SaveNodeWithImageNode sni => sni.MotionState.ZD,
SavePositionNode sp => sp.MotionState.ZD,
_ => 0d
};
set => UpdateMotion(value, MotionAxis.ZD);
}
public double TiltD
{
get => _model switch
{
ReferencePointNode rp => rp.TiltD,
SaveNodeNode sn => sn.MotionState.TiltD,
SaveNodeWithImageNode sni => sni.MotionState.TiltD,
SavePositionNode sp => sp.MotionState.TiltD,
_ => 0d
};
set => UpdateMotion(value, MotionAxis.TiltD);
}
public double Dist
{
get => _model switch
{
ReferencePointNode rp => rp.Dist,
SaveNodeNode sn => sn.MotionState.Dist,
SaveNodeWithImageNode sni => sni.MotionState.Dist,
SavePositionNode sp => sp.MotionState.Dist,
_ => 0d
};
set => UpdateMotion(value, MotionAxis.Dist);
}
public bool IsRayOn
{
get => _model switch
{
ReferencePointNode rp => rp.IsRayOn,
SaveNodeNode sn => sn.RaySourceState.IsOn,
SaveNodeWithImageNode sni => sni.RaySourceState.IsOn,
_ => false
};
set => UpdateRaySource(isOn: value);
}
public double Voltage
{
get => _model switch
{
ReferencePointNode rp => rp.Voltage,
SaveNodeNode sn => sn.RaySourceState.Voltage,
SaveNodeWithImageNode sni => sni.RaySourceState.Voltage,
_ => 0d
};
set => UpdateRaySource(voltage: value);
}
public double Current
{
get => _model is ReferencePointNode rp ? rp.Current : 0d;
set
{
if (_model is ReferencePointNode rp)
{
UpdateModel(rp with { Current = value });
}
}
}
public double Power
{
get => _model switch
{
SaveNodeNode sn => sn.RaySourceState.Power,
SaveNodeWithImageNode sni => sni.RaySourceState.Power,
_ => 0d
};
set => UpdateRaySource(power: value);
}
public bool DetectorConnected
{
get => _model switch
{
SaveNodeNode sn => sn.DetectorState.IsConnected,
SaveNodeWithImageNode sni => sni.DetectorState.IsConnected,
_ => false
};
set => UpdateDetector(isConnected: value);
}
public bool DetectorAcquiring
{
get => _model switch
{
SaveNodeNode sn => sn.DetectorState.IsAcquiring,
SaveNodeWithImageNode sni => sni.DetectorState.IsAcquiring,
_ => false
};
set => UpdateDetector(isAcquiring: value);
}
public double FrameRate
{
get => _model switch
{
SaveNodeNode sn => sn.DetectorState.FrameRate,
SaveNodeWithImageNode sni => sni.DetectorState.FrameRate,
_ => 0d
};
set => UpdateDetector(frameRate: value);
}
public string Resolution
{
get => _model switch
{
SaveNodeNode sn => sn.DetectorState.Resolution,
SaveNodeWithImageNode sni => sni.DetectorState.Resolution,
_ => string.Empty
};
set => UpdateDetector(resolution: value ?? string.Empty);
}
public string ImageFileName
{
get => _model is SaveNodeWithImageNode sni ? sni.ImageFileName : string.Empty;
set
{
if (_model is SaveNodeWithImageNode sni)
{
UpdateModel(sni with { ImageFileName = value ?? string.Empty });
}
}
}
public string PipelineName
{
get => _model is InspectionModuleNode im ? im.Pipeline?.Name ?? string.Empty : string.Empty;
set
{
if (_model is InspectionModuleNode im)
{
var pipeline = im.Pipeline ?? new PipelineModel();
pipeline.Name = value ?? string.Empty;
UpdateModel(im with { Pipeline = pipeline });
}
}
}
public PipelineModel Pipeline
{
get => _model is InspectionModuleNode im ? im.Pipeline : null;
set
{
if (_model is InspectionModuleNode im)
{
UpdateModel(im with { Pipeline = value ?? new PipelineModel() });
}
}
}
public string MarkerType
{
get => _model is InspectionMarkerNode mk ? mk.MarkerType : string.Empty;
set
{
if (_model is InspectionMarkerNode mk)
{
UpdateModel(mk with { MarkerType = value ?? string.Empty });
}
}
}
public double MarkerX
{
get => _model is InspectionMarkerNode mk ? mk.MarkerX : 0d;
set
{
if (_model is InspectionMarkerNode mk)
{
UpdateModel(mk with { MarkerX = value });
}
}
}
public double MarkerY
{
get => _model is InspectionMarkerNode mk ? mk.MarkerY : 0d;
set
{
if (_model is InspectionMarkerNode mk)
{
UpdateModel(mk with { MarkerY = value });
}
}
}
public string DialogTitle
{
get => _model is PauseDialogNode pd ? pd.DialogTitle : string.Empty;
set
{
if (_model is PauseDialogNode pd)
{
UpdateModel(pd with { DialogTitle = value ?? string.Empty });
}
}
}
public string DialogMessage
{
get => _model is PauseDialogNode pd ? pd.DialogMessage : string.Empty;
set
{
if (_model is PauseDialogNode pd)
{
UpdateModel(pd with { DialogMessage = value ?? string.Empty });
}
}
}
public int DelayMilliseconds
{
get => _model is WaitDelayNode wd ? wd.DelayMilliseconds : 0;
set
{
if (_model is WaitDelayNode wd)
{
UpdateModel(wd with { DelayMilliseconds = value });
}
}
}
public void ReplaceModel(CncNode model)
{
_model = model ?? throw new ArgumentNullException(nameof(model));
Icon = GetIconForNodeType(model.NodeType);
RaiseAllPropertiesChanged();
}
public static string GetIconForNodeType(CncNodeType nodeType)
{
return nodeType switch
{
CncNodeType.ReferencePoint => "/Assets/Icons/reference.png",
CncNodeType.SaveNodeWithImage => "/Assets/Icons/saveall.png",
CncNodeType.SaveNode => "/Assets/Icons/save.png",
CncNodeType.SavePosition => "/Assets/Icons/add-pos.png",
CncNodeType.InspectionModule => "/Assets/Icons/Module.png",
CncNodeType.InspectionMarker => "/Assets/Icons/mark.png",
CncNodeType.PauseDialog => "/Assets/Icons/message.png",
CncNodeType.WaitDelay => "/Assets/Icons/wait.png",
CncNodeType.CompleteProgram => "/Assets/Icons/finish.png",
_ => "/Assets/Icons/cnc.png",
};
}
private void UpdateMotion(double value, MotionAxis axis)
{
switch (_model)
{
case ReferencePointNode rp:
UpdateModel(axis switch
{
MotionAxis.XM => rp with { XM = value },
MotionAxis.YM => rp with { YM = value },
MotionAxis.ZT => rp with { ZT = value },
MotionAxis.ZD => rp with { ZD = value },
MotionAxis.TiltD => rp with { TiltD = value },
MotionAxis.Dist => rp with { Dist = value },
_ => rp
});
break;
case SaveNodeNode sn:
UpdateModel(sn with { MotionState = UpdateMotionState(sn.MotionState, axis, value) });
break;
case SaveNodeWithImageNode sni:
UpdateModel(sni with { MotionState = UpdateMotionState(sni.MotionState, axis, value) });
break;
case SavePositionNode sp:
UpdateModel(sp with { MotionState = UpdateMotionState(sp.MotionState, axis, value) });
break;
}
}
private void UpdateRaySource(bool? isOn = null, double? voltage = null, double? current = null, double? power = null)
{
switch (_model)
{
case ReferencePointNode rp:
UpdateModel(rp with
{
IsRayOn = isOn ?? rp.IsRayOn,
Voltage = voltage ?? rp.Voltage,
Current = current ?? rp.Current
});
break;
case SaveNodeNode sn:
UpdateModel(sn with
{
RaySourceState = sn.RaySourceState with
{
IsOn = isOn ?? sn.RaySourceState.IsOn,
Voltage = voltage ?? sn.RaySourceState.Voltage,
Power = power ?? sn.RaySourceState.Power
}
});
break;
case SaveNodeWithImageNode sni:
UpdateModel(sni with
{
RaySourceState = sni.RaySourceState with
{
IsOn = isOn ?? sni.RaySourceState.IsOn,
Voltage = voltage ?? sni.RaySourceState.Voltage,
Power = power ?? sni.RaySourceState.Power
}
});
break;
}
}
private void UpdateDetector(bool? isConnected = null, bool? isAcquiring = null, double? frameRate = null, string resolution = null)
{
switch (_model)
{
case SaveNodeNode sn:
UpdateModel(sn with
{
DetectorState = sn.DetectorState with
{
IsConnected = isConnected ?? sn.DetectorState.IsConnected,
IsAcquiring = isAcquiring ?? sn.DetectorState.IsAcquiring,
FrameRate = frameRate ?? sn.DetectorState.FrameRate,
Resolution = resolution ?? sn.DetectorState.Resolution
}
});
break;
case SaveNodeWithImageNode sni:
UpdateModel(sni with
{
DetectorState = sni.DetectorState with
{
IsConnected = isConnected ?? sni.DetectorState.IsConnected,
IsAcquiring = isAcquiring ?? sni.DetectorState.IsAcquiring,
FrameRate = frameRate ?? sni.DetectorState.FrameRate,
Resolution = resolution ?? sni.DetectorState.Resolution
}
});
break;
}
}
private static MotionState UpdateMotionState(MotionState state, MotionAxis axis, double value)
{
return axis switch
{
MotionAxis.XM => state with { XM = value },
MotionAxis.YM => state with { YM = value },
MotionAxis.ZT => state with { ZT = value },
MotionAxis.ZD => state with { ZD = value },
MotionAxis.TiltD => state with { TiltD = value },
MotionAxis.Dist => state with { Dist = value },
_ => state
};
}
private void UpdateModel(CncNode updatedModel)
{
_model = updatedModel ?? throw new ArgumentNullException(nameof(updatedModel));
RaiseAllPropertiesChanged();
_modelChangedCallback(this, updatedModel);
}
private void RaiseAllPropertiesChanged()
{
RaisePropertyChanged(nameof(Model));
RaisePropertyChanged(nameof(Id));
RaisePropertyChanged(nameof(Index));
RaisePropertyChanged(nameof(Name));
RaisePropertyChanged(nameof(NodeType));
RaisePropertyChanged(nameof(NodeTypeDisplay));
RaisePropertyChanged(nameof(Icon));
RaisePropertyChanged(nameof(IsReferencePoint));
RaisePropertyChanged(nameof(IsSaveNode));
RaisePropertyChanged(nameof(IsSaveNodeWithImage));
RaisePropertyChanged(nameof(IsSavePosition));
RaisePropertyChanged(nameof(IsInspectionModule));
RaisePropertyChanged(nameof(IsInspectionMarker));
RaisePropertyChanged(nameof(IsPauseDialog));
RaisePropertyChanged(nameof(IsWaitDelay));
RaisePropertyChanged(nameof(IsCompleteProgram));
RaisePropertyChanged(nameof(IsPositionChild));
RaisePropertyChanged(nameof(IsMotionSnapshotNode));
RaisePropertyChanged(nameof(RelationTag));
RaisePropertyChanged(nameof(XM));
RaisePropertyChanged(nameof(YM));
RaisePropertyChanged(nameof(ZT));
RaisePropertyChanged(nameof(ZD));
RaisePropertyChanged(nameof(TiltD));
RaisePropertyChanged(nameof(Dist));
RaisePropertyChanged(nameof(IsRayOn));
RaisePropertyChanged(nameof(Voltage));
RaisePropertyChanged(nameof(Current));
RaisePropertyChanged(nameof(Power));
RaisePropertyChanged(nameof(DetectorConnected));
RaisePropertyChanged(nameof(DetectorAcquiring));
RaisePropertyChanged(nameof(FrameRate));
RaisePropertyChanged(nameof(Resolution));
RaisePropertyChanged(nameof(ImageFileName));
RaisePropertyChanged(nameof(Pipeline));
RaisePropertyChanged(nameof(PipelineName));
RaisePropertyChanged(nameof(MarkerType));
RaisePropertyChanged(nameof(MarkerX));
RaisePropertyChanged(nameof(MarkerY));
RaisePropertyChanged(nameof(DialogTitle));
RaisePropertyChanged(nameof(DialogMessage));
RaisePropertyChanged(nameof(DelayMilliseconds));
}
private enum MotionAxis
{
XM,
YM,
ZT,
ZD,
TiltD,
Dist
}
}
}