Something went wrong. Try again.
The agentic engineering control plane for the posthuman future
Something went wrong. Try again.
20 kB · 454 lines
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454import QtQuickimport QtQuick.Controlsimport Xenomorphic
// One level of the split tree, laid out with pure bindings over// containerNode (no SplitView, no addItem/removeItem, no diff-sync).//// Geometry derives entirely from model data + parent size:// - axis 0 (row, children side by side): child i sits at the cumulative// width of children 0..i-1, height fills the parent.// - axis 1 (column, stacked): the mirror in y/height.// Every x/y/width/height (panes and divider handles alike) is a binding// whose dependencies are containerNode.children / containerNode.ratios /// containerNode.axis and parent size. A function call inside a binding// re-evaluates whenever those dependencies change.//// Divider handles (n-1 boundaries) sit centered on each boundary, 6px// hit area, and drag writes the whole container's ratios back to// AppModel.setRatios.//// Separate file from SplitTreeDelegate because QML forbids a component// from instantiating itself directly.
Item { id: root
property var containerNode: null property var controller: null property var settings: null property var page: null
// Focus gate forwarded to child TerminalPane wrappers: false when a // host (mission control) renders this tree outside the normal page // focus flow. property bool focusEnabled: true
// True when this container's top-left corner is the tree root's // top-left (the corner where the active tab docks onto the pane // line). Propagates down the index-0 child chain so the leading // leaf can square its top-left border corner. property bool dockedTopLeft: false
// The tab's zoomed pane id ("" = full split tree). Purely a geometry // gate: while set, this container lays out ONLY the child whose // subtree contains the zoomed pane (that child fills the whole // extent; other children collapse), and zoom leaves hide entirely. // No tree/ratio/pool mutation, so clearing restores the exact layout. property string zoomedPaneId: ""
// Whether `paneId` is a leaf anywhere inside `node`'s subtree. A // stack walk over the node's children (each NOTIFIED), so a binding // calling it re-evaluates on structural change. The walk visits // EVERY leaf: a scan that returns at the first leaf visited reports // "not here" for a pane that is merely not the first leaf popped // (the leading leaf of a 2-pane split), which silently disables the // zoom gate and hides nothing. function subtreeContains(node, paneId) { if (!paneId || paneId.length === 0 || !node) return false var stack = [node] while (stack.length > 0) { var n = stack.pop() if (!n) continue if (!n.isContainer) { if (n.paneId === paneId) return true } else { var cs = n.children for (var i = 0; i < cs.length; i++) stack.push(cs[i]) } } return false }
// Whether the zoomed pane lives inside this container's subtree // (pane delegates test their own id instead). Reads the NOTIFIED // sources: zoomedPaneId + children. readonly property bool zoomed: subtreeContains(containerNode, root.zoomedPaneId)
// Index of the child whose subtree holds the zoomed pane (-1 none). function zoomChild() { if (root.zoomedPaneId.length === 0 || !containerNode || !containerNode.children) return -1 var cs = containerNode.children for (var i = 0; i < cs.length; i++) { if (subtreeContains(cs[i], root.zoomedPaneId)) return i } return -1 }
readonly property int zoomIdx: zoomChild()
anchors.fill: parent visible: containerNode !== null
// --- axis + extent helpers ------------------------------------------- property bool row: containerNode ? containerNode.axis === 0 : true // Extent along the split axis / perpendicular to it. property real alongExtent: row ? parent.width : parent.height property real crossExtent: row ? parent.height : parent.width property int childCount: (containerNode && containerNode.children) ? containerNode.children.length : 0
// Whole-pixel cross-axis extent (perpendicular to the split axis). // Floored so each child fills an integer number of pixels; the leftover // sub-pixel remainder just falls off the far edge, keeping every content // boundary on the pixel grid (no fractional widths → no glyph blur). function crossSize() { return Math.floor(root.crossExtent) }
// Measured ratio of child i (>0), else 0 for "unmeasured". function measuredRatio(i) { if (!containerNode || i >= root.childCount) return 0 var r = (containerNode && containerNode.ratios && containerNode.ratios.length > i) ? Number(containerNode.ratios[i]) : -1 return (isFinite(r) && r > 0) ? r : 0 }
// Share used for layout widths: a measured ratio, or an even share // (1/n) when unmeasured. Mirrors the plan's per-child fallback. function coalescedShare(i) { if (root.childCount === 0) return 0 var m = root.measuredRatio(i) return m > 0 ? m : (1.0 / root.childCount) }
// Sum of coalesced shares of children before index i (0 when i===0). function beforeShareSum(i) { var s = 0 for (var k = 0; k < i && k < root.childCount; k++) s += root.coalescedShare(k) return s }
// Pixel position of child i's leading edge along the split axis. // Math.floor keeps boundaries on whole pixels (glyph clarity); the // last child absorbs the rounding remainder by stretching to the far // edge, so the row/column always exactly fills the parent. function alongPos(i) { if (!containerNode || i <= 0) return 0 // Zoom layout: the zoom child starts at the leading edge. if (root.zoomed) return i <= root.zoomIdx ? 0 : Math.floor(root.alongExtent) var x = 0 for (var k = 0; k < i; k++) x += root.alongSize(k) return Math.floor(x) }
// Pixel size of child i along the split axis. Non-last children take // their share; the last child stretches to the far edge. function alongSize(i) { if (!containerNode || root.childCount === 0) return 0 // Zoom layout: exactly one child per level keeps its extent — // the one on the zoom path, filling everything. if (root.zoomed) { return i === root.zoomIdx ? Math.max(0, root.alongExtent) : 0 } if (i === root.childCount - 1) { return Math.max(0, root.alongExtent - root.alongPos(i)) } // Floor EVERY non-last child's extent along the split axis to a // whole pixel so adjacent boundaries land exactly on the pixel grid // (fractional share*extent could overlap neighbors by ~1px and blur // glyphs on fractional parent widths). Positions are floored sums of // these whole sizes (already exact); the last child absorbs the // remainder by stretching to the far edge. return Math.floor(root.coalescedShare(i) * root.alongExtent) }
// Write new ratios for the pair [i, i+1] (others unchanged, preserving // each sibling's measured/unmeasured state) into the model. function applyPairRatios(i, newI, newIp1) { if (!containerNode) return var n = root.childCount var full = [] for (var k = 0; k < n; k++) { if (k === i) { full.push(newI) } else if (k === i + 1) { full.push(newIp1) } else { var r = (containerNode && containerNode.ratios && containerNode.ratios.length > k) ? Number(containerNode.ratios[k]) : -1 // Pass null (invalid QVariant) for unmeasured siblings so // setRatios keeps them unmeasured rather than clamping -1 // to 0.0. full.push(r > 0 ? r : null) } } AppModel.setRatios(containerNode.containerId, full) }
// True when the model's focused pane sits anywhere inside this // container's subtree. Reads focusedPaneId (NOTIFIED) plus the node // children, so every grip re-colors on focus moves. function containerHasFocus() { return subtreeContains(containerNode, AppModel.focusedPaneId) }
// --- children -------------------------------------------------------- Repeater { model: (containerNode && containerNode.children) ? containerNode.children : []
delegate: Item { id: childDelegate required property var modelData required property int index
// Interior gutters: 2px of clear space outside a child's border // on split-axis edges that face a sibling (first/last children // keep their outer edge flush with the container). Borders of // adjacent panes never touch; the 1px divider line stays // centered in the gap because drag geometry still addresses // the un-inset slot boundaries. readonly property int gutter: 2 readonly property bool leadGutter: index > 0 && !root.zoomed readonly property bool trailGutter: index < root.childCount - 1 && !root.zoomed // Zoom layout: the child on the zoom path fills everything, // every other child collapses (0 size, invisible). readonly property bool zoomKept: !root.zoomed || index === root.zoomIdx
x: root.row ? root.alongPos(index) + (leadGutter ? gutter : 0) : 0 y: root.row ? 0 : root.alongPos(index) + (leadGutter ? gutter : 0) width: !zoomKept ? 0 : root.row ? root.alongSize(index) - (leadGutter ? gutter : 0) - (trailGutter ? gutter : 0) : root.crossSize() height: !zoomKept ? 0 : root.row ? root.crossSize() : root.alongSize(index) - (leadGutter ? gutter : 0) - (trailGutter ? gutter : 0) visible: modelData != null && zoomKept
// Container children recurse; pane children render their kind // through leafComponent. Guard container-vs-pane on // modelData.isContainer (a pane has no containerNode property). Loader { id: childLoader anchors.fill: parent source: (modelData && modelData.isContainer) ? "SplitTreeNodeDelegate.qml" : "" sourceComponent: (modelData && !modelData.isContainer) ? leafComponent(modelData) : null
// A leaf renders its own kind: a terminal, an editor or a // chooser. The binding reads the node's NOTIFIED kind, so a // pane that changes kind swaps the component in place. function leafComponent(node) { if (node.isEditor) return editorComponent if (node.isPicker) return pickerComponent return terminalComponent }
onLoaded: { if (item && modelData && modelData.isContainer) { item.containerNode = modelData item.controller = root.controller item.settings = root.settings item.page = root.page } }
// The dock corner passes down the FIRST child's chain only: // a leading child keeps this container's top-left corner. // A live Binding, not an onLoaded write: onLoaded runs // before the caller-side dockedTopLeft binding // (ws.activeTabIndex === 0) re-evaluates on a tab switch, // so a one-shot assignment bakes the STALE value into the // rebuilt child and the docked corner rounds wrong until // the next rebuild. Binding { target: childLoader.item property: "dockedTopLeft" value: root.dockedTopLeft && childDelegate.index === 0 // A leaf loads through a pane component and has no // dockedTopLeft property; applying the binding to it // warns "Property 'dockedTopLeft' does not exist on // TerminalPane" on every pane materialization. Gate on // the delegate's model kind (the loaded container's own // dockedTopLeft existence and isContainer agree). when: childLoader.item !== null && childDelegate.modelData && childDelegate.modelData.isContainer === true } // The zoom id flows into every nested container the same // way dockedTopLeft does (a Binding, not an onLoaded // write: nested delegates materialize lazily as the zoom // path opens/closes). Binding { target: childLoader.item property: "zoomedPaneId" value: root.zoomedPaneId when: childLoader.item !== null && childDelegate.modelData && childDelegate.modelData.isContainer === true } }
Component { id: terminalComponent
TerminalPane { paneId: childDelegate.modelData.paneId controller: root.controller settings: root.settings page: root.page focusEnabled: root.focusEnabled // The pill gate: this pane IS the tab's zoom. zoomed: childDelegate.modelData.paneId === root.zoomedPaneId // A leading leaf of the root's top-left chain squares // its border's top-left corner so the docked tab // merges with the pane line. squareTopLeft: root.dockedTopLeft && index === 0
Component.onCompleted: { start() // On a tab switch every pane re-creates in layout // order; only the model-focused pane may grab focus, // so the last-created pane's auto-focus can't clobber // AppModel.focusedPaneId (restore-on-select). The // focused pane's onActiveFocusChanged → focusPane // broadcast remains the real focus source. if (root.controller && root.controller.focusedPaneId === childDelegate.modelData.paneId) { forceActiveFocus() } } } }
Component { id: editorComponent
EditorPane { paneId: childDelegate.modelData.paneId controller: root.controller settings: root.settings page: root.page focusEnabled: root.focusEnabled zoomed: childDelegate.modelData.paneId === root.zoomedPaneId squareTopLeft: root.dockedTopLeft && index === 0 } }
Component { id: pickerComponent
PickerPane { paneId: childDelegate.modelData.paneId controller: root.controller settings: root.settings page: root.page focusEnabled: root.focusEnabled zoomed: childDelegate.modelData.paneId === root.zoomedPaneId squareTopLeft: root.dockedTopLeft && index === 0 } } } }
// --- divider drag handles (n-1 boundaries) --------------------------- Repeater { // childCount - 1 handles; handle i sits on the boundary after // child i. model: Math.max(0, root.childCount - 1)
delegate: Item { id: divider required property int index
// boundaryIndex: the boundary after child `index` property int boundaryIndex: index property bool dragActive: false property real beforeShare: 0 property real pairShare: 0
x: root.row ? (root.alongPos(boundaryIndex + 1) - 3) : 0 y: root.row ? 0 : (root.alongPos(boundaryIndex + 1) - 3) width: root.row ? 6 : root.crossExtent height: root.row ? root.crossExtent : 6 z: 5 // above the panes so the hit strip takes the cursor
// Zoom layout: dividers are meaningless (one visible // child per level) and must not intercept drags. visible: root.childCount > 1 && !root.zoomed
MouseArea { id: dividerArea anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.LeftButton cursorShape: (dividerArea.containsMouse || dividerArea.pressed) ? (root.row ? Qt.SplitHCursor : Qt.SplitVCursor) : Qt.ArrowCursor
onPressed: { divider.dragActive = true divider.beforeShare = root.beforeShareSum(divider.boundaryIndex) divider.pairShare = root.coalescedShare(divider.boundaryIndex) + root.coalescedShare(divider.boundaryIndex + 1) } onPositionChanged: function(mouse) { if (!divider.dragActive) return var p = divider.mapToItem(root, mouse.x, mouse.y) var along = root.row ? p.x : p.y var extent = root.alongExtent if (extent <= 0) return // Boundary's target share of the whole container. var ratioPos = along / extent // The pair keeps its summed share; each member clamps // to [0.1, 0.9] of that sum. var minShare = divider.pairShare * 0.1 var maxShare = divider.pairShare * 0.9 var newI = Math.min(maxShare, Math.max(minShare, ratioPos - divider.beforeShare)) var newIp1 = divider.pairShare - newI root.applyPairRatios(divider.boundaryIndex, newI, newIp1) } onReleased: divider.dragActive = false }
// Three-dot grip centered on the boundary (perpendicular to the // split axis): the `] | [` full-rule look read as clutter between // the 1px pane borders. 2px dots, 2px gaps, whole-pixel so they // stay crisp. castIron idle; molecularAcid on hover/press and // while the focused pane lives in this container's subtree — // the grip marks the active split group. Rectangle { anchors.centerIn: parent width: root.row ? 2 : 10 height: root.row ? 10 : 2 color: "transparent"
Repeater { model: 3
Rectangle { x: root.row ? 0 : index * 4 y: root.row ? index * 4 : 0 width: 2 height: 2 radius: 1 color: (dividerArea.pressed || dividerArea.containsMouse || root.containerHasFocus()) ? XenoTheme.molecularAcid : XenoTheme.castIron } } } } }}