using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using AIStudio.Wpf.DiagramDesigner.Helpers; namespace AIStudio.Wpf.DiagramDesigner { public class BlockItemsContainer : ContentControl { static BlockItemsContainer() { DefaultStyleKeyProperty.OverrideMetadata(typeof(BlockItemsContainer), new FrameworkPropertyMetadata(typeof(BlockItemsContainer))); } public static readonly DependencyProperty BorderProperty = DependencyProperty.Register( nameof(Border), typeof(object), typeof(BlockItemsContainer), new PropertyMetadata(default(object))); public object Border { get => GetValue(BorderProperty); set => SetValue(BorderProperty, value); } public static readonly DependencyProperty BorderTemplateProperty = DependencyProperty.Register( nameof(BorderTemplate), typeof(DataTemplate), typeof(BlockItemsContainer), new PropertyMetadata(default(DataTemplate))); [Bindable(true), Category("Content")] public DataTemplate BorderTemplate { get => (DataTemplate)GetValue(BorderTemplateProperty); set => SetValue(BorderTemplateProperty, value); } public static readonly DependencyProperty BorderTemplateSelectorProperty = DependencyProperty.Register( nameof(BorderTemplateSelector), typeof(DataTemplateSelector), typeof(BlockItemsContainer), new PropertyMetadata(default(DataTemplateSelector))); [Bindable(true), Category("Content")] public DataTemplateSelector BorderTemplateSelector { get => (DataTemplateSelector)GetValue(BorderTemplateSelectorProperty); set => SetValue(BorderTemplateSelectorProperty, value); } public static readonly DependencyProperty BorderStringFormatProperty = DependencyProperty.Register( nameof(BorderStringFormat), typeof(string), typeof(BlockItemsContainer), new PropertyMetadata(default(string))); [Bindable(true), Category("Content")] public string BorderStringFormat { get => (string)GetValue(BorderStringFormatProperty); set => SetValue(BorderStringFormatProperty, value); } public static readonly DependencyProperty ParentPanelProperty = DependencyProperty.Register(nameof(ParentPanel), typeof(FrameworkElement), typeof(BlockItemsContainer), new FrameworkPropertyMetadata(null)); public FrameworkElement ParentPanel { get { return (FrameworkElement)GetValue(ParentPanelProperty); } set { SetValue(ParentPanelProperty, value); } } public static readonly DependencyProperty GetOffSetFuncProperty = DependencyProperty.Register(nameof(GetOffSetFunc), typeof(Func), typeof(BlockItemsContainer), new FrameworkPropertyMetadata(null)); public Func GetOffSetFunc { get { return (Func)this.GetValue(GetOffSetFuncProperty); } set { this.SetValue(GetOffSetFuncProperty, value); } } public Func GetOffSet { get { return new Func(() => this.TransformToAncestor(ParentPanel).Transform(new Point(0, 0))); } } public BlockItemsContainerInfo Info { get { if (Border is BlockItemsContainerInfo itemsContainerInfo) return itemsContainerInfo; return this.DataContext as BlockItemsContainerInfo; } } public BlockDesignerItemViewModel DragObject { get; private set; } public Point DragOffset { get; private set; } public Point? FirstPoint { get; private set; } public BlockItemsContainer() { } public static List Containers = new List(); public override void OnApplyTemplate() { base.OnApplyTemplate(); GetOffSetFunc = GetOffSet; } protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { base.OnMouseLeftButtonDown(e); FirstPoint = e.GetPosition(this); Containers.Add(this); } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (FirstPoint != null) { var currentPoint = e.GetPosition(this); if (Math.Sqrt(Math.Pow(FirstPoint.Value.X - currentPoint.X, 2) + Math.Pow(FirstPoint.Value.Y - currentPoint.Y, 2)) > 5) { FirstPoint = null; if (Info?.Children.Count > 0) { var borders = VisualHelper.FindVisualChildren(this); foreach (var border in borders) { var itemsContainers = VisualHelper.TryFindParent(border); if (this != itemsContainers) { continue; } var point = border.TransformToAncestor(this).Transform(new Point(0, 0)); var rect = new Rect(point.X, point.Y, border.ActualWidth, border.ActualHeight); if (rect.Contains(currentPoint)) { DragObject = border.DataContext as BlockDesignerItemViewModel; DragOffset = new Point(currentPoint.X - point.X, currentPoint.Y - point.Y); break; } } if (DragObject != null) { Containers.ForEach(p => p.FirstPoint = null); DesignerCanvas canvas = GetDesignerCanvas(this); if (canvas != null) { canvas.SourceItemsContainer = this; e.Handled = true; } } } } } } protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); FirstPoint = null; Containers.Clear(); } public ConnectorOrientation Orientation { get; set; } // iterate through visual tree to get parent DesignerCanvas private DesignerCanvas GetDesignerCanvas(DependencyObject element) { while (element != null && !(element is DesignerCanvas)) element = VisualTreeHelper.GetParent(element); return element as DesignerCanvas; } } }