Wäre es richtig, zu sagen, dass Lilyponds Notensatz eine große Tabelle ist, jedes Element also eine Zelle ist? Und manche Elemente auch aus der Zelle hinausragen oder andere Elemente überlappen dürfen?
Ich muß gestehen, daß ich hier nur eingeschränkt Bescheid weiß. Mit den übergeordneten grobs wie #<Grob NonMusicalPaperColumn > #<Grob PaperColumn > #<Grob SystemStartBar > #<Grob SpacingSpanner > #<Grob VerticalAlignment > #<Grob BreakAlignment > beschäftige ich mich nur, wenn ich muß.

Aber es ist sicherlich richtig, daß es eine Hierarchie von Eltern/Kinder-grobs gibt, sowohl in X- als auch in Y-Achse. Manche sind auch "Container-grobs", sammeln und bündeln also andere. Z.B. kommen alle NoteHeads (aber auch andere grobs) in die NoteColumn, um ein simples Beispiel zu bringen.
Alle grobs werden letztlich durch engraver (und deren Zusammenspiel) auf Grundlage des musikalischen inputs (den man sich z.B. mit displayMusic anzeigen lassen kann) erstellt.
Deine Beschreibung erscheint mir erstmal einleuchtend zu sein.
Der Y-Parent von VerticalAxisGroups ist VerticalAlignment
Der X-Parent von VerticalAxisGroups und VerticalAlignment ist jeweils eine NonMusicalPaperColumn
Meine Frage ist: Ist die NonMusicalPaperColumn für beide die selbe? Oder wie muss ich mir das vorstellen?
Lass es uns testen:
\new Staff \with {
\override VerticalAxisGroup.after-line-breaking =
#(lambda (grob)
(let* ((x-par (ly:grob-parent grob X)) ;; -> NonMusicalPaperColumn
(y-par (ly:grob-parent grob Y)) ;; -> VerticalAlignment
(x-par-y-par (ly:grob-parent y-par X))) ;; -> NonMusicalPaperColumn
(format
#t
"\nIs the X-parent of VerticalAxisGroup a NonMusicalPaperColumn?: ~a"
(eq? (grob::name x-par) 'NonMusicalPaperColumn))
(format
#t
"\nIs the X-parent of the Y-parent of VerticalAxisGroup a NonMusicalPaperColumn?: ~a"
(eq? (grob::name x-par-y-par) 'NonMusicalPaperColumn))
(format #t "\nAre the found NonMusicalPaperColumns equal?: ~a"
(equal? x-par x-par-y-par))))
}
{ c'1 }
Also: ja.
Tool aus der Snippet Repository, um sich die Hierarchie von Grobs anzeigen zu lassen:
http://lsr.di.unimi.it/LSR/Item?id=622
Hier noch zwei andere tools:
(1)
Mein eigenes 'look-up-for-parent'
Es geht rekursiv durch den parent-tree um ein bestimmtes grob zu finden, egal an welcher Position im tree es ist. Allerdings nur in der spezifizierten Richtung.
#(define (look-up-for-parent name-symbol axis grob)
"Return the parent of @var{grob}, specified by it's @var{name-symbol} in
axis @var{axis} or @var{grob}, if equal to the grob named @var{name-symbol}
already.
If not found, look up for the next parent."
(let* ((parent (ly:grob-parent grob axis)))
(cond
((not (ly:grob? parent))
(ly:error
(_"Perhaps typing error for \"~a\" or \"~a\" is not in the parent-tree.")
name-symbol name-symbol))
((equal? name-symbol (grob::name grob)) grob)
((not (equal? name-symbol (grob::name parent)))
(look-up-for-parent name-symbol axis parent))
(else parent))))
{
\override NoteHead.after-line-breaking =
#(lambda (grob)
(write (look-up-for-parent 'VerticalAxisGroup Y grob)))
c'1
}
(2)
David Nalesniks 'display-pointers'
Gibt eine Tabelle zurück, die zeigt welche Eltern/Kinder/interfaces angelegt sind.
#(define (grob-interface::info iface)
(hashq-get-handle (ly:all-grob-interfaces) iface))
#(define (grob-interface::properties iface-info)
(if iface-info (cadddr iface-info) '()))
#(define (grob-interface::pointers grob iface)
(let* ((info (grob-interface::info iface))
(props (grob-interface::properties info))
(pointers
(and (pair? props)
(filter
(lambda (prop)
(let ((type (object-property prop 'backend-type?)))
(or (eq? type ly:grob?)
(eq? type ly:grob-array?))))
props))))
(if pointers
(map
(lambda (p) (list p (ly:grob-object grob p)))
pointers))))
#(define (grob::all-pointers grob)
(let ((ifaces (ly:grob-interfaces grob)))
(define (entry iface)
(let ((pointers (grob-interface::pointers grob iface)))
(if (pair? pointers)
(list (list iface pointers))
'())))
(let loop ((ifaces ifaces) (result '()))
(if (null? ifaces)
result
(loop (cdr ifaces)
(append result (entry (car ifaces))))))))
#(define (display-pointers grob)
(format #t "~%~y ~y~%"
(grob::name grob)
(grob::all-pointers grob)))
{
\override NoteHead.after-line-breaking =
#(lambda (grob)
(display-pointers grob))
c'1
}
HTH,
Harm