Table of Contents

Controller Branch

The Controller branch is the SoftNcRunner-native settings face: the controller the project actually parses NC with, edited one tree node at a time. It lives on the General Setup page at /general-setup under the Control-Tree id equipment/controller, and grows two plane stems beneath it — equipment/controller/machine and equipment/controller/program-data. A bookmark to the retired /controller address, where the Legacy Controller page used to edit the deprecating HardNcEnv model instead of the runner, redirects to this branch root.

Important

Anatomy makes no claim that these ids are stable across versions. See Tree Ids and Routes for the migration hop that keeps an older link resolving.

Key Models

  • NcRunnerSuit — the switchable suit the branch edits: one runner plus the per-workpiece dependency list the runner's proxy placeholders resolve against. A suit constructs on the Fanuc preset, and a project file that carried no runner element keeps that.
  • SoftNcRunner — the NC pipeline itself, and the object the branch root's Object-Management menu loads, pastes and saves.
  • PipelineNcDependencyList — what a runner file carries.
  • PerCaseNcDependencyList — what stays on the project.
  • CncBrandDependency — the brand marker the root panel's badge reads. Its Brand is a plain string with five declared tokens, so the marker can be edited independently of the dependency list it sits in.
  • SoftNcRunner — the facade setter every install and every brand switch assigns through. It re-binds the proxies to the suit, stamps the machining chain's axis codes onto the axis config, and resets the per-session runner state.

Every value the branch reads is resolved through GetEffectiveNcDependencyList(API) rather than the raw pipeline list: the proxies deliberately implement no machine-config interface, so a consumer that read the raw list would see a placeholder instead of the table. The tree itself speaks domain vocabulary only — brand, machine limits, work coordinates. The dependency pipeline, the proxy indirection and the brand preset lists have no node.

The Two Planes

The branch root's children are two Group stems, and neither is ever empty: each carries at least one leaf that every runner grows. A stem's editor panel is the shared group panel — an intro line over a clickable list of its children.

Machine / Controller (equipment/controller/machine) introduces itself as "Machine and controller presets that travel with the runner file — brand, travel limits, rapid rates, home / G28 reference, the tool-change position and the controller parameters (in both a domain-grouped interface form and the native parameter form)."

Program Data (equipment/controller/program-data) introduces itself as "Data that travels with the workpiece / project — work-coordinate offsets (G54…), tool offsets and the brand-specific per-case tables. Kept on the project even when the runner file is swapped."

What a runner file actually carries

The runner's pipeline list holds two kinds of entry, and the difference decides what an installed runner file changes.

Plain instances are the runner's own and are replaced outright by an install: the brand marker, the tool-change position, the block-skip, subprogram-folder and iteration-guard configs a given preset carries, and — on Siemens and Heidenhain — the generic fallback config those two presets add because their parameter tables declare no number for the peck clearance. That last entry is why Canned Cycle (Peck) is runner-owned on those two brands, while on the other three the same clearance is a row of the brand parameter table and stays with the project.

The brand parameter table is reached through a proxy instead. The proxy carries a machine-config seed, and that seed — not the live table — is what the runner file serializes. WireNcDependencyProxies(API) deep-clones the seed into the project's per-case list only when the project holds no table of that type yet; a project that already carries one keeps it. So the per-axis limits, rapid rates, home references, M-code declarations and native parameters a panel edits are stored on the project, and installing a same-brand runner file leaves them where they are while it does replace the plain instances above. The Fanuc-family and Syntec parameter tables are per-case because they mix machine configuration with per-case work-coordinate offsets, which the two planes could not otherwise split. The Siemens machine-data and Heidenhain tables hold no work coordinates and are per-case for the other half of the reason: a project's own table wins over the seed, so installing a same-brand runner file re-binds to the machine data already edited instead of resetting it to the preset's.

What survives a swap

