In IMGUI TreeView, there’s some methods that can be overridden to provide context click functionality for the treeView and items:
These are missing on TreeView and ListView in UIToolkit.
If we’re supposed to handle this manually in UIToolkit, how can we capture the item that was context clicked?
Looking at the source code for BaseVerticalCollectionView, the mouse down method only handles left-click:
private void ProcessPointerDown(IPointerEvent evt)
{
if (!HasValidDataAndBindings())
return;
if (!evt.isPrimary)
return;
if (evt.button != (int)MouseButton.LeftMouse)
return;
if (evt.pointerType != PointerType.mouse)
{
m_TouchDownPosition = evt.position;
return;
}
DoSelect(evt.localPosition, evt.clickCount, evt.actionKey, evt.shiftKey);
}
And getting the item from a click is not publicly accessible (hidden behind virtualizationController):
private void DoSelect(Vector2 localPosition, int clickCount, bool actionKey, bool shiftKey)
{
var clickedIndex = virtualizationController.GetIndexFromPosition(localPosition);
I want to handle context click for an entire row, not the cells in each row.
How can I do this?
Is there an inbuilt method to find and element in a tree view from a position?
I would imagine that being quite complex, given there’s a scroll view, variable heights, multiple levels of nesting.
All I can find is an internal class VirtualizationController that does this. But again, no publicly available.
Maybe it’s possible to copy that method, but haven’t looked to deep into it. Just so frustrating that there’s all this useful functionality hidden away
Just for posterity, looks like in Unity 6, they have also made right click select items, which matches the IMGUI version. So your idea of using selected indices would work there. Unfortunately I’m on 2022.3
You can do this by using the BindItem method and capturing a context click event on a row. Something like this. You could even attempt listening for a ContextClickEvent
listView.makeItem = MakeItem;
listView.bindItem = BindItem;
VisualElement MakeItem()
{
var item = new Label();
item.style.flexGrow = 1;
return item;
}
void BindItem(VisualElement element, int index)
{
var label = element as Label;
label.text = $"Item {index}";
// Register callback for right mouse button click
label.RegisterCallback<PointerUpEvent>(evt =>
{
if (evt.button == (int)MouseButton.RightMouse)
{
evt.StopPropagation();
HandleContextClick(index);
}
}, TrickleDown.TrickleDown);
}