Table of Contents

Stick Tool Panel

The term stick is for not only milling, but other remover like electric discharge machining tool.

On the shipped web client the Stick Tool Panel is the Control Tree of one tool on the Tool House Page: picking a tool in that page's left list roots the tree at that tool, and the node selected in the tree fills the editor column beside it. The tree's roots are the tool's faces — General, Cutter, Holder, Clamping and Int. Holder — and the tool itself has no row, so the editor's header names the tool in front of the node, as in Tool #3 / Clamping.

The key model is MillingTool.

Layout

  • Control Tree of the picked tool — its roots are the General node followed by the faces the virtual tool container toolhouse/tool-{toolId} grows; the container itself is never drawn as a row
    • General Node (toolhouse/tool-{toolId}/general) — the first root, a leaf
      • Title Bar: Tool #N, with a Duplicate Button and a Delete Button (icon buttons; Delete asks for confirmation first)
      • Tool ID TextField — the T-number; committing it renames the tool, and a number the house already holds is refused and the field snaps back
      • Note TextField (editable)
      • Abstract Note (auto) — read-only, auto-derived, with a one-click copy button
    • Cutter Node (…/cutter)
    • Holder Node (…/holder)
    • Clamping Node (…/clamping) — a leaf
      • Exposed Cutter Height numeric field (mm)
      • Preserved Distance (flute top → spindle nose) numeric field (mm)
      • Formula caption (ExposedCutterHeight = PreservedDistance + FluteHeight)
      • Setup Angle numeric field (deg), with a hint under it
    • Int. Holder Node (…/intelligent) — a leaf, grown only while Show Physics Options is on
      • Observation Location
        • Reference Dropdown (ObservationAnchorReference) — its options are the MillingToolAnchorReference names the server sends with the observation: None, Tool Tip, Holder Anchor, Spindle Mount
        • Z Relative to Reference numeric field (RelativeHeightFromObservationAnchor_mm)
      • Holder Channels — one check box per channel the server offers, Mx / My / Mz (ObservationChannels)

General, Cutter, Holder and Clamping are roots for every tool. Int. Holder is grown only while the shell's Show Physics Options preference is on: its content is the observation point of the Smart Tool Holder that the sensor-moment mapping is computed about. With the preference off, neither the node nor the ring is shown. With it on and the reference not None, the canvases that draw the mounted tool — the Execution Page's and the Equipment Page's — draw a green observation ring at that point, sized from the outline of the tool at that height; the Tool House's own canvas does not draw it. Turning the preference off while Int. Holder is selected re-roots the tree and moves the selection to General.

Cutter and Holder are type-selector nodes: the type chosen decides which section nodes grow below them. The Cutter node grows sections only for a Milling Cutter, and the Holder node grows none for a tool whose holder type is None.

Object Management covers the whole house and the whole cutter, not the single tool: the Object Management Menu Button heads the page's tool list with file extension .MachiningToolHouse (load type Hi.Machining.MachiningToolHouse, HiMech), the Cutter node's panel carries another for the tool's cutter (.Cutter), and the General node offers Duplicate and Delete for the single tool. There is no per-tool object-management button; the identity fields — Tool ID, Note and the Abstract Note — sit on the General node beside those two buttons.

One Tool, Not the House

The tree holds one tool, never the whole house, and that is a constraint of the server rather than a layout choice. The holder index keys are per session, not per tool ({sessionKey}-HolderGeom, {sessionKey}-HolderCylindroid, re-pointed on every read), so two tools' holder branches built at once would both address the tool built last. The tools are therefore rows of the page's list rather than rows of the tree — the Tool House root grows no children — and the host points the session and the tool canvas at the picked tool (ensureToolSelected) before it builds that tool's faces. Each per-tool panel in wwwroot-src/src/components/controlTree/toolhouse/ repeats the call when it mounts.

Nodes and the URL

Every node id is a role path under toolhouse/tool-{toolId}, and the page's URL spells it as /tool-house/<toolId>/<node path>: the tool number, then the selected node's id with its toolhouse/tool-{toolId} prefix removed. The Clamping node of tool 3 is /tool-house/3/clamping, and a node five levels down rides the URL whole, as in /tool-house/3/cutter/contours/fluting/flute-0/side. toolNodePathOf and toolTreeId in wwwroot-src/src/router/treeRoutes.ts convert between the id and the URL's two halves, and routeForTreeId turns any Tool House id into this route without dropping a segment.

  • The URL is the authority. A tool number with no node path, /tool-house/3, selects General. A node path the tool does not grow is clamped to the deepest node along it that the tool does grow — or to General when not even its first segment is a root, as with intelligent while Show Physics Options is off — and the URL is rewritten to the node actually selected. A tool number the house does not hold lands on the house's first tool.
  • A bare /tool-house lands on remembered state. The menu bar's Tool House switch links there, carrying no selection, so the page keeps the tool already shown — or, on a fresh load, takes the house's first tool — and opens the last node path selected on this page, which the browser keeps with the page's last selection (lastTreeIds in wwwroot-src/src/composables/useViewPrefs.ts). An explicit URL always wins over that memory.
  • Picking another tool keeps the face. Each list row is a router link that rewrites only the tool number. The link carries the deepest node path asked for rather than the URL's clipped one, so a face one tool does not grow (flute 3 of a two-flute cutter) comes back on the next tool that grows it. A re-root adopts its selection only while the URL still names the tool it built, so two quick clicks in the list settle on the second tool.
  • House changes go through the URL. Committing a new Tool ID, duplicating a tool, or adding one with New Tool moves the URL to that tool's number, keeping the node path; deleting a tool re-roots the tree at the house's first tool, and an Object Management load rebuilds the tree in place. This is the toolhouse branch of the host's onNodeStructureChanged.
  • No ?tree=. The Tool House page never reads or writes the ?tree= query. That query belongs to the Execution and Equipment pages, and a Tool House id arriving on either of them is redirected here by routeForTreeId.