The per-case list belongs to the project and survives an install or a brand switch, minus one step: after the new runner is assigned, per-case tables its proxies resolve nothing for are removed, so a project switched from Fanuc to Siemens does not keep a retained-common-variable table nothing reads. The generic tool-offset table survives every switch, because every brand preset proxies it. Switching back does not restore what the sweep removed. Only the brand parameter table returns from a seed, deep-cloned out of the new preset's proxy; the per-case tables beside it carry no seed at all, so their proxies create bare instances — a project switched back to Fanuc gets an empty retained-common-variable table, not the values it held before.

The Root Panel

The Controller node's editor is the branch root panel. Its header row carries three things:

  • The Object Management menu (), whose entries are Load, Save As, Copy, Paste and XML Mode. Load and Save As browse the server file system through the shared file-explorer dialog, filtered to *.Controller, *.SoftNcRunner and *.xml; Save As proposes the name NcRunner.Controller. Paste checks the pasted object against the expected type Hi.NcParsers.SoftNcRunner, HiMech. Load, Paste and an XML apply all install the swapped object onto the project and then regrow the branch. The button is disabled while no runner key is indexed, which is the state with no project open; with a project but no runner a blank placeholder is indexed so the menu stays reachable as a Load target.
  • A brand badge, shown only while a runner resolves. It reads the brand marker's string, or Unknown brand when the marker is empty.
  • A runner-file caption. It reads the side-file path recorded on the suit, or Embedded in project when the runner is inlined in the project file, or No NC runner when none resolves. The web service reads that recorded path and never writes it, so a Save As from this menu writes a file without changing what the caption names — and after an Object-Management install or a brand switch the caption still names the file the project was loaded with rather than the runner now in place.

Below the separator the panel shows one of two bodies. With a runner it shows the presets hint — "Machine / controller presets (brand, limits, rapid, home, tool change, parameters) travel with the runner and can be saved / loaded as a .SoftNcRunner asset via the ⋮ menu. Program data (work coordinates, tool offsets…) stays with this project's workpiece. Edit each group via this item's child tree-nodes." Both hint blocks name .SoftNcRunner, while the file picker offers .Controller first.

An orange line follows when the snapshot reports no axes: "No machine axes yet — per-axis rows (limits / rapid / home) are driven by the Machine Tool chain. Attach a machine tool to populate them." The axis set is read from the controller parameter table's axis-type rows, which the facade setter stamps from the Machine Tool chain — adding the chain's axes and keeping the table's persisted ones. Every brand preset's default table already declares X, Y and Z, so on a preset-built runner the warning does not appear; it is a live guard for a runner whose table declares no axis, or which resolves no parameter table at all.

When No Runner Resolves

With no project open the host skips the branch builder entirely, so the Controller node stands alone with no children, and the root panel shows its own no-runner block: an hourglass, "No NC controller runner on this project.", and the hint "Load a project, or use the ⋮ menu → Load to attach a .SoftNcRunner file." This block is the panel's own, not the shared empty state the leaf panels use.

With a project open the builder runs and returns no children when the snapshot reports no runner — and returns exactly the same empty result when the snapshot request throws. Nothing in the branch shape distinguishes a failed fetch from an absent runner, and neither does the root panel: a failed load resets the shared snapshot to the empty one, so the panel renders the same no-runner block. The only signal is the error toast that failed load raises. The builder's own fetch failure raises nothing, so a request that fails for the builder alone leaves a childless branch under a panel still showing the brand badge.

In practice a loaded project resolves a runner, since the suit's runner property constructs on the Fanuc preset and a project file with no runner element keeps that default. The empty branch is therefore what a reader meets before a project is open rather than a state a loaded project sits in.

How the Branch Regrows

Two panels in the whole branch report a structural change, and both scope it to the branch root:

  • The root panel, after an Object-Management Load, Paste or XML apply. It installs the indexed object onto the project, refreshes the shared snapshot and the runner key, and then emits — whether or not the install itself succeeded, so the branch always regrows against a fresh snapshot.
  • Controller Brand, after a brand switch, and only when the switch reported success.

The host resolves the named scope, re-runs the branch builder over it, and adds the node to the expansion list so the fresh children are visible. Because a brand switch replaces the whole runner, this is what makes the brand-driven leaves appear and disappear.

