2 align-interface.cc -- implement Align_interface
4 source file of the GNU LilyPond music typesetter
6 (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "align-interface.hh"
11 #include "dimension-cache.hh"
12 #include "score-element.hh"
13 #include "group-interface.hh"
14 #include "axis-group-interface.hh"
17 This callback is set in the children of the align element. It does
18 not compute anything, but a side effect of a->do_side_processing ()
19 is that the elements are placed correctly. */
21 Align_interface::alignment_callback (Dimension_cache const *c)
24 Score_element * sc = c->element_l ()->parent_l (ax);
26 if (sc && sc->get_elt_property ("alignment-done") == SCM_UNDEFINED)
28 Align_interface (sc).do_side_processing (ax);
35 Align_interface::center_on_element (Dimension_cache const *c)
37 Score_element *me = c->element_l ();
38 Score_element *cent = unsmob_element (me->get_elt_property ("group-center-element"));
42 Real r = cent->relative_coordinate (me, c->axis ());
49 Hairy function to put elements where they should be. Can be tweaked
50 from the outside by setting minimum-space and extra-space in its
53 Align_interface::do_side_processing (Axis a)
55 elt_l_->set_elt_property ("alignment-done", SCM_BOOL_T);
57 SCM d = elt_l_->get_elt_property ("stacking-dir");
58 Direction stacking_dir = gh_number_p(d) ? to_dir (d) : CENTER;
65 Link_array<Score_element> elems;
66 Link_array<Score_element> all_elts
67 = Group_interface__extract_elements ( elt_l_, (Score_element*) 0, "elements");
68 for (int i=0; i < all_elts.size(); i++)
70 Interval y = all_elts[i]->extent(a) + all_elts[i]->relative_coordinate (elt_l_, a);
73 Score_element *e =dynamic_cast<Score_element*>(all_elts[i]);
75 // todo: fucks up if item both in Halign & Valign.
76 SCM min_dims = e->remove_elt_property ("minimum-space");
77 if (gh_pair_p (min_dims) &&
78 gh_number_p (gh_car (min_dims))
79 && gh_number_p (gh_cdr (min_dims)))
81 y.unite (Interval (gh_scm2double (gh_car (min_dims)),
82 gh_scm2double (gh_cdr (min_dims))));
85 SCM extra_dims = e->remove_elt_property ("extra-space");
86 if (gh_pair_p (extra_dims) &&
87 gh_number_p (gh_car (extra_dims))
88 && gh_number_p (gh_cdr (extra_dims)))
90 y[LEFT] += gh_scm2double (gh_car (extra_dims));
91 y[RIGHT] += gh_scm2double (gh_cdr (extra_dims));
100 Interval threshold = Interval (0, Interval::infinity ());
101 SCM thr = elt_l_->get_elt_property ("threshold");
104 threshold[SMALLER] = gh_scm2double (gh_car (thr));
105 threshold[BIGGER] = gh_scm2double (gh_cdr (thr));
109 for (int i=0 ; i < elems.size(); i++)
111 Real dy = - stacking_dir * dims[i][-stacking_dir];
113 dy += stacking_dir * dims[i-1][stacking_dir];
117 dy = (dy >? threshold[SMALLER] )
118 <? threshold[BIGGER];
121 where_f += stacking_dir * dy;
122 elems[i]->translate_axis (where_f, a);
128 Align_interface::axis ()const
130 return Axis (gh_scm2int (gh_car (elt_l_->get_elt_property ("axes"))));
135 should use generic Scm funcs.
138 Align_interface::get_count (Score_element*s)const
140 SCM e = elt_l_->get_elt_property ("elements");
142 while (gh_pair_p (e))
144 if (gh_car (e) == s->self_scm_)
153 Align_interface::add_element (Score_element* s)
155 s->add_offset_callback (alignment_callback, axis ());
156 Axis_group_interface (elt_l_).add_element (s);
160 Align_interface::Align_interface (Score_element const*s)
162 elt_l_ = (Score_element*)s;
166 Align_interface::set_interface ()
168 Axis_group_interface (elt_l_).set_interface ();
170 Group_interface (elt_l_, "interfaces").add_thing (ly_symbol2scm ("Alignment"));
174 Align_interface::set_axis (Axis a)
176 Axis_group_interface (elt_l_).set_axes (a,a );
180 Align_interface::has_interface_b ()
182 SCM ifs = elt_l_->get_elt_property ("interfaces");
183 if (!gh_pair_p (ifs))
186 return scm_memq (ly_symbol2scm ("Alignment"), ifs) != SCM_BOOL_F;