Note

The Exposed Cutter Height and Preserved Distance are directly related: ExposedCutterHeight = PreservedDistance + FluteHeight, so each value changes when the other is changed. Editing Preserved Distance commits PUT /api/ToolHouse/{id}/preserved-distance, whose response carries the recomputed pair and fills both fields; editing Exposed Cutter Height commits PUT /api/ToolHouse/{id}/exposed-height, which answers without a body, so the panel re-reads the tool to pick up the new preserved distance.

Setup Angle is a third field on the same node, coupled to neither of those two: it is how far the cutter is turned in the holder about the tool axis, and it commits on its own to PUT /api/ToolHouse/{id}/setup-angle, whose body is a bare JSON number. Only the milling physics reads it — the tool assembly and the canvas are not turned by it.

While the pace player is locked — a run in progress or paused — all three commits are refused with 409 ToolEditRefusedWhileRunning, as is every other tool-house edit; the page says so in a banner with Stop and Reset, and the fields read as before.

Source Code Path

See HiNC App Anatomy for git repository links.

HiNC-2025-webservice (Quasar CLI SPA). The tool's faces are nodes of the shared Control Tree, rendered by the same ControlTreePanel and PrimarySlavePanel pair as the Execution and Equipment pages:

  • wwwroot-src/src/components/controlTree/toolHouseItemTypes.ts — the Tool House ItemType registry: toolContainerNode mints the virtual toolhouse/tool-{toolId} container (a ToolNode with no panel), whose buildToolChildren grows the Cutter, Holder and Clamping faces and, while Show Physics Options is on, Int. Holder; toolGeneralNode mints the General leaf, whose ToolGeneral item type carries ToolNodePanel. ToolHouseRoot has no buildChildren.
  • wwwroot-src/src/components/controlTree/useControlTreeHost.ts — the toolhouse scope: buildToolHouseRoots builds the picked tool's container and lifts its children to the roots behind General, deepestBuiltId clamps a node path to what the tool grows, toolLocation builds the list rows' links, and the toolhouse branch of onNodeStructureChanged sends a tool switch through the URL and re-seats the tree in place otherwise.
  • wwwroot-src/src/router/treeRoutes.ts — toolNodePathOf / toolTreeId, the tree id ↔ URL halves, and routeForTreeId.
  • wwwroot-src/src/router/routes.ts — the route tool-house/:toolId(\d+)?/:node(.*)*.
  • wwwroot-src/src/pages/ToolHousePage.vue — renders the tree column (ControlTreePanel) and the editor column (PrimarySlavePanel) over useControlTreeHost('toolhouse'), between the tool list and the tool canvas.
  • wwwroot-src/src/components/controlTree/toolhouse/ToolNodePanel.vue — the General node: Tool ID / Note / read-only auto Abstract Note with copy, plus Duplicate and Delete.
  • wwwroot-src/src/components/controlTree/toolhouse/ToolCutterPanel.vue — the Cutter node's type selector (Milling Cutter / Freeform Remover / None) plus a milling cutter's own fields.
  • wwwroot-src/src/components/controlTree/toolhouse/ToolHolderPanel.vue — the Holder node's type selector (None / Cylindroid / Freeform) plus the holder's Name / Note / auto Abstract Note.
  • wwwroot-src/src/components/controlTree/toolhouse/ToolClampingPanel.vue — the Clamping node and its two coupled fields, plus the independent Setup Angle.
  • wwwroot-src/src/components/controlTree/toolhouse/ToolIntelligentPanel.vue — the Int. Holder node; a thin wrapper over wwwroot-src/src/components/toolhouse/IntelligentHolderDiv.vue, which holds the Observation Location controls.
  • wwwroot-src/src/composables/useToolHouse.ts — the module-singleton state every tool-house panel is a thin view over: the tool list, the active tool, and the rendering connection id; ensureToolSelected points the session and the canvas at one tool.
  • Mech/ToolHouseController.cs — [Route("api/[controller]")], so /api/ToolHouse: the tool-level fields the General, Clamping and Int. Holder nodes edit — PUT /{id}/note | exposed-height | preserved-distance | setup-angle, GET/PUT /{id}/observation, POST DuplicateTool | RenameTool, DELETE DeleteTool — plus the Holder node's POST SetHolderType and the tool list's POST CreateTool. Every one of them answers 409 ToolEditRefusedWhileRunning while the pace player is locked (a run in progress or paused); POST Initialize and POST SelectTool, which only index, do not.
  • Mech/CutterController.cs (/api/Cutter), Mech/CylindroidHolderController.cs (/api/CylindroidHolder) and Mech/FreeformHolderController.cs (/api/FreeformHolder) — the server surface behind the Cutter and Holder nodes; the two holder controllers mint the per-session holder index keys. All three are read-only while the pace player is locked, the same 409; the cutter's POST /{id}/inner-beam and POST /{id}/upper-beam, the holder controllers' POST Get and the freeform holder's POST IndexCurrentGeometry — the reads that only index — stay available.
  • wwwroot-src/src/api/toolHouse.ts — the typed client for /api/ToolHouse and /api/Cutter; wwwroot-src/src/api/cylindroidHolder.ts and wwwroot-src/src/api/freeformHolder.ts are the two holder controllers' clients.

See Also

  • Tool House Page — the page this tree sits in: its tool list, its four columns and its route
  • Cutter Branch — the section nodes the Cutter node grows
  • Holder Branch — the section nodes the Holder node grows
  • Control Tree — the shared tree host whose toolhouse scope builds these roots