A brand switch that fails after the server has already assigned the preset leaves the two halves out of step: the shared snapshot is reloaded either way, so the badge and the brand select read the new brand, while the branch was not regrown and still lists the old brand's leaves.

The tree shape and the panels' own gate come from two independent requests for the same snapshot. The builder calls the endpoint directly; the panels read a module-singleton cache filled once per SPA session and refreshed on a project-presence change, an Object-Management install and a brand switch. No panel refreshes it, so an edit that empties a table changes neither the cache nor the branch until one of those happens.

Both structural writes are refused while an NC program is playing: installing a runner and switching brand each answer a conflict rather than swapping the parser under a running session.

Layout

  • General Setup Control Tree — the left dock of /general-setup
    • Controller Node Row — equipment/controller, built after Workpiece and ahead of the two optional runner-suit leaves
      • Machine / Controller Group Row — equipment/controller/machine
        • Controller Brand, Machine Limits (Stroke), Rapid Feedrates, Home / G28 Reference, Tool-Change Position, Controller Parameters — grown for every runner
        • M-Code Declarations, Canned Cycle (Peck), Block Skip / Delete, Subprogram Folders, Indexing Position Tables, Parameters (Native) — each grown only where the snapshot reports its backing entry. Across the shipped presets only Block Skip / Delete and Indexing Position Tables ever go missing; the other four are gated in code and unconditional in practice
      • Program Data Group Row — equipment/controller/program-data
        • Work Coordinates (G54…) and Tool Offsets — grown for every runner. The second reads Tool Offsets (ISO G43 H) while the Siemens $TC_DP table resolves, so the two offset ledgers do not read as one; its node id is unchanged by that relabel
        • Tool Offsets ($TC_DP), Tool Names, Datum Presets (Q339), Datum Shifts (D), Frames (Siemens), Retained Common Variables, R Parameters — each grown only where the snapshot reports its backing table
  • Editor Row — the panel of whichever node is selected
    • Controller Root Panel
      • Object Management Menu Button () — Load, Save As, Copy, Paste, XML Mode
      • Brand Badge — the brand marker, or Unknown brand
      • Runner File Caption — the recorded side file, Embedded in project, or No NC runner
      • No-Runner Block — hourglass icon, No NC controller runner on this project., and the attach-a-file hint; shown instead of the two items below
      • Presets Hint
      • No-Axes Warning — shown only while the snapshot carries no axis
    • Machine / Controller and Program Data Group Panels — the stem's intro line over a clickable list of its children, each row selecting that node

Which brand grows which leaf is Controller Brand Matrix; how a leaf panel commits an edit is Controller Editing Contract.

Source Code Path

See HiNC App Anatomy for git repository links.

Web Application

HiNC-2025-webservice (Quasar CLI SPA):

  • wwwroot-src/src/components/controlTree/SoftNcRunnerRootPanel.vue — the branch root's editor: the Object-Management button and its install-then-regrow handler, the brand badge, the runner-file caption, the no-runner block, the presets hint and the no-axes warning.
  • wwwroot-src/src/components/controlTree/softNcItemTypes.ts — the wave's item-type registry and the branch builder: the two plane stems, the leaves every runner grows, the snapshot flag each further leaf is grown behind, and the Siemens relabel of the Tool Offsets leaf.
  • wwwroot-src/src/composables/useSoftNcRunner.ts — the module-singleton snapshot and runner key, the idempotent install of the project-presence watch, and the install and brand-switch calls the two emitting panels use.
  • wwwroot-src/src/api/softNcRunner.ts — the snapshot shape the tree and the panels parse, and the typed wrappers over the controller's REST surface.
  • wwwroot-src/src/components/controlTree/SoftNcEmptyState.vue — the shared “no runner” line the leaf panels render; the root panel renders its own block instead.
  • wwwroot-src/src/components/controlTree/SoftNcBrandPanel.vue — the other panel that regrows the branch: the staged brand select, its confirmation, and the scope it emits.
  • wwwroot-src/src/components/controlTree/useControlTreeHost.ts — builds the equipment/controller root inside the equipment group, and turns a reported structure change into a branch rebuild.
  • wwwroot-src/src/components/controlTree/GroupInfoPanel.vue — the editor both plane stems use.
  • wwwroot-src/src/components/controlTree/itemTypes.ts — the base item-type registry the wave's own registry is spread into, and the mapping of the Group item type to that shared editor.
  • wwwroot-src/src/components/widgets/ObjectManagementMenuButton.vue — the menu: the server file browser and its extension filter, the expected type it sends with a paste, and the events the root panel listens to.
  • wwwroot-src/src/pages/GeneralSetupPage.vue — the route that creates the equipment-scoped tree host this branch is built in.
  • wwwroot-src/src/router/routes.ts — the /general-setup route, and the redirect stub that sends a bookmarked /controller address to this branch root.
  • wwwroot-src/src/i18n/en/softNc.ts — every label, group intro, hint and empty string this branch renders.
  • wwwroot-src/src/i18n/en/tree.ts — the Controller root label.
  • Mech/SoftNcRunnerController.cs — the branch's REST surface: the snapshot the tree shape is built from, the index-and-install pair behind Object Management, the brand switch with its carry and sweep, and the per-group readers and writers the leaves use.
  • Widget/ObjectManagementController.cs — the server half of the menu: the paste that rejects an object the expected-type string does not admit.

