2 vertical-align-engraver.cc -- implement Vertical_align_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
10 #include "paper-column.hh"
11 #include "align-interface.hh"
12 #include "span-bar.hh"
13 #include "axis-group-interface.hh"
14 #include "engraver.hh"
16 #include "pointer-group-interface.hh"
17 #include "grob-array.hh"
19 #include "translator.icc"
21 class Vertical_align_engraver
: public Engraver
24 bool qualifies (Grob_info
) const;
25 SCM id_to_group_hashtab_
;
28 TRANSLATOR_DECLARATIONS (Vertical_align_engraver
);
29 DECLARE_ACKNOWLEDGER (axis_group
);
32 virtual void derived_mark () const;
33 void process_music ();
34 virtual void finalize ();
35 virtual void initialize ();
40 ADD_ACKNOWLEDGER (Vertical_align_engraver
, axis_group
);
41 ADD_TRANSLATOR (Vertical_align_engraver
,
43 "Catch groups (staves, lyrics lines, etc.) and stack them"
57 Vertical_align_engraver::Vertical_align_engraver ()
60 id_to_group_hashtab_
= SCM_EOL
;
65 Vertical_align_engraver::derived_mark () const
67 scm_gc_mark (id_to_group_hashtab_
);
71 Vertical_align_engraver::initialize ()
73 id_to_group_hashtab_
= scm_c_make_hash_table (11);
77 Vertical_align_engraver::process_music ()
81 top_level_
= to_boolean (get_property ("topLevelAlignment"));
83 valign_
= make_spanner (top_level_
? "VerticalAlignment" : "StaffGrouper", SCM_EOL
);
84 valign_
->set_bound (LEFT
, unsmob_grob (get_property ("currentCommandColumn")));
85 Align_interface::set_ordered (valign_
);
90 Vertical_align_engraver::finalize ()
94 valign_
->set_bound (RIGHT
, unsmob_grob (get_property ("currentCommandColumn")));
100 Vertical_align_engraver::qualifies (Grob_info i
) const
102 int sz
= i
.origin_contexts ((Translator
*)this).size ();
104 return sz
> 0 && Axis_group_interface::has_interface (i
.grob ())
105 && !i
.grob ()->get_parent (Y_AXIS
)
106 && !to_boolean (i
.grob ()->get_property ("no-alignment"))
107 && Axis_group_interface::has_axis (i
.grob (), Y_AXIS
);
111 Vertical_align_engraver::acknowledge_axis_group (Grob_info i
)
113 if (top_level_
&& qualifies (i
))
115 string id
= i
.context ()->id_string ();
117 scm_hash_set_x (id_to_group_hashtab_
, ly_string2scm (id
),
118 i
.grob ()->self_scm ());
120 SCM before_id
= i
.context ()->get_property ("alignAboveContext");
121 SCM after_id
= i
.context ()->get_property ("alignBelowContext");
123 SCM before
= scm_hash_ref (id_to_group_hashtab_
, before_id
, SCM_BOOL_F
);
124 SCM after
= scm_hash_ref (id_to_group_hashtab_
, after_id
, SCM_BOOL_F
);
126 Grob
*before_grob
= unsmob_grob (before
);
127 Grob
*after_grob
= unsmob_grob (after
);
129 Align_interface::add_element (valign_
, i
.grob ());
131 if (before_grob
|| after_grob
)
133 Grob_array
*ga
= unsmob_grob_array (valign_
->get_object ("elements"));
134 vector
<Grob
*> &arr
= ga
->array_reference ();
136 Grob
*added
= arr
.back ();
138 for (vsize i
= 0; i
< arr
.size (); i
++)
140 if (arr
[i
] == before_grob
)
142 arr
.insert (arr
.begin () + i
, added
);
143 added
->set_property ("staff-affinity", scm_from_int (DOWN
));
146 else if (arr
[i
] == after_grob
)
148 arr
.insert (arr
.begin () + i
+ 1, added
);
149 added
->set_property ("staff-affinity", scm_from_int (UP
));
155 else if (!top_level_
)
157 Pointer_group_interface::add_grob (valign_
, ly_symbol2scm ("elements"), i
.grob ());
158 i
.grob ()->set_object ("staff-grouper", valign_
->self_scm ());