73 lines
10 KiB
Markdown
73 lines
10 KiB
Markdown
# Authoritative documents and source-preserving projection
|
|
|
|
This stage replaces whole-document XML serialization with source-range edits and extends the shared Kit projection. Both hosts use the same implementation and live qualification scenarios. It establishes the document/projection foundation; structural authoring and complete target-type discovery are later work.
|
|
|
|
## Source ownership and edits
|
|
|
|
The host Document remains authoritative. A securely parsed DOM identifies elements and compares Kit's projected state, while a lexical index records the original start tags and attribute-value ranges. An accepted canvas edit produces an `EditBatch` containing only changed ranges, with the expected host revision and one named undo transaction. Kit's generated XML never replaces the source document.
|
|
|
|
Unchanged characters stay unchanged: import-only binding types, Model processing instructions, comments, unknown declarations, namespace versions, attribute order, quote style, whitespace, entities and line endings. Attribute values are escaped for their existing quote delimiter. Removing an attribute removes only that attribute; new attributes are inserted into its original start tag. A newly edited attached constraint adds its required layout-class import if absent, without moving existing processing instructions. No-op round trips return the original text exactly.
|
|
|
|
Source edits use a minimal changed range. Shared source selection is mapped through visual ranges, while native IntelliJ editors retain their Document range markers. A source edit queued during an asynchronous visual transaction retains disjoint visual changes; later overlapping source typing wins in its own undo command. Revisions belong to each host adapter and do not assume that IntelliJ modification stamps increase across undo.
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
D[Host Document and revision] --> L[Secure DOM + lexical ranges]
|
|
L --> P[Kit projection with private identities]
|
|
P --> C[Canvas property or layout proposal]
|
|
C --> V[Validate identities and structure]
|
|
V --> E[Attribute-range EditBatch]
|
|
E --> D
|
|
D --> O[Private draft overlay]
|
|
O --> W[Target-runtime rendering]
|
|
```
|
|
|
|
## Broader Component coverage
|
|
|
|
- Explicitly imported and fully qualified Component declarations, multiple instances, and Components nested in standard layout containers.
|
|
- Anonymous Components and standard nodes receive collision-checked projection identities. They are never saved into source. Anonymous Component render identities are added only to the private FXML overlay.
|
|
- `fx:root` bodies project through their declared type, allowing ordinary controls inside a Component's own FXML to be edited while retaining the original `fx:root` declaration.
|
|
- Component internals remain opaque to the parent canvas. Inline content and unknown attributes stay in source; target rendering sees the original declaration. Open Component continues to navigate to its separate source.
|
|
- The shared Component panel shows the real declared class and existing FXML properties. Enter applies an escaped source-range edit; target rendering validates application-specific values. It does not infer application property types from `SnapshotRegion`.
|
|
- Native Kit picking, resize handles and relocation commands operate on proxies. Attribute editing now includes AnchorPane constraints, GridPane spans/growth, HBox/VBox growth, alignment, transforms and existing scalar/layout properties.
|
|
|
|
Kit's built-in hierarchy/inspector still identifies the host placeholder as `SnapshotRegion`; the shared Component panel supplies the actual class/properties. There is no new upstream Kit patch in this stage. A full target-aware hierarchy/typed inspector remains a later integration seam.
|
|
|
|
## Failure and external-edit behavior
|
|
|
|
Source, Design and Split are explicit modes over the same draft. Invalid or unrepresentable source leaves source editing available and disables the retained canvas and Component property panel. Correcting the source restores the projection. Unsupported structural proposals, identifier changes and unsupported property changes are rejected without rewriting the source. Changes of property ownership, such as moving a node from BorderPane.left to right, cannot be silently ignored.
|
|
|
|
Standalone polls clean files through document snapshots, reloads changed contents, advances the revision and clears obsolete local history. IntelliJ refreshes/reloads clean Documents through its native file/document manager. If native autosave already made disk and Document identical, it only advances the disk baseline; it does not reload the same text or invalidate a render revision. Dirty drafts are preserved; saving checks the disk baseline and rejects a conflict. Standalone rechecks immediately before its atomic replacement. There is no cross-process filesystem lock or interactive three-way merge UI; source editing and the retained draft remain available for resolution.
|
|
|
|
The tests reuse independent handles for the same authoritative draft, including native IDE Documents opened through path aliases. Context-specific workflows do not create independent document histories.
|
|
|
|
## Verification
|
|
|
|
Run the full bootstrap and real-IDE checks from [README](../README.md). The same `ProjectionHostChecks` test artifact runs in native standalone windows and the disposable IntelliJ companion, for classpath and module-path applications. The artifact is test-only and excluded from the delivered plugin.
|
|
|
|
The live scenarios cover exact source preservation, nested/fully qualified/anonymous Components, declared-property editing, unaffected source selection, native undo/redo, mode transitions, target NeitzelLib loading, native picking, resize-handle gestures, Kit relocation commands and attached constraints, save/reopen, invalid-source recovery, `fx:root` editing and source typing queued during a visual edit. Existing text-selection and worker-lifetime regressions remain required. Unit/adapter tests cover alternate XML prefixes, CDATA/comments/quoted delimiters, safe rejection of property reparenting, clean external reload, dirty conflicts, stale revisions and native caret/selection preservation.
|
|
|
|
Verified on 2026-11-12: **65 tests** (58 Maven, seven IntelliJ), zero failures/errors/skips, plus the retained 346 target assertions in 24 JVMs, 14 Build and Refresh checks and 64 connected workflow assertions. Both native standalone layouts and both real registered IntelliJ layouts passed the shared projection scenarios. The final unchanged-property/entity-spelling and missing constraint-import regressions passed in the subsequent Maven/IDE builds. Plugin packaging, dependency/bytecode boundaries, test-artifact exclusion and documentation checks pass. Both isolated IDEs loaded exactly one Glass library with the recorded JavaFX 26 artifact hash. Evidence remains under `target/connected-workflow/` and `target/ide-workflow/`. The intentional SDK until-build warning is unchanged.
|
|
|
|
Physical OS drag-and-drop delivery is **not qualified by this automated result**. Synthetic mouse events cannot start JavaFX's native dragboard; a desktop Robot attempt did not result in a document move, including after bringing the test process to the foreground. The suite therefore tests the actual Kit relocation command separately from resize-handle events. The subsequent [human review](manual-input-validation.md) passed physical drag/drop and resizing in both hosts, closing that gate on the recorded baseline.
|
|
|
|
## Corner-resize correction and manual review
|
|
|
|
Human standalone review confirmed independent dragging of both Components, one-click Undo/Redo, save and Source/Design preservation, and separate width/height edge resizing. Corner resizing exposed a dropped height update: Kit emits a separate synchronous job for each dimension, and the first asynchronous host write caused the second notification to be ignored. The shared UI now collects those notifications until the next FX event turn and submits the final geometry as one source-preserving undo transaction. Source edits, document actions and close synchronization flush any queued canvas edit; projection reloads invalidate stale callbacks.
|
|
|
|
The regression checks the selected Component's own width and height (the previous whole-document height check could match its ancestor), the reloaded canvas height, and exact source through one Undo and Redo. It runs through the shared live host scenarios. A small standalone reproducer can also run after the Maven build without Build and Refresh or a target worker:
|
|
|
|
```sh
|
|
python3 scripts/check-corner-resize.py --target-java-home "$TARGET_JAVA_HOME"
|
|
```
|
|
|
|
The focused regression, Maven tests, IntelliJ adapter tests/plugin build, both connected standalone layouts and both registered IntelliJ layouts passed with the correction. One earlier IDE run failed the later save-preservation assertion after the corner checks passed; this did not reproduce on the next complete run. The save assertion now reports expected and actual source for investigation if it recurs.
|
|
|
|
The user subsequently passed the physical corner retest for both Components in both hosts, including one-action Undo/Redo and save/reopen. The [manual input record](manual-input-validation.md) closes this bounded gate; automated gestures remain separate evidence.
|
|
|
|
## Remaining boundaries
|
|
|
|
This stage preserves arbitrary source, but does not make arbitrary structure visually editable. Insert/delete/reparent, binding-aware renames and subtree copy/paste require later structural transactions. Application wildcard imports, `fx:include`, scripts and unrepresentable roots retain source fallback. Arbitrary target properties use declared FXML text editing until shared discovery supplies typed metadata. Anonymous identities are local to a projection revision, not the persistent occurrence identities needed for repeated/Table Components. Target node lookup still uses the initial CSS-ID route; separate CSS IDs and repeated/internal scopes need stage 3's occurrence identity work.
|
|
|
|
Qualification remains scoped to the recorded macOS arm64 / IntelliJ 263.7307.200 / JavaFX and Kit 26 host baseline and Java 21 / JavaFX 21.0.7 application fixtures. Product packaging, a broader platform matrix, lossless structural editing and wider input qualification are not implied. The stage-2 physical input gate is closed on the tested baseline. The following [target-runtime stage](target-runtime-sessions.md) implements retained sessions, sizing and navigation; its new actions have a separate human review.
|