Skip to content
This repository was archived by the owner on Apr 13, 2026. It is now read-only.

Add Tab-Pass Node for cross-tab signal routing - #37

Merged
lunarcloud merged 5 commits into
mainfrom
copilot/add-special-tab-pass-node
Mar 19, 2026
Merged

lunarcloud merged 5 commits into
mainfrom
copilot/add-special-tab-pass-node

Conversation

Copilot AI commented Mar 19, 2026 •

Copy link
Copy Markdown

Adds a new "Tab Pass" node type that lets connections flow between tabs. Creating one node automatically creates a linked sibling; connectors are mirrored (input on one ↔ output on the other), and the two nodes stay in sync as slots are added, removed, or renamed.

New types

  • TabPassConnectorSlot — named connector slot with direction (IsInput) relative to its owner node
  • TabPassNode — paired node with shared PairId (Guid), PairIndex (1 or 2), transient Pair reference, observable ConnectorSlots, and shared PairLabel display name

Behavior

  • Pair creation: AddNodeAt("Tab Pass", ...) creates two linked nodes side-by-side with default slots In 1 (input) and Out 1 (output); the sibling has the mirrors
  • Slot sync: AddConnectorSlot(name, isInput) propagates a mirrored slot to the sibling automatically; removal syncs back and cleans up connections across all tabs
  • Slot name sync: Renaming a connector slot on either node propagates the new name to the matching ConnectorViewModel on the same node and to the mirrored slot and connector on the paired node
  • Pair name sync: Both nodes share a PairLabel display name. Editing it on either node automatically updates the other. The node header on the canvas shows PairLabel (via the DisplayName virtual property on NodeViewModel). The unique internal Name is auto-generated as {PairLabel}.1 and {PairLabel}.2 (using PairIndex) and is never shown to the user
  • Editable slot names: The properties panel slot list uses editable TextBox fields so connector names can be changed inline
  • Configurable I/O: Properties panel exposes + Input / + Output buttons and per-slot ✕ remove buttons
  • Clone: Copy-paste produces a standalone (unpaired) copy with a fresh PairId and no inherited pair label

Serialization

NodeData gains pairId, pairLabel, pairIndex, and slots fields. After all tabs are deserialized, LinkTabPassPairs() reconnects siblings by matching PairId across tabs.

Undo/redo

Three new actions: AddTabPassPairAction, AddTabPassSlotAction, RemoveTabPassSlotAction. Slot undo/redo uses RemoveTabPassSlotCore (bypasses recording) to avoid stack corruption when the undo action itself would re-enqueue a new undo entry.

UI

New Utilities gallery group in the Nodes ribbon tab. Properties panel shows:

  • Pair Name — editable field bound to PairLabel; changes propagate to the paired node and auto-update both nodes' internal names to {PairLabel}.1 / {PairLabel}.2
  • Editable connector slot list with direction labels and add/remove controls

Context menu fix

Right-click node context menu options (Delete, Move To Tab, Rename, Properties) now reliably work. The tunnel pointer handler captures _contextMenuTargetNode before NodifyEditor can deselect nodes. A RestoreContextMenuTargetSelection() helper is called at the start of every menu item click handler to restore IsSelected and SelectedNode, ensuring commands always have a valid target regardless of NodifyEditor's deselection behavior.

Original prompt

This section details on the original issue you should resolve

<issue_title>Special Tab-Pass Node</issue_title>
<issue_description>There should be a node type. It's goal is to allow connections to go from one tab to another.

  1. When you created it, it's pair is also created next to it.
  2. It has a configurable number of input and output connections
  3. The two nodes always keep their connectors in sync, but opposite. An input on one shows as an output on the other</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

Co-authored-by: lunarcloud <1565970+lunarcloud@users.noreply.github.com>
Copilot AI changed the title [WIP] Add special tab-pass node for tab connections Add Tab-Pass Node for cross-tab signal routing Mar 19, 2026
Copilot AI requested a review from lunarcloud March 19, 2026 12:39
@lunarcloud

Copy link
Copy Markdown
Owner

@copilot three notes:

  • I want to be able to name the inputs and outputs
  • I want the names to be in sync (we can have a hidden differentiator if necessary)
  • I cannot test this feature, as the "move to tab" doesn't work for me (none of the right click on node options do)

Co-authored-by: lunarcloud <1565970+lunarcloud@users.noreply.github.com>

Copilot AI commented Mar 19, 2026 •

Copy link
Copy Markdown
Author

@copilot three notes:

  • I want to be able to name the inputs and outputs
  • I want the names to be in sync (we can have a hidden differentiator if necessary)
    ...

