This commit is contained in:
2026-09-09 18:06:21 +08:00
parent 161af68fe3
commit 45b9f9ed5d
79 changed files with 1167 additions and 1532 deletions
@@ -205,36 +205,6 @@ carrying no title of its own still reads as its localized display name.</p>
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="the-wpf-clients-list-panel">The WPF Client's List Panel</h2>
<p>The WPF panel edits the <strong>root</strong> list only. It binds the project's player command as a list, its Add
menu offers no List item, and its content switch has no List arm, so a nested list entry selected
there renders the literal text &ldquo;No editor available for ListCommand&rdquo;. Nesting is a web surface.</p>
<ul>
<li>Two columns: a 400px entry column, a <code>GridSplitter</code>, and the selected command's content column,
both columns floored at 300px.</li>
<li>One toolbar over the list — Add, Remove, Move Up, Move Down — acting on the list selection. There
is no duplicate.</li>
<li>Add is a plain button that pops a fixed six-item context menu built in its click handler:
&ldquo;Pre-Setting Command&rdquo;, &ldquo;NC Opt Option Command&rdquo;, &ldquo;NC File Command&rdquo;, &ldquo;NC Code Command&rdquo;,
&ldquo;Script Command&rdquo; and &ldquo;Post Execution Command&rdquo;.</li>
<li>The list box is extended-select. Remove takes every selected entry, prompting with a count when
more than one is selected, and a drag can carry a whole selection; Move Up and Move Down stay
disabled unless exactly one entry is selected.</li>
<li>Each entry box carries a labelled Enable checkbox at its left, the command's title in bold, and a
pin icon with a &ldquo;Pin at beginning&rdquo; / &ldquo;Pin at end&rdquo; label — shown on the first entry when it is a
General Config command, and on the last when it is a Post-Execution command.</li>
<li>Insertion works around the ends: a new entry lands before a trailing Post-Execution when that is
the list's only one, and a General Config lands at the top unless the list already starts with
one. A drag that would move a pinned entry — or drop another entry onto it — is refused, the guard
testing that the entry is the only command of its kind and sits at that end. The Move Up / Move
Down buttons are not covered by that guard.</li>
<li>The content panel is greyed and made read-only while the selected entry's Enable box is clear.</li>
<li>Files dropped from the file explorer onto the entry list create one enabled NC File command per
file, taking a project-relative path when the file sits under the project directory.</li>
<li>The entry label falls back to the raw class name for a command that composes no title of its
own — <code>GeomDiffCommand</code>, <code>OptimizeToFilesCommand</code>, <code>WriteStepFilesCommand</code> and
<code>WriteShotFilesCommand</code>.</li>
</ul>
<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>
@@ -118,9 +118,8 @@ mission row.</li>
<li>NC Code Editor Area
<ul>
<li>The model is <a class="xref" href="../../../api/Hi.SessionCommands.NcCodeCommand.html#Hi_SessionCommands_NcCodeCommand_NcText">NcText</a>.</li>
<li>A plain monospace text area: on the web an 18-row field with a 360 px floor, on WPF a Consolas
text box in an NC Code group box that takes the panel's remaining height.</li>
<li>No line-number gutter and no syntax highlighting on either client. The rich editor in this
<li>A plain monospace text area: an 18-row field with a 360 px floor.</li>
<li>No line-number gutter and no syntax highlighting. The rich editor in this
folder is the <a class="xref" href="script-command-panel.html">Script command</a>'s — that command ships
CodeMirror with a C# grammar, this one ships a text area.</li>
</ul>
@@ -97,9 +97,8 @@ into the project itself.</p>
and an absolute path on the server is accepted just as well. No base directory is stored with the
command: at play time <a class="xref" href="../../../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_RunNcFile_">RunNcFile</a> hands the stored path
together with the project's own base directory to the local project service, and that is where a
relative path acquires its root. The WPF panel's <code>BaseDirectory</code> is the code-behind assistant
property the <a class="xref" href="../../conventions/gui-file-path-assignment.html">Load Pattern</a> asks a file-assigning GUI to carry,
assigned to the panel by its parent — a panel member, not a model member.</p>
relative path acquires its root; the convention behind it is the
<a class="xref" href="../../conventions/gui-file-path-assignment.html">Load Pattern</a>.</p>
<p>The panel renders on the command's own node in the Mission branch of the Execution page's Control
Tree, below the move / duplicate / delete control bar. This command has no title of its own, so the
row and tree label read <code>Program File [path]</code>, the path being the detail the label brackets.</p>
@@ -124,8 +123,7 @@ as CSV, and every other extension as brand NC).</p>
the project folder.</li>
<li>Every keystroke saves the path. Leaving the field or pressing Enter additionally refreshes
the file-info banner.</li>
<li>The web field flexes to fill the row beside the Browse button at any panel width; the WPF
field is a fixed 200 px column carrying its own label.</li>
<li>The field flexes to fill the row beside the Browse button at any panel width.</li>
</ul>
</li>
<li>Browse Button
@@ -140,8 +138,6 @@ field is a fixed 200 px column carrying its own label.</li>
<li>The model is <a class="xref" href="../../../api/Hi.SessionCommands.NcFileCommand.html#Hi_SessionCommands_NcFileCommand_NcKind">NcKind</a>.</li>
<li>Four choices: Auto (by extension), Brand NC, CL (CLSF) and CSV. The hint restates what Auto
detects, so the runner can be pinned when the extension would route the file elsewhere.</li>
<li>This control is the web client's. The WPF panel ships no kind control, so a project edited
there keeps the kind it already holds — Auto until something else sets it.</li>
</ul>
</li>
<li>File Info Banner
@@ -180,9 +176,6 @@ browser to preserve. It is the backstop for a brand extension the NC group does
</ul>
<p>CL and CSV are split out because they are closed extension sets: those are exactly the extensions
Auto routes to the CL and CSV runners, and everything else falls through to brand NC.</p>
<p>The WPF Browse button opens an <code>OpenFileDialog</code> with the panel's file-filter resource, starting at
the project directory or at the current file's own directory. A pick under the project directory is
stored as a relative path, and a pick outside it as an absolute one.</p>
<h2 id="multi-pick-fan-out">Multi-Pick Fan-Out</h2>
<p>The dialog is multi-select, and this is the one command editor that grows the mission. The first
picked file lands on this command. Each further pick becomes a <strong>new</strong> Program File command, added
@@ -191,18 +184,9 @@ list, so a command inside a nested list fans out inside that nested list. The pa
structure change, which rebuilds the owning list's branch around the new rows and leaves the
selection on this command.</p>
<h2 id="where-the-program-text-is-edited">Where the Program Text Is Edited</h2>
<p>The two clients part company here, and the command is the same either way: it stores a path.</p>
<ul>
<li><strong>Web</strong> — the panel does not edit the file. It assigns the path, picks the runner, reports what
the server knows about the file, and previews its first 100 lines read-only. Nothing in the
browser writes NC bytes back; the two file endpoints this panel calls are both reads.</li>
<li><strong>WPF</strong> — the panel opens the file. A non-text file, or one the panel cannot find, disables the
editor and states why in the Head Message Place above it. A text file within 20000 lines opens for
editing, with its line count in the group-box header; a longer one shows its first 20000 lines
read-only and warns in the Head Message Place. Two seconds after the last keystroke the editor
writes the file back, and reports the save in that same message place. The editor is AvalonEdit
with line numbers where that assembly resolves, and a plain Consolas text box otherwise.</li>
</ul>
<p>The command stores a path, and the panel does not edit the file. It assigns the path, picks the
runner, reports what the server knows about the file, and previews its first 100 lines read-only.
Nothing in the browser writes NC bytes back; the two file endpoints this panel calls are both reads.</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>
@@ -94,7 +94,7 @@ preference. <code>Run</code> assigns the command's option object onto the sessio
<code>sessionShell.NcOptOption = NcOptOption</code> — so the settings take effect at the point the entry sits
in the list. Everything played below it optimizes under them, and a second NC Optimization Config
further down the list re-points them mid-mission.</p>
<p>The command carries no title on either client. Its row and its tree label always read
<p>The command carries no title. Its row and its tree label always read
<code>NC Optimization Config</code>: <code>GetCommandTitle</code> returns that fixed name and takes nothing from the user.</p>
<h2 id="where-it-renders">Where It Renders</h2>
<p>The web client has one editor component for this command and mounts it once per tree node, each
@@ -126,7 +126,6 @@ command — a disabled command is skipped during play and stays fully editable.<
<li>Enable Depth Splition CheckBox
<ul>
<li>The model is <a class="xref" href="../../../api/Hi.NcOpt.NcOptOption.html#Hi_NcOpt_NcOptOption_EnableDepthSplition">EnableDepthSplition</a>.</li>
<li>The desktop client labels the same switch &ldquo;Enable Depth Splitting&rdquo;.</li>
</ul>
</li>
<li>Enable Interpolation CheckBox
@@ -327,11 +326,6 @@ feed per tooth or preferred force survives a project save and reload.</p>
</tr>
</tbody>
</table>
<h2 id="the-two-clients">The Two Clients</h2>
<p>The desktop client edits the same command in one scrolling panel of six group boxes, and it names 17
of the model's options — the four enable switches, the two distances, the three feedrates,
acceleration and jerk, Preferred Force with the two spindle safety factors, and the three
compensation switches.</p>
<p>The web client edits five more, and that is the whole difference between the two editors: Min Feed
Per Tooth, Max Feed Per Tooth and Feedrate Assignment Ratio in the Feedrate section, and Yielding
Safety Factor and Thermal Yield Safety Factor in Force &amp; Safety.</p>
@@ -87,8 +87,7 @@
<article data-uid="Anatomy-PostExecutionCommandPanel">
<h1 id="postexecutioncommand-panel-post-execution">PostExecutionCommand Panel (Post-Execution)</h1>
<p>The key model is <a class="xref" href="../../../api/Hi.SessionCommands.PostExecutionCommand.html">PostExecutionCommand</a>, the command both clients label
<strong>Post-Execution</strong>. It is the Output category's first catalog entry, and it carries five outputs
<p>The key model is <a class="xref" href="../../../api/Hi.SessionCommands.PostExecutionCommand.html">PostExecutionCommand</a>, labelled <strong>Post-Execution</strong>. It is the Output category's first catalog entry, and it carries five outputs
derived from what the session has played: step files, shot files, optimization files, a CL → NC
writeback, and a geometry-difference detection.</p>
<h2 id="when-it-runs-and-what-it-covers">When It Runs, and What It Covers</h2>
@@ -103,9 +102,7 @@ command before this command — and it re-serializes every control file the sess
play is written back too. Read this together with
<a class="xref" href="PreSettingCommand-panel.html">General Config</a>, the other half of the pair: those settings
apply from their position forward, these outputs cover everything up to this position.</p>
<p>The web client places the command anywhere in the list, like any other. The WPF client pins it to
the end: a new command is inserted before a trailing Post-Execution while that is the list's only
one, and the drag guard refuses to move it off the last position.</p>
<p>The command sits anywhere in the list, like any other; nothing pins it to the end.</p>
<p><code>Run</code> executes the enabled outputs in an order of its own, which is <strong>not</strong> the order the tree and
the list below show them in: shot files, then step files, then optimization, then the CL → NC
writeback, then the geometry difference. Output timestamps follow that order rather than the layout.</p>
@@ -218,14 +215,6 @@ carries the catalog attribute, so they load from a project file but are not offe
Command dialog. Post-Execution is the catalogued carrier of these outputs, which is why they are
edited as its sections.</p>
</div>
<h2 id="the-wpf-clients-panel">The WPF Client's Panel</h2>
<p>There four of the outputs are group boxes on one panel, each an enable checkbox over a grid that is
disabled until the box is ticked: Step Files Output, Shot Files Output, Optimization Output and
Geometry Difference Detection. The physics condition collapses the Shot Files and Optimization group
boxes rather than omitting tree nodes.</p>
<p>CL → NC Writeback is the one output the web client has and this panel does not. Its two properties
live on the same engine command, and the web section and its two endpoints are where they are
edited.</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>
@@ -251,7 +240,7 @@ overview caption and the writeback paragraph.</li>
<li><code>wwwroot-src/src/stores/appState.ts</code> — the physics preference and licence flags the tree builder
reads.</li>
<li><code>Environments/PreferenceController.cs</code> — serves the physics preference already combined with the
advanced-physics licence, the same condition the WPF panel evaluates.</li>
advanced-physics licence.</li>
<li><code>Missions/MissionController.cs</code> — the <code>commands/{path}/postexecution/*</code> endpoints: the five enable
flags, the four templates, the shot-file time resolution and the geom-diff detect radius.</li>
</ul>
@@ -87,18 +87,12 @@
<article data-uid="Anatomy-PreSettingCommandPanel">
<h1 id="presettingcommand-panel-general-config">PreSettingCommand Panel (General Config)</h1>
<p>The key model is <a class="xref" href="../../../api/Hi.SessionCommands.PreSettingCommand.html">PreSettingCommand</a>, the command both clients label
<strong>General Config</strong>. It is one command carrying a bundle of session settings — the machining
<p>The key model is <a class="xref" href="../../../api/Hi.SessionCommands.PreSettingCommand.html">PreSettingCommand</a>, labelled <strong>General Config</strong>. It is one command carrying a bundle of session settings — the machining
resolution, the machining motion resolution, collision detection, pause on failure, physics — plus
an optional read of a meshed-geometry file.</p>
<h2 id="where-a-general-config-comes-from">Where a General Config Comes From</h2>
<p>The two clients differ on how a mission acquires these settings, and that difference is the first
thing to know about this panel.</p>
<p>The WPF client creates the bundle. Its Add menu carries a hard-coded item that constructs a
<code>PreSettingCommand</code>, and the insert rule pins it to the top of the list: a new General Config lands
at index 0 unless the list already starts with one, and while it is the list's only General Config
the drag guard refuses to move it off that position.</p>
<p>The web client's Add Command dialog is served by the server's command catalog, which reflects every
<p>How a mission acquires these settings is the first thing to know about this panel.</p>
<p>The Add Command dialog is served by the server's command catalog, which reflects every
engine command carrying <code>[CommandCatalog]</code>. <code>PreSettingCommand</code> carries no such attribute, so the
dialog cannot produce one — the catalog keeps <code>presetting</code> only as a readable kind key, and creating
a command looks the kind up in the addable set alone. What the web offers instead is the same
@@ -212,21 +206,6 @@ project is loaded or assigned — not on a runtime reset and not when the workpi
an explicit setting survives both. This command carries its own value, and overwrites the
session's with it at the moment the command runs.</p>
</div>
<h2 id="the-wpf-clients-panel">The WPF Client's Panel</h2>
<p>There the whole bundle is one panel, in two group boxes.</p>
<ul>
<li><strong>Meshed Geometry Settings</strong> — an Enable Read Meshed Geometry checkbox over a Geometry File text
box and a Browse button; the grid beneath the checkbox is disabled until it is ticked. Browse is
an <code>OpenFileDialog</code> filtered to <code>*.wct;*.stl</code>, storing a pick under the project directory as a
relative path and one outside it as an absolute path.</li>
<li><strong>Machining Settings</strong> — the Machining Resolution control is an editable ComboBox pre-filled with
fifteen powers of two, from 0.0009765625 up to 16 in doublings, and a typed value outside that
list is accepted. Beside the Motion Resolution ComboBox a content presenter holds the fixed
fields, built at runtime and labelled Linear Resolution (mm) and Angle Resolution (deg) — Angle
Resolution being this client's wording for the same <code>RotaryResolution_deg</code> the web labels Rotary
Resolution. The three checkboxes sit loose in the same grid, and the Enable Physics one carries no
licence gate.</li>
</ul>
<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>
@@ -108,7 +108,7 @@ fully usable.</p>
<li>Script Title Text Field
<ul>
<li>The model is <a class="xref" href="../../../api/Hi.SessionCommands.ScriptCommand.html#Hi_SessionCommands_ScriptCommand_ScriptTitle">ScriptTitle</a>.</li>
<li>Labelled &ldquo;Title (optional)&rdquo; on the web, &ldquo;Script Title&rdquo; on WPF.</li>
<li>Labelled &quot;Title (optional)&quot;.</li>
</ul>
</li>
<li>Autosave Indicator (web)
@@ -183,11 +183,6 @@ the evaluator uses — and refuses to start when any of them has an error, namin
title, path, diagnostic id, message and line. The SPA's Start sends nothing to bypass that check, so
the refusal is what a user sees. The same check is also an endpoint of its own, per command and for
the whole mission.</p>
<h2 id="the-two-clients">The Two Clients</h2>
<p>The desktop client edits the same command in AvalonEdit: a bold Script Title label with its text
box, a Script Text label, and the editor with C# syntax highlighting and a line-number gutter,
bound to the command through an attached behaviour. There is no completion popup and no autosave —
the binding writes straight into the command as the text changes.</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>