Mark Polesky wrote: > Otherwise, does this look good?
I'm sorry to keep doing this, but I keep finding ways of improving this. Now I think users should find this very intuitive, although the internal workings are more complex. I've attached the most recent version, which includes an annotated example at the bottom, which explains the behind- the-scenes operations. Anyone want to have a look at it? Anyone have any comments/suggestions? - Mark
\version "2.13.3" %%%%%% begin property-init.ly revision %%%%%% #(define (arpeggio-generic pushpops) (lambda (context) (let* ((parent (ly:context-property-where-defined context 'connectArpeggios)) (target (if (and (not (null? parent)) (eq? #t (ly:context-property parent 'connectArpeggios))) parent context))) (for-each (lambda (pushpop) (if (pair? pushpop) (ly:context-pushpop-property target 'Arpeggio (car pushpop) (cdr pushpop)) (ly:context-pushpop-property target 'Arpeggio pushpop))) pushpops)))) #(define (find-spannable-context context) (let ((spannable-contexts '(GrandStaff PianoStaff StaffGroup))) (if (member (ly:context-name context) spannable-contexts) context (let ((parent (ly:context-parent context))) (if parent (let ((parent-name (ly:context-name parent))) (if (member parent-name spannable-contexts) parent (find-spannable-context parent))) #f))))) #(define (move-arpeggio-generic origin destination) ;; origin and destination are contexts (let* ((Arpeggio (ly:context-grob-definition origin 'Arpeggio)) (X-extent (assoc 'X-extent Arpeggio)) (stencil (assoc 'stencil Arpeggio)) (arpeggio-direction (assoc 'arpeggio-direction Arpeggio)) (direction (assoc 'direction Arpeggio)) (dash-definition (assoc 'dash-definition Arpeggio)) (props `((X-extent . ,X-extent) (stencil . ,stencil) (arpeggio-direction . ,arpeggio-direction) (direction . ,direction) (dash-definition . ,dash-definition)))) (for-each (lambda (prop) ;; copy <origin>.Arpeggio props to <destination>.Arpeggio (if (cdr prop) (ly:context-pushpop-property destination 'Arpeggio (cadr prop) (cddr prop)) (ly:context-pushpop-property destination 'Arpeggio (car prop))) ;; revert <origin>.Arpeggio props (ly:context-pushpop-property origin 'Arpeggio (car prop))) props))) #(define (move-arpeggio-to-spannable-context context) ;; move the active arpeggio properties to the closest GrandStaff, ;; PianoStaff, or StaffGroup parent that can be found. (let ((target (find-spannable-context context))) (if target (move-arpeggio-generic context target)))) #(define (move-arpeggio-to-this-context context) ;; move any arpeggio props, active in a parent context where ;; 'connectArpeggios is #t, to this context (usually Voice). (let ((origin (ly:context-property-where-defined context 'connectArpeggios))) (if (and (not (null? origin)) (eq? #t (ly:context-property origin 'connectArpeggios))) (move-arpeggio-generic origin context)))) #(define (connect-arpeggios-switch value) (lambda (context) (let ((target (find-spannable-context context))) (if target (ly:context-set-property! target 'connectArpeggios value) (ly:warning "No viable context found for connectArpeggios"))))) connectArpeggiosOn = { \applyContext #move-arpeggio-to-spannable-context \applyContext #(connect-arpeggios-switch #t) } connectArpeggiosOff = { \applyContext #move-arpeggio-to-this-context \applyContext #(connect-arpeggios-switch #f) } arpeggioArrowUp = \applyContext #(arpeggio-generic `(stencil X-extent (arpeggio-direction . ,UP))) arpeggioArrowDown = \applyContext #(arpeggio-generic `(stencil X-extent (arpeggio-direction . ,DOWN))) arpeggioNormal = \applyContext #(arpeggio-generic '(stencil X-extent arpeggio-direction dash-definition)) arpeggioBracket = \applyContext #(arpeggio-generic `(X-extent (stencil . ,ly:arpeggio::brew-chord-bracket))) %%%%%% end property-init.ly revision %%%%%% %%%%%% demonstration %%%%%% \new PianoStaff \relative << \new Staff { % current context is Staff. \arpeggioArrowUp looks for #t value for % 'connectArpeggios, doesn't find it anywhere, so it sets arpeggio % props in the current context (Staff). Voice inherits these props. \arpeggioArrowUp <c e g>4\arpeggio % Voice context created implicitly % current context is Voice. % \connectArpeggiosOn finds PianoStaff, sets 'connectArpeggios % there, and moves \arpeggioArrowUp info from Voice to PianoStaff. \connectArpeggiosOn <c e g>4\arpeggio % current context is Voice, but since \arpeggioBracket sees that % 'connectArpeggios is #t in PianoStaff, props are set there instead. \arpeggioBracket <c e g>4\arpeggio % \connectArpeggiosOff finds PianoStaff, sets 'connectArpeggios to % #f there, and moves \arpeggioBracket info from PianoStaff to Voice. \connectArpeggiosOff <c e g>\arpeggio } \new Staff { \clef bass % current context is Staff. \arpeggioArrowDown looks for #t value % for 'connectArpeggios, doesn't find it anywhere, so it sets % arpeggio props in the current context (Staff). Voice inherits these. \arpeggioArrowDown <c, e g>4\arpeggio % cross-staff behavior controlled from other Staff block. <c e g>\arpeggio <c e g>\arpeggio % recent props set in PianoStaff from within the other Staff block % are reverted there with \connectArpeggiosOff, so former Staff % (or Voice) props set in this Staff block (\arpeggioArrowDown in % this case) resume being active. <c e g>\arpeggio } >>
_______________________________________________ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel