Use scalar instead of embedded_scm for context mod overrides.
[lilypond/mpolesky.git] / lily / vertical-align-engraver.cc
blobb90af7471af3d3f21efe31dd0537cbda123bd575
1 /*
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>
7 */
9 #include "context.hh"
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"
15 #include "spanner.hh"
16 #include "pointer-group-interface.hh"
17 #include "grob-array.hh"
19 #include "translator.icc"
21 class Vertical_align_engraver : public Engraver
23 Spanner *valign_;
24 bool qualifies (Grob_info) const;
25 SCM id_to_group_hashtab_;
27 public:
28 TRANSLATOR_DECLARATIONS (Vertical_align_engraver);
29 DECLARE_ACKNOWLEDGER (axis_group);
31 protected:
32 virtual void derived_mark () const;
33 void process_music ();
34 virtual void finalize ();
35 virtual void initialize ();
37 bool top_level_;
40 ADD_ACKNOWLEDGER (Vertical_align_engraver, axis_group);
41 ADD_TRANSLATOR (Vertical_align_engraver,
42 /* doc */
43 "Catch groups (staves, lyrics lines, etc.) and stack them"
44 " vertically.",
46 /* create */
47 "VerticalAlignment ",
49 /* read */
50 "alignAboveContext "
51 "alignBelowContext ",
53 /* write */
57 Vertical_align_engraver::Vertical_align_engraver ()
59 valign_ = 0;
60 id_to_group_hashtab_ = SCM_EOL;
61 top_level_ = false;
64 void
65 Vertical_align_engraver::derived_mark () const
67 scm_gc_mark (id_to_group_hashtab_);
70 void
71 Vertical_align_engraver::initialize ()
73 id_to_group_hashtab_ = scm_c_make_hash_table (11);
76 void
77 Vertical_align_engraver::process_music ()
79 if (!valign_)
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_);
89 void
90 Vertical_align_engraver::finalize ()
92 if (valign_)
94 valign_->set_bound (RIGHT, unsmob_grob (get_property ("currentCommandColumn")));
95 valign_ = 0;
99 bool
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);
110 void
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 ();
137 arr.pop_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));
144 break;
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));
150 break;
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 ());