554 lines
20 KiB
C#
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
|
|
}
|
|
}
|
|
}
|