using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Controls.Primitives; using System.Windows.Media; using AIStudio.Wpf.DiagramDesigner.Geometrys; namespace AIStudio.Wpf.DiagramDesigner.Controls { public class DragThumb : Thumb { public DragThumb() { base.DragDelta += new DragDeltaEventHandler(DragThumb_DragDelta); base.DragStarted += DragThumb_DragStarted; base.DragCompleted += DragThumb_DragCompleted; } public IDiagramViewModel DiagramViewModel { get { return (this.DataContext as SelectableDesignerItemViewModelBase)?.Root; } } private List designerItems; private bool drag; private void DragThumb_DragStarted(object sender, DragStartedEventArgs e) { GetDesignerCanvas(this)?.Focus(); drag = false; SelectableDesignerItemViewModelBase designerItem = this.DataContext as SelectableDesignerItemViewModelBase; if (designerItem != null && designerItem.IsSelected) { // we only move DesignerItems designerItems = designerItem.Root.SelectedItems.ToList(); if (designerItem is IGroupable groupable) { designerItems.AddRange(designerItem.Root.SelectionService.GetGroupMembers(groupable).OfType()); } //拖动连线,把连接者也一起移动 if (designerItem is ConnectionViewModel connector) { if (connector.SourceConnectorInfoFully != null) { designerItems.Add(connector.SourceConnectorInfoFully.DataItem); } if (connector.SinkConnectorInfoFully != null) { designerItems.Add(connector.SinkConnectorInfoFully.DataItem); } } if (designerItem is PointDesignerItemViewModel) { designerItems = new List { designerItem }; } designerItems = designerItems.Distinct().ToList(); Interlocked.Increment(ref DiagramViewModel.DoCommandManager.BeginDo); foreach (DesignerItemViewModelBase item in designerItems.OfType()) { item.SetOldValue(item.TopLeft, nameof(item.TopLeft)); } //部分连接点可以移动 foreach (ConnectionViewModel item in designerItems.OfType()) { item.SourceConnectorInfoPart?.SetOldValue(item.SourceConnectorInfoPart.Position, nameof(item.SourceConnectorInfoPart.Position)); item.SinkConnectorInfoPart?.SetOldValue(item.SinkConnectorInfoPart.Position, nameof(item.SinkConnectorInfoPart.Position)); } e.Handled = true; } else { designerItems = null; } } private void DragThumb_DragCompleted(object sender, DragCompletedEventArgs e) { if (drag == false) { Interlocked.Decrement(ref DiagramViewModel.DoCommandManager.BeginDo); return; } if (designerItems != null) { foreach (DesignerItemViewModelBase item in designerItems.OfType()) { item.SetCellAlignment(); } Dictionary> infos = designerItems.OfType().ToDictionary(p => p, p => new Tuple(p.GetOldValue(nameof(p.TopLeft)), p.TopLeft)); //部分连接点可以移动 Dictionary, Tuple>> conncetorinfos = designerItems.OfType().ToDictionary(p => p, p => new Tuple, Tuple>( new Tuple(p.SourceConnectorInfoPart?.GetOldValue(nameof(p.SourceConnectorInfoPart.Position)), p.SinkConnectorInfoPart?.GetOldValue(nameof(p.SinkConnectorInfoPart.Position))), new Tuple(p.SourceConnectorInfoPart?.Position, p.SinkConnectorInfoPart?.Position))); Interlocked.Decrement(ref DiagramViewModel.DoCommandManager.BeginDo); DiagramViewModel.DoCommandManager.DoNewCommand(this.ToString(), () => { foreach (var info in infos) { info.Key.TopLeft = info.Value.Item2; } foreach (var info in conncetorinfos) { info.Key.SetPartPostion(info.Value.Item2.Item1, info.Value.Item2.Item2); } }, () => { foreach (var info in infos) { info.Key.TopLeft = info.Value.Item1; } foreach (var info in conncetorinfos) { info.Key.SetPartPostion(info.Value.Item1.Item1, info.Value.Item1.Item2); } }); e.Handled = true; } } void DragThumb_DragDelta(object sender, DragDeltaEventArgs e) { drag = true; if (designerItems != null) { foreach (DesignerItemViewModelBase item in designerItems.OfType()) { item.Left += e.HorizontalChange; item.Top += e.VerticalChange; } //部分连接点可以移动 foreach (ConnectionViewModel item in designerItems.OfType()) { PointBase? sourcePoint = null; PointBase? sinkPoint = null; if (item.SourceConnectorInfoPart != null) { sourcePoint = new PointBase(item.SourceConnectorInfoPart.Position.X + e.HorizontalChange, item.SourceConnectorInfoPart.Position.Y + e.VerticalChange); } if (item.SinkConnectorInfoPart != null) { sinkPoint = new PointBase(item.SinkConnectorInfoPart.Position.X + e.HorizontalChange, item.SinkConnectorInfoPart.Position.Y + e.VerticalChange); } item.SetPartPostion(sourcePoint, sinkPoint); } e.Handled = true; } } private DesignerCanvas GetDesignerCanvas(DependencyObject element) { while (element != null && !(element is DesignerCanvas)) element = VisualTreeHelper.GetParent(element); return element as DesignerCanvas; } } }