2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "paper-column.hh"
22 #include "align-interface.hh"
23 #include "span-bar.hh"
24 #include "axis-group-interface.hh"
25 #include "engraver.hh"
27 #include "pointer-group-interface.hh"
28 #include "grob-array.hh"
30 #include "translator.icc"
32 class Vertical_align_engraver
: public Engraver
35 bool qualifies (Grob_info
) const;
36 SCM id_to_group_hashtab_
;
39 TRANSLATOR_DECLARATIONS (Vertical_align_engraver
);
40 DECLARE_ACKNOWLEDGER (axis_group
);
43 virtual void derived_mark () const;
44 void process_music ();
45 virtual void finalize ();
46 virtual void initialize ();
51 ADD_ACKNOWLEDGER (Vertical_align_engraver
, axis_group
);
52 ADD_TRANSLATOR (Vertical_align_engraver
,
54 "Catch groups (staves, lyrics lines, etc.) and stack them"
68 Vertical_align_engraver::Vertical_align_engraver ()
71 id_to_group_hashtab_
= SCM_EOL
;
76 Vertical_align_engraver::derived_mark () const
78 scm_gc_mark (id_to_group_hashtab_
);
82 Vertical_align_engraver::initialize ()
84 id_to_group_hashtab_
= scm_c_make_hash_table (11);
88 Vertical_align_engraver::process_music ()
92 top_level_
= to_boolean (get_property ("topLevelAlignment"));
94 valign_
= make_spanner (top_level_
? "VerticalAlignment" : "StaffGrouper", SCM_EOL
);
95 valign_
->set_bound (LEFT
, unsmob_grob (get_property ("currentCommandColumn")));
96 Align_interface::set_ordered (valign_
);
101 Vertical_align_engraver::finalize ()
105 valign_
->set_bound (RIGHT
, unsmob_grob (get_property ("currentCommandColumn")));
111 Vertical_align_engraver::qualifies (Grob_info i
) const
113 int sz
= i
.origin_contexts ((Translator
*)this).size ();
115 return sz
> 0 && Axis_group_interface::has_interface (i
.grob ())
116 && !i
.grob ()->get_parent (Y_AXIS
)
117 && !to_boolean (i
.grob ()->get_property ("no-alignment"))
118 && Axis_group_interface::has_axis (i
.grob (), Y_AXIS
);
122 Vertical_align_engraver::acknowledge_axis_group (Grob_info i
)
124 if (top_level_
&& qualifies (i
))
126 string id
= i
.context ()->id_string ();
128 scm_hash_set_x (id_to_group_hashtab_
, ly_string2scm (id
),
129 i
.grob ()->self_scm ());
131 SCM before_id
= i
.context ()->get_property ("alignAboveContext");
132 SCM after_id
= i
.context ()->get_property ("alignBelowContext");
134 SCM before
= scm_hash_ref (id_to_group_hashtab_
, before_id
, SCM_BOOL_F
);
135 SCM after
= scm_hash_ref (id_to_group_hashtab_
, after_id
, SCM_BOOL_F
);
137 Grob
*before_grob
= unsmob_grob (before
);
138 Grob
*after_grob
= unsmob_grob (after
);
140 Align_interface::add_element (valign_
, i
.grob ());
142 if (before_grob
|| after_grob
)
144 Grob_array
*ga
= unsmob_grob_array (valign_
->get_object ("elements"));
145 vector
<Grob
*> &arr
= ga
->array_reference ();
147 Grob
*added
= arr
.back ();
149 for (vsize i
= 0; i
< arr
.size (); i
++)
151 if (arr
[i
] == before_grob
)
153 arr
.insert (arr
.begin () + i
, added
);
154 added
->set_property ("staff-affinity", scm_from_int (DOWN
));
157 else if (arr
[i
] == after_grob
)
159 arr
.insert (arr
.begin () + i
+ 1, added
);
160 added
->set_property ("staff-affinity", scm_from_int (UP
));
166 else if (qualifies (i
) && !unsmob_grob (i
.grob ()->get_object ("staff-grouper")))
168 Pointer_group_interface::add_grob (valign_
, ly_symbol2scm ("elements"), i
.grob ());
169 i
.grob ()->set_object ("staff-grouper", valign_
->self_scm ());