Displaying grob ancestry: Difference between revisions
m Replace version="2.24.0" with version="2.24" now that the LilyWiki extension supports auto-selecting the latest release in a stable series |
mNo edit summary |
||
| (3 intermediate revisions by the same user not shown) | |||
| Line 10: | Line 10: | ||
For example, the <code>System</code> grob can be both parent (on the Y-side) and grandparent (twice on the X-side) to a <code>VerticalAlignment</code> grob. | For example, the <code>System</code> grob can be both parent (on the Y-side) and grandparent (twice on the X-side) to a <code>VerticalAlignment</code> grob. | ||
The macro defined in this snippet prints (to the console) a textual representation of a grob's ancestry. For example, the call | |||
{ | |||
\once \override NoteHead.before-line-breaking = #display-ancestry | |||
c | |||
} | |||
generates the following output. | |||
------------------------------------ | |||
X,Y: NoteColumn | |||
NoteHead | |||
X,Y: NoteColumn | |||
X: PaperColumn | |||
X,Y: System | |||
Y: VerticalAxisGroup | |||
X: NonMusicalPaperColumn | |||
X,Y: System | |||
Y: VerticalAlignment | |||
X: NonMusicalPaperColumn | |||
X,Y: System | |||
Y: System | |||
As a consequence, you have to execute the code in this snippet by yourself, since the generated output file doesn't show the data we are interested in. | |||
<lilypond version="2.24"> | <lilypond version="2.24"> | ||
#(define (get-ancestry grob) | #(define (get-ancestry grob) | ||
(if (not (null? (ly:grob-parent grob X))) | |||
(list (grob::name grob) | |||
(get-ancestry (ly:grob-parent grob X)) | |||
(get-ancestry (ly:grob-parent grob Y))) | |||
(grob::name grob))) | |||
#(define (format-ancestry lst padding) | #(define (format-ancestry lst padding) | ||
(string-append | (string-append | ||
(symbol->string (car lst)) | (symbol->string (car lst)) "\n" | ||
(let ((X-ancestry (if (list? (cadr lst)) | |||
(let ((X-ancestry | (format-ancestry (cadr lst) (+ padding 3)) | ||
(symbol->string (cadr lst)))) | |||
(Y-ancestry (if (list? (caddr lst)) | |||
(format-ancestry (caddr lst) (+ padding 3)) | |||
(Y-ancestry | (symbol->string (caddr lst))))) | ||
(if (equal? X-ancestry Y-ancestry) | (if (equal? X-ancestry Y-ancestry) | ||
(string-append | (string-append (format #f "~&") | ||
(make-string padding #\space) | |||
"X,Y: " | |||
(if (list? (cadr lst)) | |||
(format-ancestry (cadr lst) (+ padding 5)) | |||
(symbol->string (cadr lst)))) | |||
(string-append (format #f "~&") | |||
(string-append | (make-string padding #\space) | ||
"X: " X-ancestry "\n" | |||
(make-string padding #\space) | |||
"Y: " Y-ancestry (format #f "~&")))) | |||
(format #f "~&"))) | (format #f "~&"))) | ||
#(define (display-ancestry grob) | #(define (display-ancestry grob) | ||
(format (current- | (format (current-output-port) | ||
"~2&~a~2%~a~&" | |||
(make-string 36 #\-) | |||
(if (ly:grob? grob) | |||
(format-ancestry (get-ancestry grob) 0) | |||
(format #f "~a is not a grob" grob)))) | |||
\relative c' { | \relative c' { | ||
| Line 86: | Line 83: | ||
</lilypond> | </lilypond> | ||
[[Category:Scheme]] | [[Category:Scheme]] | ||
[[Category:Tweaks and overrides]] | [[Category:Tweaks and overrides]] | ||
[[Category:Included in the official documentation]] | [[Category:Included in the official documentation]] | ||
[[Category:Snippet]] | |||
Latest revision as of 10:51, 28 December 2025
When working with grob callbacks, it can be helpful to understand a grob's ancestry. Most grobs have parents which influence the positioning of the grob. X- and Y-parents influence the horizontal and vertical positions for the grob, respectively. Additionally, each parent may have parents of its own.
Unfortunately, there are several aspects of a grob's ancestry that can lead to confusion:
- The types of parents a grob has may depend on context.
- For some grobs, the X- and Y-parents are the same.
- A particular ancestor may be related to a grob in multiple ways.
- The concept of generations is misleading.
For example, the System grob can be both parent (on the Y-side) and grandparent (twice on the X-side) to a VerticalAlignment grob.
The macro defined in this snippet prints (to the console) a textual representation of a grob's ancestry. For example, the call
{
\once \override NoteHead.before-line-breaking = #display-ancestry
c
}
generates the following output.
------------------------------------
NoteHead
X,Y: NoteColumn
X: PaperColumn
X,Y: System
Y: VerticalAxisGroup
X: NonMusicalPaperColumn
X,Y: System
Y: VerticalAlignment
X: NonMusicalPaperColumn
X,Y: System
Y: System
As a consequence, you have to execute the code in this snippet by yourself, since the generated output file doesn't show the data we are interested in.
\version "2.24"
#(define (get-ancestry grob)
(if (not (null? (ly:grob-parent grob X)))
(list (grob::name grob)
(get-ancestry (ly:grob-parent grob X))
(get-ancestry (ly:grob-parent grob Y)))
(grob::name grob)))
#(define (format-ancestry lst padding)
(string-append
(symbol->string (car lst)) "\n"
(let ((X-ancestry (if (list? (cadr lst))
(format-ancestry (cadr lst) (+ padding 3))
(symbol->string (cadr lst))))
(Y-ancestry (if (list? (caddr lst))
(format-ancestry (caddr lst) (+ padding 3))
(symbol->string (caddr lst)))))
(if (equal? X-ancestry Y-ancestry)
(string-append (format #f "~&")
(make-string padding #\space)
"X,Y: "
(if (list? (cadr lst))
(format-ancestry (cadr lst) (+ padding 5))
(symbol->string (cadr lst))))
(string-append (format #f "~&")
(make-string padding #\space)
"X: " X-ancestry "\n"
(make-string padding #\space)
"Y: " Y-ancestry (format #f "~&"))))
(format #f "~&")))
#(define (display-ancestry grob)
(format (current-output-port)
"~2&~a~2%~a~&"
(make-string 36 #\-)
(if (ly:grob? grob)
(format-ancestry (get-ancestry grob) 0)
(format #f "~a is not a grob" grob))))
\relative c' {
\once \override NoteHead.before-line-breaking = #display-ancestry
f4
\once \override Accidental.before-line-breaking = #display-ancestry
\once \override Arpeggio.before-line-breaking = #display-ancestry
<f as c>4\arpeggio
}