HiAPI Engine

  • HiMech/NcParsers/NcRunnerSuit.cs — the suit: the runner, its optional side-file path, the per-case list, the nested serialization of both, and the proxy wiring that materialises a per-case table into a project holding none of that type yet.
  • HiMech/NcParsers/SoftNcRunner.cs — the pipeline and the five brand presets whose entries decide which leaves a brand grows, plus the chain configuration that stamps axis codes onto the axis config.
  • HiMech/NcParsers/Dependencys/CncBrandDependency.cs — the brand marker behind the badge and the five declared tokens.
  • HiMech/NcParsers/Dependencys/ControllerParameterTableBase.cs — the base whose interface list is why the per-axis leaves exist on every brand, and the axis-type rows the axis set is read from.
  • HiMech/NcParsers/Dependencys/Fanuc/FanucParameterTableProxy.cs — the get-or-create proxy pattern the parameter tables use: a serialized seed on the runner, the live table on the project.
  • HiNc/MachiningProcs/LocalProjectService.cs — the facade setter: the hoist of pre-proxy baked tables, the proxy re-binding, the chain-driven axis stamp and the session reset.
  • HiNc/MachiningProcs/MachiningProject.cs — where the suit hangs off the project and the load path that leaves a project with the default preset when its file names no runner.

Pages

Ordered as the branch is read: the two references that hold across every node in it, then the two plane folders whose leaves have editors of their own.

  • Controller Brand Matrix — Which leaf exists on which brand, the snapshot flag behind each one, and what a brand switch keeps, resets or destroys
  • Controller Editing Contract — The rules every leaf panel in the branch follows — when an edit commits, what a failed write does, how a table is rendered — and the panels that depart from them
  • Machine / Controller Plane — The plane that carries the machine and controller settings: the brand switch, the per-axis tables, the parameter forms, the M-code declarations, program reading and the indexing tables
  • Program Data Plane — The plane that carries the per-case tables: the work coordinates, the two tool-offset ledgers, the Heidenhain datum rows, the Siemens frames and the two variable tables

See Also

  • Brand Matrix — which leaf exists on which brand, and the snapshot flag behind each one
  • Editing Contract — the commit, rollback and error rules every leaf panel in this branch follows
  • Machine and Controller Plane — the plane whose leaves carry the machine and controller settings, one page per editor
  • Program Data Plane — the plane whose leaves carry the per-case tables, and the ownership rules that keep them on the project
  • General Setup Page — the page that hosts this branch, and the equipment items beside it
  • Control Tree — the engine that builds, rebuilds and selects this branch
  • Legacy Controller Model (HardNcEnv) — the deprecating HardNcEnv model the project still carries beside this runner, what this branch shares with it, and the three settings that retire with it