Hi all,

On Thu, Mar 13, 2014 at 12:41 PM, David Kastrup <[email protected]> wrote:

>
> You should likely also use interval-index instead of doing your own code
> internally.  It's shorter and much more flexible as it is not restrained
> to LEFT/CENTER/RIGHT.
>

Thanks for pointing this out.  I've incorporated it in the function. So now
no "leveling" takes place: the user can use fractional values (interpreted
in the way they would be with, say, 'self-alignment-X).

I've moved usage information to a comment at the head of the file.

If anyone can come up with a better, more concise example, go for it.  I
remember making the first one with an eye to squeezing as much as I could
into one line.  And of course you wouldn't actually center stems on the
notehead with this command.

Best,
David
\version "2.18.0"

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% A command to horizontally align a grob to another grob.
%%
%% Syntax:
%%
%% [\once] \alignGrob [Context.]Grob-to-align [Context.]Grob-to-align-to
%%                    alignment-direction(s) extra-offset(s)
%%
%% Usage:
%%
%% The argument "alignment-direction(s)" specifies the sides of our
%% grob and the reference grob to align.  If a single number (or LEFT,
%% CENTER, RIGHT) is given, this is used for both objects.  If a pair is
%% given, the first value refers to our grob, and the second to the
%% reference grob.  Standard values are -1 for LEFT, 0 for CENTER, or 1 for
%% RIGHT.  Fractional values are allowed, permitting greater refinement
%% of positioning.
%%
%% The argument extra-offset(s) can be a number or a pair of numbers.  A
%% single number always indicates the vertical displacement of the object
%% from its default position: the single number or the second value of a
%% number-pair.  The first value of a pair (e.g., (dx . dy) ) gives an
%% extra amount to add to the horizontal position.  This allows you to tweak
%% the new alignment.
%%
%% Important: This command uses 'extra-offset, and thus only moves the object
%% in question.  Other objects will not be moved out of the way in the case
%% of a collision.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

alignGrob =
#(define-music-function (parser location grob-to-align reference-grob dir extra-displacement)
                        (symbol-list? symbol-list? number-or-pair? number-or-pair?)
 #{
    \override $grob-to-align . extra-offset =
    #(lambda (grob)
      (let* ((refp (ly:grob-system grob))
             (default-coord (ly:grob-relative-coordinate grob refp X))
             (array (ly:grob-object refp 'all-elements))
             ;; We only want the name of the grob we're aligning to.  If
             ;; input is in the form Context.Grob, strip Context silently.
             (reference-grob
               (if (pair? reference-grob)
                   (car (reverse reference-grob))
                   reference-grob))
             
             (grob-name (lambda (x) (assq-ref (ly:grob-property x 'meta) 'name)))
             ;; all the grobs of the reference type in the current system
             (lst (filter
                    (lambda (x) (eq? reference-grob (grob-name x)))
                    (ly:grob-array->list array)))
             ;; Find the grob with the X-coordinate closest to our grob.
             (ref
               (reduce
                 (lambda (elem prev)
                   (if (< (abs (- default-coord
                                   (ly:grob-relative-coordinate elem refp X)))
                           (abs (- default-coord
                                   (ly:grob-relative-coordinate prev refp X))))
                       elem prev))
                 '()
                 lst)))
        
        (if (ly:grob? ref)
            (let* ((grob-ext (ly:grob-extent grob refp X))
                    (grob-dir (if (pair? dir) (car dir) dir))
                    (grob-ext-idx (interval-index grob-ext grob-dir))
                    (ref-ext (ly:grob-extent ref refp X))
                    ;; If user specified single direction, use it for both objects.
                    (ref-dir (if (pair? dir) (cdr dir) dir))
                    (ref-ext-idx (interval-index ref-ext ref-dir))
                    (extra-X-offset
                      (if (pair? extra-displacement)
                          (car extra-displacement)
                          0.0))
                    (extra-Y-offset
                      (if (pair? extra-displacement)
                          (cdr extra-displacement)
                          extra-displacement)))
              (cons
                (+
                  (- ref-ext-idx grob-ext-idx)
                  extra-X-offset)
                extra-Y-offset))
            
            (cons 0.0 0.0))))
  #}
)

ln = \markup \with-color #red \draw-line #'(0 . 6)
uparrow = \markup \combine \arrow-head #Y #UP ##f \draw-line #'(0 . -2)
downarrow = \markup \combine \arrow-head #Y #DOWN ##f \draw-line #'(0 . 2)

\relative c' {

  %% bar 1
  \time 3/4
  \key d \major
  d
  \alignGrob TextScript KeySignature #CENTER #6
  e-\ln
  \alignGrob TextScript Clef #RIGHT #5.5
  fis-\ln

  %% bar 2
  \time 5/4
  \alignGrob TextScript BarLine #CENTER #-5.5
  e^\ln
  \alignGrob TextScript Hairpin #RIGHT #1
  d(_\ln
  \alignGrob TextScript Slur #CENTER #0
  e_\uparrow
  \alignGrob TextScript StaffSymbol #CENTER #0
  fis^\markup \center-column { "mid-staff" \downarrow  } d)\<

  %% bar 3
  \time 3/4
  \alignGrob TextScript TimeSignature #LEFT #-5
  e^\ln
  \alignGrob TextScript TimeSignature #RIGHT #-5
  fis^\ln d

  %% bar 5
  \alignGrob TextScript Stem #CENTER #-5.5
  e\!^\ln fis
  \alignGrob TextScript Accidental #CENTER #0
  d!_\uparrow

  %% bar 6
  \time 2/4
  \alignGrob Stem NoteHead #CENTER #0
   fis
  \alignGrob Stem NoteHead #CENTER #0
  \alignGrob Script BarLine #CENTER #0.5
  \alignGrob TextScript StaffSymbol #RIGHT #0
  d\fermata _"end"
  \bar "||"
}

thickln = \markup {
  \override #'(thickness . 5) \with-color #red \draw-line #'(0 . 6)
}

\new Staff {
  \relative c' {
    \override Staff.TimeSignature.layer = #2
    \time 3/4
    \alignGrob TextScript TimeSignature #'(1 . -1) #5.5
    s2.-\thickln
    \time 3/4
    \alignGrob TextScript TimeSignature #'(0 . -1) #5.5
    s-\thickln
    \time 3/4
    \alignGrob TextScript TimeSignature #'(-1 . -1) #5.5
    s-\thickln
    \alignGrob TextScript TimeSignature #'(1 . 0) #5.5
    \time 3/4
    s-\thickln
    \alignGrob TextScript TimeSignature #'(0 . 0) #5.5
    \time 3/4
    s-\thickln
    \alignGrob TextScript TimeSignature #'(-1 . 0) #5.5
    \time 3/4
    s-\thickln
    \alignGrob TextScript TimeSignature #'(1 . 1) #5.5
    \time 3/4
    s-\thickln
    \alignGrob TextScript TimeSignature #'(0 . 1) #5.5
    \time 3/4
    s-\thickln
    \alignGrob TextScript TimeSignature #(cons LEFT RIGHT) #5.5
    \time 3/4
    s-\thickln
    
  }
}

\new Staff {
  \override Staff.StaffSymbol.width = 50
  \alignGrob Score.BarLine StaffSymbol #RIGHT #'(0.08 . 0)
  c''4 d e 
  f
  s2.
}
_______________________________________________
lilypond-user mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to