using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Windows.Input; using System.Windows.Media; using AIStudio.Wpf.DiagramDesigner.Enums; using AIStudio.Wpf.DiagramDesigner.Models; namespace AIStudio.Wpf.DiagramDesigner { public abstract class LogicalGateItemViewModelBase : DesignerItemViewModelBase { public ICommand AddInputCommand { get; private set; } public ICommand AddOutputCommand { get; private set; } public virtual bool EnableAddInput { get; } = false; public virtual bool EnableAddOutput { get; } = false; public LogicalGateItemViewModelBase(LogicalType logicalType) : this(null, logicalType) { } public LogicalGateItemViewModelBase(IDiagramViewModel root, LogicalType logicalType) : base(root) { this.LogicalType = logicalType; } public LogicalGateItemViewModelBase(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer) { } public LogicalGateItemViewModelBase(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType) { } public override SelectableItemBase GetSerializableObject() { return new LogicalGateDesignerItemBase(this); } public override void Init(IDiagramViewModel root, bool initNew) { ShowRotate = false; ShowArrow = false; AddInputCommand = new SimpleCommand(Command_Enable, para => ExecuteAddInput(para)); AddOutputCommand = new SimpleCommand(Command_Enable, para => ExecuteAddOutput(para)); BuildMenuOptions(); base.Init(root, initNew); } protected override void InitNew() { ExecuteAddInput(null); ExecuteAddInput(null); ExecuteAddOutput(null); } private void BuildMenuOptions() { menuOptions = new ObservableCollection(); if (EnableAddInput == true) { CinchMenuItem menuItem = new CinchMenuItem(); menuItem.Text = "添加输入"; menuItem.Command = AddInputCommand; menuItem.CommandParameter = menuItem; menuOptions.Add(menuItem); } if (EnableAddOutput == true) { CinchMenuItem menuItem = new CinchMenuItem(); menuItem.Text = "添加输出"; menuItem.Command = AddOutputCommand; menuItem.CommandParameter = menuItem; menuOptions.Add(menuItem); } } protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase) { base.LoadDesignerItemViewModel(designerbase); if (designerbase is LogicalGateDesignerItemBase designer) { this.LogicalType = designer.LogicalType; this.OrderNumber = designer.OrderNumber; this.Value = designer.Value; this.IsEnabled = designer.IsEnabled; ClearConnectors(); Input.Clear(); Output.Clear(); if (designer.LogicalConnectors != null) { foreach (var connector in designer.LogicalConnectors) { LogicalConnectorInfo fullyCreatedConnectorInfo = new LogicalConnectorInfo(this.Root, this, connector); if (fullyCreatedConnectorInfo.Orientation == ConnectorOrientation.Left) { Input.Add(Input.Count, fullyCreatedConnectorInfo); } else if (fullyCreatedConnectorInfo.Orientation == ConnectorOrientation.Right) { Output.Add(Output.Count, fullyCreatedConnectorInfo); } AddConnector(fullyCreatedConnectorInfo); } } } } private int _orderNumber; public int OrderNumber { get { return _orderNumber; } set { SetProperty(ref _orderNumber, value); } } private bool _isEnabled; public bool IsEnabled { get { return _isEnabled; } set { SetProperty(ref _isEnabled, value); } } private double _value; public double Value { get { return _value; } set { SetProperty(ref _value, value); } } public LogicalType LogicalType { get; set; } public Dictionary Input { get; set; } = new Dictionary(); public Dictionary Output { get; set; } = new Dictionary(); public override void ClearConnectors() { Connectors.Clear(); Input.Clear(); Output.Clear(); } public virtual LogicalConnectorInfo ExecuteAddInput(object parameter, int index = 0, string name = null) { if (Input.Values.Count >= 2) { this.ItemHeight = this.ItemHeight * (Input.Values.Count + 1) / Input.Values.Count; } LogicalConnectorInfo connector = new LogicalConnectorInfo(this, ConnectorOrientation.Left, true, false, ValueTypeInput.Count > index ? ValueTypeInput[index] : ValueTypeInput[0]); connector.XRatio = 0; connector.Name = name ?? $"Input{index}"; Input.Add(Input.Count, connector); for (int i = 0; i < Input.Values.Count; i++) { Input[i].YRatio = (i + 1.0) / (Input.Values.Count + 1.0); } AddConnector(connector); return connector; } public virtual LogicalConnectorInfo ExecuteAddToInput(LogicalConnectorInfo connector) { //if (Input.Values.Count >= 2) //{ // this.ItemHeight = this.ItemHeight * (Input.Values.Count + 1) / Input.Values.Count; //} connector.Orientation = ConnectorOrientation.Left; connector.IsInnerPoint = true; connector.IsPortless = false; connector.XRatio = 0; Input.Add(Input.Count, connector); for (int i = 0; i < Input.Values.Count; i++) { Input[i].YRatio = (i + 1.0) / (Input.Values.Count + 1.0); } AddConnector(connector); return connector; } public virtual LogicalConnectorInfo ExecuteAddOutput(object parameter, int index = 0, string name = null) { LogicalConnectorInfo connector = new LogicalConnectorInfo(this, ConnectorOrientation.Right, true, false, ValueTypeOutput.Count > index ? ValueTypeOutput[index] : ValueTypeInput[0]); connector.XRatio = 1; connector.Name = name ?? $"Output{index}"; Output.Add(Output.Count, connector); for (int i = 0; i < Output.Values.Count; i++) { Output[i].YRatio = (i + 1.0) / (Output.Values.Count + 1.0); } AddConnector(connector); return connector; } public virtual LogicalConnectorInfo ExecuteAddToOutput(LogicalConnectorInfo connector) { connector.Orientation = ConnectorOrientation.Right; connector.IsInnerPoint = true; connector.IsPortless = false; connector.XRatio = 1; Output.Add(Output.Count, connector); for (int i = 0; i < Output.Values.Count; i++) { Output[i].YRatio = (i + 1.0) / (Output.Values.Count + 1.0); } AddConnector(connector); return connector; } public virtual List ValueTypeInput { get { return new List() { ConnectorValueType.Real }; } } public virtual List ValueTypeOutput { get { return new List() { ConnectorValueType.Real }; } } public void Execute() { GetInput(); CalculateOutput(); } public virtual void GetInput() { foreach (var input in Input) { var connector = GetSourceItem(input.Value); if (connector == null) { input.Value.ErrorCode = ConnectorErrorCode.None; continue; } if (connector.SourceConnectorInfoFully?.DataItem is LogicalGateItemViewModelBase sourceItem) { var output = (connector.SourceConnectorInfoFully as LogicalConnectorInfo); if (EnableInputValue(connector, input.Value, output)) { connector.ColorViewModel.LineColor.Color = output.ColorViewModel.FillColor.Color; connector.ColorViewModel.FillColor.Color = output.ColorViewModel.FillColor.Color; connector.AnimationViewModel.Color = output.ColorViewModel.FillColor.Color; input.Value.ConnectorValue = output.ConnectorValue; input.Value.ConnectorString = output.ConnectorString; input.Value.ColorViewModel.FillColor.Color = connector.SourceConnectorInfoFully.ColorViewModel.FillColor.Color; if (LogicalType == LogicalType.Output) { input.Value.ConnectorValueType = (connector.SourceConnectorInfoFully as LogicalConnectorInfo).ConnectorValueType; } else if (LogicalType == LogicalType.NOT) { input.Value.ConnectorValueType = ((connector.SourceConnectorInfoFully as LogicalConnectorInfo).ConnectorValueType == ConnectorValueType.Bool) ? ConnectorValueType.Bool : ConnectorValueType.Int; } sourceItem.ClearOutputValue(connector, output); } sourceItem.StartAnimation(output); } } } public virtual void CalculateOutput() { foreach (var output in Output) { if (output.Value.ErrorCode != ConnectorErrorCode.None) { output.Value.ColorViewModel.FillColor.Color = Colors.DarkRed; } else if (output.Value.ConnectorValueType == ConnectorValueType.Bool) { if (output.Value.ConnectorValue == 0) { output.Value.ColorViewModel.FillColor.Color = Colors.Red; if (LogicalType == LogicalType.Output) { ColorViewModel.FillColor.Color = Colors.Red; } } else { output.Value.ColorViewModel.FillColor.Color = Colors.Green; if (LogicalType == LogicalType.Output) { ColorViewModel.FillColor.Color = Colors.Green; } } } else if (output.Value.ConnectorValueType <= ConnectorValueType.ValueType) { output.Value.ColorViewModel.FillColor.Color = Colors.Green; } } } public virtual bool EnableInputValue(ConnectionViewModel connector, LogicalConnectorInfo input, LogicalConnectorInfo output) { if (!input.CanAttachTo(output)) { input.ErrorCode = ConnectorErrorCode.ConnErr; input.ErrorMessage = "连接类型不匹配"; input.ColorViewModel.FillColor.Color = Colors.DarkRed; return false; } if (output.ErrorCode == ConnectorErrorCode.ExecuteErr) { input.ErrorCode = ConnectorErrorCode.ExecuteErr; input.ErrorMessage = "无效的输入"; input.ColorViewModel.FillColor.Color = Colors.DarkRed; return false; } return true; } public virtual void ClearOutputValue(ConnectionViewModel connector, LogicalConnectorInfo output) { } public virtual void StartAnimation(LogicalConnectorInfo output) { } protected ConnectionViewModel GetSourceItem(FullyCreatedConnectorInfo sinkConnector) { return Root?.Items.OfType().FirstOrDefault(p => p.SinkConnectorInfo == sinkConnector); } protected ConnectionViewModel GetSinkItem(FullyCreatedConnectorInfo sourceConnector) { return Root?.Items.OfType().FirstOrDefault(p => p.SourceConnectorInfoFully == sourceConnector); } } }