I want to extend the basic edge to add extra functionality that I need, but I also want to disable the ability to drag it out of a port.
The port dragging functionality is provided by the EdgeManipulator that is added to the Edge in its constructor with
this.AddManipulator(new EdgeManipulator());
The problem is that this doesn’t keep a reference to the created manipulator, and there doesn’t seem to be a way to remove a manipulator without a direct reference to it.
Not exactly the solution I wanted, but I managed to find a hack that works.
Intercepting the mouse movement event and disabling its further propagation will prevent it from reaching the EdgeManipulator, and thus disable the port dragging.
The caveat is that any other functionality that relies on the mouse move event is also disabled unless explicitly forwarded from this hack. Which is not pretty.
The code for anyone interested:
public override void HandleEvent(EventBase evt)
{
if (evt is MouseMoveEvent)
{
evt.StopImmediatePropagation();
}
else
{
base.HandleEvent(evt);
}
}
I too think this is an important basic feature that is missing.
In my case I wanted to remove a manipulator automatically added to GraphView by Unity, but it seems impossible as I don’t have any reference to this manipulator.
We really need a way to get all manipulators associated to a given VisualElement.
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace YourNamespace
{
public abstract class ManipulatorBase<T> : Manipulator
where T : ManipulatorBase<T>
{
/// <summary>
/// All manipulators that are linked to an element AND whose 'target' element is currently attached to a panel.
/// </summary>
public static List<T> ActiveManipulators = new List<T>();
public event Action<T> OnRegisterCallbacksOnTarget;
public event Action<T> OnUnregisterCallbacksOnTarget;
public event Action<T, AttachToPanelEvent> OnElementAttachToPanel;
public event Action<T, DetachFromPanelEvent> OnElementDetachFromPanel;
protected override void RegisterCallbacksOnTarget()
{
addToManipulators();
target.UnregisterCallback<AttachToPanelEvent>(onAttach);
target.RegisterCallback<AttachToPanelEvent>(onAttach);
target.UnregisterCallback<DetachFromPanelEvent>(onDetached);
target.RegisterCallback<DetachFromPanelEvent>(onDetached);
OnRegisterCallbacksOnTarget?.Invoke((T)this);
}
protected virtual void onAttach(AttachToPanelEvent evt)
{
addToManipulators();
OnElementAttachToPanel?.Invoke((T)this, evt);
}
protected virtual void onDetached(DetachFromPanelEvent evt)
{
removeFromManipulators();
OnElementDetachFromPanel?.Invoke((T)this, evt);
}
protected override void UnregisterCallbacksFromTarget()
{
target.UnregisterCallback<AttachToPanelEvent>(onAttach);
target.UnregisterCallback<DetachFromPanelEvent>(onDetached);
removeFromManipulators();
OnUnregisterCallbacksOnTarget?.Invoke((T)this);
}
protected void addToManipulators()
{
if (!ActiveManipulators.Contains((T)this))
{
ActiveManipulators.Add((T)this);
}
}
protected void removeFromManipulators()
{
if (ActiveManipulators.Contains((T)this))
{
ActiveManipulators.Remove((T)this);
}
}
public static T GetManipulatorOnElement(VisualElement element)
{
foreach (var m in ActiveManipulators)
{
if (m != null && m.target != null && m.target == element)
return m;
}
return null;
}
}
}