This repository has been archived on 2026-10-11. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
HiNC-2025-win-desktop-Deploy/App/wwwroot/HiAPI-docsite/anatomy/execution/mission/ListCommand-panel.html
T
2026-09-09 18:06:21 +08:00

293 lines
18 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>List Command Panel | HiAPI-C# 2025 </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="List Command Panel | HiAPI-C# 2025 ">
<link rel="icon" href="../../../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../../../public/docfx.min.css">
<link rel="stylesheet" href="../../../public/main.css">
<meta name="docfx:navrel" content="../../../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../../../">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../../index.html">
<img id="logo" class="svg" src="../../../img/HiAPI.logo.png" alt="">
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="Anatomy-ListCommandPanel">
<h1 id="list-command-panel">List Command Panel</h1>
<p>A <a class="xref" href="../../../api/Hi.SessionCommands.ListCommand.html">ListCommand</a> is the container command: an optional title plus a list of
enable-wrapped commands. Running one walks
<a class="xref" href="../../../api/Hi.SessionCommands.ListCommand.html#Hi_SessionCommands_ListCommand_CommandEntryList">CommandEntryList</a> top-down and skips a disabled entry together
with everything nested under it — the wrapper yields nothing while its flag is clear. The mission's
own command is always a list, so the <a class="xref" href="mission-root-panel.html">Mission branch root</a> <em>is</em> a
list, and every nested one is the same shape one level down.</p>
<p><code>List</code> is an ordinary catalog kind — category Flow — so a list is added the way any command is, and
adding one grows a sub-tree: the node's children are its own entries, and its panel embeds the same
entry-list editor the branch root uses, scoped to the nested list.</p>
<p>This page covers what a list is, how its title reads, and what moving commands in and out of one
costs. The entry-list editor itself — Add Command, the row actions, the three drag landings — is
documented once, on <a class="xref" href="mission-root-panel.html">Mission Root Panel</a>.</p>
<h2 id="key-models">Key Models</h2>
<ul>
<li><strong>Primary</strong>: <a class="xref" href="../../../api/Hi.SessionCommands.ListCommand.html">ListCommand</a> — <a class="xref" href="../../../api/Hi.SessionCommands.ListCommand.html#Hi_SessionCommands_ListCommand_Title">Title</a>
and <a class="xref" href="../../../api/Hi.SessionCommands.ListCommand.html#Hi_SessionCommands_ListCommand_CommandEntryList">CommandEntryList</a>.</li>
<li><strong>Supporting</strong>:
<ul>
<li><a class="xref" href="../../../api/Hi.SessionCommands.EnablingWrapper.html">EnablingWrapper</a> — one entry:
<a class="xref" href="../../../api/Hi.SessionCommands.EnablingWrapper.html#Hi_SessionCommands_EnablingWrapper_Command">Command</a> plus
<a class="xref" href="../../../api/Hi.SessionCommands.EnablingWrapper.html#Hi_SessionCommands_EnablingWrapper_IsEnabled">IsEnabled</a>.</li>
<li><a class="xref" href="../../../api/Hi.SessionCommands.ITitleCommand.html">ITitleCommand</a> — <code>ListCommand</code> implements it, and
<a class="xref" href="../../../api/Hi.SessionCommands.ITitleCommand.html#Hi_SessionCommands_ITitleCommand_GetCommandTitle_">GetCommandTitle</a> composes the label a row shows.</li>
<li><a class="xref" href="../../../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_PlayerCommand">PlayerCommand</a> — the mission's command, a list.</li>
<li><a class="xref" href="../../../api/Hi.SessionCommands.CommandCatalogAttribute.html">CommandCatalogAttribute</a> and <a class="xref" href="../../../api/Hi.SessionCommands.CommandCategory.html">CommandCategory</a>
— what makes <code>List</code> addable, and the group it is offered under.</li>
</ul>
</li>
</ul>
<h2 id="the-panel-of-a-list-entry">The Panel of a List Entry</h2>
<p>Selecting a list command in the Control Tree opens, top to bottom:</p>
<ul>
<li>List Entry Panel
<ul>
<li>Control Bar
<ul>
<li>Up / Down / Duplicate / Delete — labelled buttons for the operations that rewrite the
<strong>parent</strong> list. Delete asks for confirmation in a dialog naming the command.</li>
<li>At the bar's left, a caption while the command is disabled: skipped during play, still
editable.</li>
</ul>
</li>
<li>Title (optional) Input</li>
<li>Embedded Entry-List Editor
<ul>
<li>This list's own entries, scoped to the node's path.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>The Title input holds the <strong>raw</strong> title — empty when unset — while the label the row and the tree
show is composed by the engine: <code>List</code> when the title is blank, <code>List [title]</code> when it is not. A
titled list still says what it is. A whitespace-only title counts as unset and is never written into
the project file, so it cannot come back as a changed title on the next load.</p>
<p>Keystrokes debounce into one title save. The pending save is flushed before anything that shifts the
entry paths — a structural operation, a duplicate, a selection change — and cancelled on delete and
on unmount, so a late write cannot land on whichever command slid into the old path. Once it is
saved the tree label refreshes in place rather than by rebuilding the branch, which would remount
the open editor mid-edit.</p>
<p>The root list is the one list without a title input: the branch root reads <code>Mission</code>.</p>
<h2 id="enabling-and-what-a-disabled-list-skips">Enabling, and What a Disabled List Skips</h2>
<p>The enable switch is the checkbox on the command's own Control Tree item, not a control in the entry
row. It decides only whether the command <strong>runs</strong>: while it is clear the row and the tree node dim,
and the editor stays open and fully editable. Unticking a list dims its whole sub-tree — the dim
rides ancestor propagation in the tree while each nested entry keeps its own flag, which is exactly
what the run does: a disabled entry is skipped with everything under it.</p>
<h2 id="paths">Paths</h2>
<p>A command node's key is its Mission API path — <code>&quot;0&quot;</code>, <code>&quot;1&quot;</code>, nested <code>&quot;0.2&quot;</code> for entry 2 inside the
list at index 0. Every structural change re-mints them: deleting entry 2 slides the next command
into path <code>&quot;2&quot;</code>. Each branch build therefore stamps its nodes, so the editor panel remounts onto the
new path instead of going on showing the command that used to live there.</p>
<h2 id="moving-commands-in-and-out">Moving Commands In and Out</h2>
<ul>
<li><strong>Into a list</strong> — drag a row onto the middle band of a list row; that row's outer quarters still
reorder around it.</li>
<li><strong>Out of a list</strong> — drag onto the drop-out zone of a nested list's editor, which is visible only
while a row inside that editor is being dragged. The entry lands right after the list command
itself in the owning list.</li>
</ul>
<p>Both are the same reparent call. The server resolves the source list and the target list to object
references before it mutates either, so the index shift the removal causes cannot misroute the
insert, and it refuses to move a list into itself or into one of its own descendants. That guard
compares identity rather than path-string prefixes, because <code>&quot;02&quot;</code>, <code>&quot;+2&quot;</code> and <code>&quot; 2&quot;</code> all parse to
index 2.</p>
<p>Two more properties of a list follow from the same API:</p>
<ul>
<li><strong>A new command lands at the end</strong> of the list it was added to, root or nested. Nothing is pinned;
the order is entirely the user's, changed with the row's up / down buttons or by dragging.</li>
<li><strong>Duplicate is a deep copy.</strong> The entry is cloned through the same XML round-trip the project file
uses, so a nested list copies with its whole sub-tree, and the clone lands right after the source.</li>
</ul>
<p>Dragging serves rearrangement only: a drag carrying text or files is ignored, because the row's drag
handling returns as soon as the drag did not start on a row. To bring several program files in at
once, open a <a class="xref" href="NcFileCommand-panel.html">Program File</a> command's picker and pick them
together — the first pick lands on that command and each further pick becomes another Program File
command right after it, in pick order, inside the same list at any depth.</p>
<h2 id="which-commands-a-list-can-hold">Which Commands a List Can Hold</h2>
<p>The addable set is the server's command catalog: every engine command carrying <code>[CommandCatalog]</code>,
reflected into the picker Add Command opens, which searches by display label, kind key and alias.
<code>List</code> is one of those commands, which is what makes nesting an ordinary act rather than a special
case. The frontend contributes an icon per kind, and its own label where it has one; the server
supplies the localized label otherwise, so a newly attributed engine command becomes addable with no
frontend change.</p>
<p>A command without that attribute stays loadable from a project file but is never offered for
creation. General Config is the one such command with an editor of its own: it is the legacy
settings bundle, so a project file storing one loads as the individual setting commands it stands
for and saving never writes the bundle back — editable when a project still constructs one through
the API, and absent from the catalog.</p>
<p>Selecting an entry row selects that command's tree node, and the command's editor opens on that
node — the kind's own panel when one exists, otherwise a generic editor built from the scalar fields
the command declares. Selection is one row at a time: there is no multi-selection here, and every
action acts on the row that carries it. Because the server composes every entry label, a command
carrying no title of its own still reads as its localized display name.</p>
<p>There is no second column inside this editor: the entry list is a single column in the tree's editor
pane. The draggable vertical divider on screen belongs to the Execution page, between the left dock
— the Control Tree over the editor panel — and the central area; a second divider inside that dock
drags the height between the tree and the editor.</p>
<h2 id="source-code-path">Source Code Path</h2>
<p>See <a class="xref" href="../../index.html">HiNC App Anatomy</a> for git repository links.</p>
<h3 id="web-application">Web Application</h3>
<ul>
<li><code>wwwroot-src/src/components/controlTree/MissionCommandSlavePanel.vue</code> — a list entry's panel: the
control bar, the optional Title input with its debounce / flush / cancel discipline, the embedded
entry-list editor of a list entry, and the bespoke-or-generic editor choice for every other kind.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionRootPanel.vue</code> — the entry-list editor embedded
here and serving the branch root: the rows and their actions, the three drag landings, and the
drop-out zone shown only during a drag inside a nested editor.</li>
<li><code>wwwroot-src/src/components/controlTree/missionItemTypes.ts</code> — the child builders that recurse
into a list's own entries, the per-kind editor override map, the kind and category icons, and the
per-build stamp that forces the panel remount.</li>
<li><code>wwwroot-src/src/components/controlTree/useControlTreeHost.ts</code> — which nodes show a checkbox, the
dim that flows down a disabled command's sub-tree, the enable write, and the in-place label
refresh after a title edit or a language switch.</li>
<li><code>wwwroot-src/src/api/mission.ts</code> — the typed wrapper over the Mission API and the path convention
(<code>root</code> or empty = the root list, <code>0.2</code> = a nested entry).</li>
<li><code>wwwroot-src/src/components/mission/GenericCommandPanel.vue</code> — the editor a catalog kind gets when
it ships no bespoke panel, built from the command's declared scalar fields.</li>
<li><code>wwwroot-src/src/components/mission/NcFileCommandPanel.vue</code> — the multi-pick file dialog: the
first pick lands on the command, each further pick becomes another Program File command right
after it.</li>
<li><code>wwwroot-src/src/pages/ExecutionPage.vue</code> — the page-level splitter between the left dock and the
central area.</li>
<li><code>wwwroot-src/src/i18n/en/tree.ts</code> — the <code>tree.mission.*</code> strings: the kind names, the drop-out
zone, the run-order hint, the disabled hint and the operation labels.</li>
<li><code>Missions/MissionController.cs</code> — the entry lifecycle: <code>GET list-command/entries</code> (recursive),
<code>POST list-command/entries</code> and <code>POST list-command/entries/{path}</code> (append at the tail of the root
or of a nested list), <code>DELETE list-command/entries/{path}</code>,
<code>POST list-command/entries/{path}/move</code>, <code>PUT list-command/reorder</code>,
<code>POST list-command/entries/{path}/duplicate</code> (the XML-round-trip deep clone),
<code>POST list-command/entries/{path}/reparent</code> (drag-into-list and drop-out, with the self/descendant
guard), <code>PUT commands/{path}/listcommand</code> for the title, and <code>PUT commands/{path}/enabled</code> for an
entry's enable flag. <code>GetCommandTitle</code> composes every entry label the tree shows.</li>
<li><code>Missions/MissionCommandCatalog.cs</code> — reflects the <code>[CommandCatalog]</code> commands into the addable
set and constructs the picked kind.</li>
</ul>
<h3 id="hiapi-engine">HiAPI Engine</h3>
<ul>
<li><code>HiNc/SessionCommands/ListCommand.cs</code> — the container: the optional title, the entry list a run
walks top-down, the whitespace-only-title-is-unset XML rule, the Flow catalog attribute, and the
<code>List</code> / <code>List [title]</code> composition.</li>
<li><code>HiNc/SessionCommands/EnablingWrapper.cs</code> — the enable flag plus the wrapped command that together
make one entry.</li>
<li><code>HiNc/SessionCommands/ITitleCommand.cs</code> — the interface a command implements to compose its own
title from the caller's vocabulary.</li>
<li><code>HiNc/SessionCommands/CommandCatalogAttribute.cs</code> — <code>CommandCategory</code> and the attribute (category,
order, kind key, aliases) that makes the addable set backend-owned.</li>
<li><code>HiNc/SessionCommands/PreSettingCommand.cs</code> — the General Config bundle: no catalog attribute, and
a loaded project expands a stored one into the split setting commands.</li>
<li><code>HiNc/MachiningProcs/MachiningProject.cs</code> — declares the mission's command and keeps it a list.</li>
</ul>
<h2 id="see-also">See Also</h2>
<ul>
<li><a class="xref" href="mission-root-panel.html">Mission Root Panel</a> — the entry-list editor this command embeds, documented once</li>
<li><a href="../../../manual/run/building-a-mission.html">Building a Mission</a> — the task this command serves: grouping a mission and moving entries between groups</li>
<li><a href="index.html">Mission</a> — the rest of the command panels</li>
</ul>
</article>
<div class="contribution d-print-none">
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
</div>
</div>
</footer>
</body>
</html>