Files
cumulus/src/model/mod.rs
T
skkeyeandClaude Opus 5.5 13a603837e Tidy a branch and line nodes up (stage 9a)
The first small part of stage 9 (v1.1). <Space>= then m, c or g (the
user's pick: leader menus), or :tidy map|chart|grid, lays out the
cursor's branch while its top node stays put: a mind map puts each node
in the middle of its children (the user's pick), an org chart puts them
side by side below, and a grid makes a block of cards beside the node
(the user's pick), a card's own branch going along as a mind map. Every
node of the branch gets a place, folded away or not (the user's pick),
as one undo step, and the message says when the branch now covers nodes
outside it.

The lines follow the layouts: a parent whose children are all below it
sends its branches down to a shared bend, and a new child of it goes
beside the last one; a grid card behind another isn't joined by a line,
which would look like it joins the two cards.

In visual mode, <Space>a then h, l, k, j or c lines the selection up on
the box around it, each node bringing its branch along, and : opens the
command line on the selection: :align and :tidy take it, and so do
:color, :border, :style, :tag and :fold, as one undo step. The layouts
are pure functions in view::canvas::arrange, applied as one
EditOp::Reposition. Layout and Side moved from the parser to the model
so keys can name them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 10:42:00 -04:00

101 lines
3.6 KiB
Rust

//! The data: documents, nodes, links and how they look. No UI and no files
//! here, just the rules.
//!
//! - A [`Document`] owns a tree of [`Node`]s under one root, loose nodes
//! beside it, and cross-[`Link`]s, and keeps its rules (one root, no
//! cycles, links between nodes that exist).
//! - Every change goes through [`Document::edit`], which returns a
//! [`Change`] that [`History`] can undo and redo.
//! - Text from outside ([`Title`], [`Tag`]…) is checked once, when it's
//! turned into these types.
//! - [`Visible`] works out which nodes folding leaves on show.
mod clip;
mod document;
mod edit;
mod fold;
mod geometry;
mod history;
mod ids;
mod link;
mod look;
mod node;
mod op;
mod portal;
mod text;
pub use clip::{Clip, ClipNode};
pub use document::{Document, NodeRecord, Place, StructureError};
pub use edit::{Change, Edit, EditError, Spot};
pub use fold::Visible;
pub use geometry::{CanvasOffset, CanvasPos, CanvasRect, CanvasSize, Direction, Layout, Side};
pub use history::{Group, History, StateId};
pub use ids::{DocUid, NodeId};
pub use link::{LineRef, Link, LinkKey};
pub use look::{Arrows, Border, LineColor, LineLook, NodeLook, Stroke};
pub use node::{Content, Fold, Idea, Node};
pub use op::{Applied, EditOp, Inbox};
pub use portal::{Backlink, EmptyPath, LinkPath, Portal};
pub use text::{Body, ColorName, Label, StyleName, Tag, Tags, TextError, Title};
/// Small documents and helpers shared by the tests.
#[cfg(test)]
pub(crate) mod test_support {
use super::*;
pub fn title(text: &str) -> Title {
Title::parse(text).expect("a valid title")
}
pub fn idea(text: &str) -> Node {
Node::idea(title(text), CanvasPos::default())
}
/// The ids in [`garden`].
pub struct Garden {
pub root: NodeId,
pub soil: NodeId,
pub beds: NodeId,
pub cedar: NodeId,
pub watering: NodeId,
pub compost: NodeId,
}
/// The document from the design mockup:
///
/// ```text
/// Garden plans ─┬─ Soil
/// ├─ Raised beds ── Cedar
/// └─ Watering
/// ask about compost (loose)
/// ```
pub fn garden() -> (Document, Garden) {
let mut doc = Document::with_uid(title("Garden plans"), DocUid::parse("7f3c9a1e52b04d18").unwrap());
let root = doc.root();
let at = |text: &str, x: i32, y: i32| Node::idea(title(text), CanvasPos::new(x, y));
let (ids, _) = doc
.edit(|e| {
e.update(root, |node| node.pos = CanvasPos::new(0, 4))?;
let soil = e.add(at("Soil", 22, 0), Spot::LastChildOf(root))?;
let beds = e.add(at("Raised beds", 22, 4), Spot::LastChildOf(root))?;
let cedar = e.add(at("Cedar", 40, 4), Spot::LastChildOf(beds))?;
let watering = e.add(at("Watering", 22, 8), Spot::LastChildOf(root))?;
let compost = e.add(at("ask about compost", 0, 14), Spot::Loose)?;
Ok(Garden { root, soil, beds, cedar, watering, compost })
})
.expect("the garden builds");
(doc, ids)
}
/// Adds a portal to a "Kitchen" document under `parent`.
pub fn portal(doc: &mut Document, parent: NodeId) -> NodeId {
let portal = Portal {
path: LinkPath::parse("kitchen.cum").expect("a path"),
uid: DocUid::parse("c01d5e7aa0f3b912").expect("a uid"),
title: title("Kitchen"),
};
let node = Node::portal(portal, CanvasPos::new(22, 12));
doc.edit(|e| e.add(node, Spot::LastChildOf(parent))).expect("the portal goes in").0
}
}