Add the table node, row selection and linked tables, and ship the misc registers as tables #19
@@ -965,9 +965,10 @@ renamed or retyped line is a major.
|
||||
- **The rows of a table are alternatives.** Only one row renders, so a cell in one
|
||||
row and a cell in another never meet, and each may select its own row of another
|
||||
table; the cells of one row, and whatever they reach, do meet, and so does the
|
||||
format beside them. The family fence replays the reads of each row apart,
|
||||
together with the reads outside any row. A choice's items get no such treatment
|
||||
yet: two items selecting different rows are still refused.
|
||||
format beside them. The rule the fence applies is that two reads meet unless
|
||||
they sit in two rows of one table, or in a row outside a selected ancestor's. A
|
||||
choice's items get no such treatment yet: two items selecting different rows
|
||||
are still refused.
|
||||
- **A path is walked once without drawing before it is walked for real.** A path
|
||||
that fails below its first level then moves no seeded stream, at the cost of one
|
||||
draw-free walk per call, which allocates nothing.
|
||||
|
||||
@@ -363,8 +363,7 @@ func (w *drawWalk) walk(n node, at drawAt) {
|
||||
}
|
||||
for _, e := range renderEdges(n) {
|
||||
if cell, isCell := e.to.(*template); isCell && cell.cellOf != nil {
|
||||
// A row already entered renders only its own cell of this column.
|
||||
if r, in := at.alt.rowOf(cell.cellOf); in && r != cell.cellRow {
|
||||
if at.alt.excludes(cell) {
|
||||
continue
|
||||
}
|
||||
w.edge(n, e, drawAt{at.group, at.route, at.alt.enter(cell.cellOf, cell.cellRow)})
|
||||
@@ -374,22 +373,31 @@ func (w *drawWalk) walk(n node, at drawAt) {
|
||||
}
|
||||
}
|
||||
|
||||
// excludes reports whether a cell's row cannot render with the rows entered: another
|
||||
// row of its table, or a row outside an entered ancestor's.
|
||||
func (s rowSet) excludes(cell *template) bool {
|
||||
for _, p := range s {
|
||||
if p.t == cell.cellOf {
|
||||
return p.row != cell.cellRow
|
||||
}
|
||||
if cell.cellOf.descends(p.t) && !cell.cellOf.under(cell.cellRow, p.t, p.row) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// edge records the reference an edge reads, then walks on with every row the read
|
||||
// pins entered, so a selected row renders only its own cells.
|
||||
func (w *drawWalk) edge(from node, e renderEdge, at drawAt) {
|
||||
var tr *tableRead
|
||||
if a, reads := refRead(from, e.label); reads {
|
||||
tr = tableReadOf(from.(*template).fields[a.key], a, e.to)
|
||||
tr := tableReadOf(from.(*template).fields[a.key], a, e.to)
|
||||
if k := (drawKey{at.group, a.path, at.alt.key()}); !w.read[k] {
|
||||
w.read[k] = true
|
||||
w.reads = append(w.reads, pathRead{at, a, tr})
|
||||
}
|
||||
}
|
||||
// A read that pins the column's table renders that row's cell alone.
|
||||
if c, isColumn := e.to.(*column); isColumn && tr != nil {
|
||||
if r, pinned := tr.pins.pinned(c.t); pinned {
|
||||
if cell := c.t.cellNode(r, c.i); cell != nil {
|
||||
w.walk(cell, drawAt{at.group, at.route, at.alt.enter(c.t, r)})
|
||||
}
|
||||
return
|
||||
if tr != nil {
|
||||
tr.pins.each(func(t *table, r int) { at.alt = at.alt.enter(t, r) })
|
||||
}
|
||||
}
|
||||
w.walk(e.to, at)
|
||||
|
||||
@@ -465,6 +465,16 @@ func (t *table) descendant(name string) *table {
|
||||
// parentRow is the row of t's parent that row r links to.
|
||||
func (t *table) parentRow(r int) int { return t.parentT.byKey[t.cell(r, t.parent)] }
|
||||
|
||||
// descends reports whether a is an ancestor of t.
|
||||
func (t *table) descends(a *table) bool {
|
||||
for p := t.parentT; p != nil; p = p.parentT {
|
||||
if p == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// under reports whether row r of t sits inside row pr of ancestor a.
|
||||
func (t *table) under(r int, a *table, pr int) bool {
|
||||
for c, row := t, r; c.parentT != nil; c, row = c.parentT, c.parentRow(row) {
|
||||
|
||||
Reference in New Issue
Block a user