OverviewFilesCommitsIssuesDocsReleasesPeers

ifsrenderer-linux / WpfDisplay / Views / Node.xaml.cs

143 lines · csharp ref:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

using CommunityToolkit.Mvvm.Input;

using WpfDisplay.Helper;
using WpfDisplay.ViewModels;

namespace WpfDisplay.Views;

/// <summary>
/// Interaction logic for Node.xaml
/// </summary>
public partial class Node : UserControl
{
    private IteratorViewModel vm => (IteratorViewModel)DataContext;
    private ContentPresenter _parentContainer;
    private Vector? _t;

    public static readonly DependencyProperty IsMouseDownProperty =
        DependencyProperty.Register("IsMouseDown", typeof(bool), typeof(Node), new PropertyMetadata(false));

    public RelayCommand<IteratorViewModel> SelectCommand
    {
        get => (RelayCommand<IteratorViewModel>)GetValue(SelectCommandProperty);
        set => SetValue(SelectCommandProperty, value);
    }
    public static readonly DependencyProperty SelectCommandProperty =
        DependencyProperty.Register("SelectCommand", typeof(RelayCommand<IteratorViewModel>), typeof(Node), new PropertyMetadata(null));

    public BindablePoint Position
    {
        get => (BindablePoint)GetValue(PositionProperty);
        set => SetValue(PositionProperty, value);
    }
    public static readonly DependencyProperty PositionProperty =
        DependencyProperty.Register("Position", typeof(BindablePoint), typeof(Node), new PropertyMetadata(new BindablePoint(0, 0), (s, e) =>
        {
            var container = ((Node)s)._parentContainer;
            if (container is not null)
            {
                Canvas.SetLeft(container, ((BindablePoint)e.NewValue).X);
                Canvas.SetTop(container, ((BindablePoint)e.NewValue).Y);
            }
        }));

    //Positioning is relative to this element
    public FrameworkElement ParentCanvas
    {
        get => (FrameworkElement)GetValue(ParentCanvasProperty);
        set => SetValue(ParentCanvasProperty, value);
    }
    public static readonly DependencyProperty ParentCanvasProperty =
        DependencyProperty.Register("ParentCanvas", typeof(FrameworkElement), typeof(Node), new PropertyMetadata(null));

    public Node()
    {
        InitializeComponent();
        Loaded += (s, e) =>
        {
            _parentContainer = (ContentPresenter)System.Windows.Media.VisualTreeHelper.GetParent(this);

            Position = vm.Position;
            Canvas.SetLeft(_parentContainer, vm.Position.X);
            Canvas.SetTop(_parentContainer, vm.Position.Y);
            vm.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName is nameof(vm.Position))
                {
                    Canvas.SetLeft(_parentContainer, vm.Position.X);
                    Canvas.SetTop(_parentContainer, vm.Position.Y);
                }
            };

        };
    }

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        e.Handled = true;
        SetValue(IsMouseDownProperty, true);
    }

    protected override void OnMouseUp(MouseButtonEventArgs e)
    {
        base.OnMouseUp(e);
        e.Handled = true;
        SetValue(IsMouseDownProperty, false);
        _t = null;
        Mouse.Capture(null);
        if (e.ChangedButton == MouseButton.Left)
        {
            var vm = (IteratorViewModel)DataContext;
            vm.FinishConnecting();
            SelectCommand.Execute(vm);
        }
    }

    private Point GetCanvasPosition() => new(Canvas.GetLeft(_parentContainer), Canvas.GetTop(_parentContainer));

    private void dragHandle_MouseMove(object sender, MouseEventArgs e)
    {
        if (_t is not null)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Mouse.Capture((IInputElement)sender);
                e.Handled = true;
                Position = BindablePoint.FromPoint(e.GetPosition(ParentCanvas) + _t.Value);
            }
        }
    }

    protected override void OnMouseLeave(MouseEventArgs e)
    {
        base.OnMouseLeave(e);
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            e.Handled = true;
            vm.StartConnecting();
        }
    }

    private void UserControl_GotFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        var vm = (IteratorViewModel)DataContext;
        SelectCommand.Execute(vm);
    }

    private void Label_MouseDown(object sender, MouseButtonEventArgs e)
    {
        e.Handled = true;
        if (e.ChangedButton == MouseButton.Left && e.ButtonState == MouseButtonState.Pressed)
        {
            _t = GetCanvasPosition() - e.GetPosition(ParentCanvas);
        }
    }

    private void ellipseBody_MouseDown(object sender, MouseButtonEventArgs e) => Focus();
}