Done in commit 939f65b:

  1. Editable slot names — The slot name display in the properties panel is now a TextBox with two-way binding instead of a read-only TextBlock. ConnectorViewModel.Name is now observable so the node connector label updates live.

  2. Names in sync — Renaming a slot on either node propagates to the matching slot and ConnectorViewModel on the paired node. A _isSyncingSlotName flag prevents infinite recursion.

  3. Context menu fix — Added right-click detection in the tunnel pointer handler (OnEditorPointerPressedTunnel). When the user right-clicks a node, the handler now walks the visual tree to find the NodeViewModel and sets SelectedNode before the context menu opens. This ensures "Delete", "Move To Tab", and other commands have a valid target.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • av-build-tel-api-v1.avaloniaui.net
    • Triggering command: /usr/share/dotnet/dotnet dotnet exec --runtimeconfig /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/runtimeconfig.json /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/Avalonia.BuildServices.Collector.dll (dns block)
    • Triggering command: /usr/share/dotnet/dotnet dotnet exec --runtimeconfig /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/runtimeconfig.json /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/Avalonia.BuildServices.Collector.dll de.cs (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@lunarcloud

Copy link
Copy Markdown
Owner

@copilot two notes:

  • I still can't right click and move a node - right clicking de-selects the node so nothing happens on any context menu item.
  • the node's name isn't syncing

Co-authored-by: lunarcloud <1565970+lunarcloud@users.noreply.github.com>

Copilot AI commented Mar 19, 2026 •

Copy link
Copy Markdown
Author

@copilot two notes:

  • I still can't right click and move a node - right clicking de-selects the node so nothing happens on any context menu item.
  • the node's name isn't syncing

Fixed in commit 270d82b:

Context menu: Right-clicking now always works. The right-click tunnel handler captures _contextMenuTargetNode before NodifyEditor can deselect. A new RestoreContextMenuTargetSelection() helper is called at the top of every click handler (Delete, Rename, Move To Tab, Properties) to set node.IsSelected = true and restore SelectedNode, even if NodifyEditor cleared it.

Node name sync: Added a PairLabel property to TabPassNode. Both nodes of a pair share the same label — editing one automatically updates the other. The node header on the canvas now shows PairLabel for Tab-Pass nodes (overrides the base DisplayName property). The properties panel has:

  • Pair Name — editable TextBox bound to PairLabel (syncs to partner node)
  • Internal name — read-only TextBox showing the unique internal Name (used in connections/serialization)
  • Paired with — shows the internal name of the partner node

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • av-build-tel-api-v1.avaloniaui.net
    • Triggering command: /usr/share/dotnet/dotnet dotnet exec --runtimeconfig /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/runtimeconfig.json /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/Avalonia.BuildServices.Collector.dll (dns block)
    • Triggering command: /usr/share/dotnet/dotnet dotnet exec --runtimeconfig /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/runtimeconfig.json /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/Avalonia.BuildServices.Collector.dll indowViewModel.cs (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@lunarcloud

Copy link
Copy Markdown
Owner

@copilot can we keep "internal name" hidden from the properties editor and automatically set it to like "{pairName}.1" and "{pairName}.2"

…erties panel

Co-authored-by: lunarcloud <1565970+lunarcloud@users.noreply.github.com>

Copilot AI commented Mar 19, 2026 •

Copy link
Copy Markdown
Author

@copilot can we keep "internal name" hidden from the properties editor and automatically set it to like "{pairName}.1" and "{pairName}.2"

Done in commit b718273.

The "Internal name" and "Paired with" fields are now hidden from the properties panel. The internal name is auto-set to {pairName}.1 and {pairName}.2 whenever the Pair Name is edited — you only see and edit the shared Pair Name:

  • Changing "Pair Name" in the properties panel instantly renames both nodes (e.g. Signal.1 and Signal.2) across all tabs
  • If the Pair Name is cleared, the names fall back to Tab Pass 1 / Tab Pass 2
  • The .1 / .2 suffix is preserved in serialization so pairs reconnect correctly on load

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • av-build-tel-api-v1.avaloniaui.net
    • Triggering command: /usr/share/dotnet/dotnet dotnet exec --runtimeconfig /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/runtimeconfig.json /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/Avalonia.BuildServices.Collector.dll (dns block)
    • Triggering command: /usr/share/dotnet/dotnet dotnet exec --runtimeconfig /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/runtimeconfig.json /home/REDACTED/.nuget/packages/avalonia.buildservices/11.3.2/tools/netstandard2.0/Avalonia.BuildServices.Collector.dll indowViewModel.cs (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@lunarcloud
lunarcloud marked this pull request as ready for review March 19, 2026 13:43
@lunarcloud
lunarcloud merged commit 67a380c into main Mar 19, 2026
3 of 4 checks passed
@lunarcloud
lunarcloud deleted the copilot/add-special-tab-pass-node branch March 19, 2026 13:47
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Special Tab-Pass Node

2 participants