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"
12 #include "score-element.hh"
13 #include "group-interface.hh"
14 #include "axis-group-interface.hh"
15 #include "paper-def.hh"
18 This callback is set in the children of the align element. It does
19 not compute anything, but a side effect of a->do_side_processing ()
20 is that the elements are placed correctly. */
22 Align_interface::alignment_callback (Score_element *sc, Axis ax)
24 Score_element * par = sc->parent_l (ax);
25 if (par && !to_boolean (par->get_elt_property ("alignment-done")))
27 Align_interface::do_side_processing (par, ax);
34 Align_interface::center_on_element (Score_element *me, Axis a)
36 Score_element *cent = unsmob_element (me->get_elt_property ("group-center-element"));
40 Real r = cent->relative_coordinate (me, a);
47 Hairy function to put elements where they should be. Can be tweaked
48 from the outside by setting minimum-space and extra-space in its
51 Align_interface::do_side_processing (Score_element * me, Axis a)
53 me->set_elt_property ("alignment-done", SCM_BOOL_T);
55 SCM d = me->get_elt_property ("stacking-dir");
56 Direction stacking_dir = gh_number_p(d) ? to_dir (d) : CENTER;
63 Link_array<Score_element> elems;
64 Link_array<Score_element> all_elts
65 = Pointer_group_interface__extract_elements ( me, (Score_element*) 0, "elements");
66 for (int i=0; i < all_elts.size(); i++)
68 Interval y = all_elts[i]->extent(a) + all_elts[i]->relative_coordinate (me, a);
71 Score_element *e =dynamic_cast<Score_element*>(all_elts[i]);
73 // todo: fucks up if item both in Halign & Valign.
74 SCM min_dims = e->remove_elt_property ("minimum-space");
75 if (gh_pair_p (min_dims) &&
76 gh_number_p (gh_car (min_dims))
77 && gh_number_p (gh_cdr (min_dims)))
79 y.unite (Interval (gh_scm2double (gh_car (min_dims)),
80 gh_scm2double (gh_cdr (min_dims))));
83 SCM extra_dims = e->remove_elt_property ("extra-space");
84 if (gh_pair_p (extra_dims) &&
85 gh_number_p (gh_car (extra_dims))
86 && gh_number_p (gh_cdr (extra_dims)))
88 y[LEFT] += gh_scm2double (gh_car (extra_dims));
89 y[RIGHT] += gh_scm2double (gh_cdr (extra_dims));
98 Interval threshold = Interval (0, Interval::infinity ());
99 SCM thr = me->get_elt_property ("threshold");
102 Real ss = me->paper_l ()-> get_var ("staffspace");
103 threshold[SMALLER] = ss *gh_scm2double (gh_car (thr));
104 threshold[BIGGER] = ss * gh_scm2double (gh_cdr (thr));
108 for (int i=0 ; i < elems.size(); i++)
110 Real dy = - stacking_dir * dims[i][-stacking_dir];
112 dy += stacking_dir * dims[i-1][stacking_dir];
116 dy = (dy >? threshold[SMALLER] )
117 <? threshold[BIGGER];
120 where_f += stacking_dir * dy;
121 elems[i]->translate_axis (where_f, a);
127 Align_interface::axis (Score_element*me)
129 return Axis (gh_scm2int (gh_car (me->get_elt_property ("axes"))));
134 should use generic Scm funcs.
137 Align_interface::get_count (Score_element*me,Score_element*s)
139 SCM e = me->get_elt_property ("elements");
141 while (gh_pair_p (e))
143 if (gh_car (e) == s->self_scm ())
152 Align_interface::add_element (Score_element*me,Score_element* s)
154 s->add_offset_callback (alignment_callback, Align_interface::axis (me));
155 Axis_group_interface::add_element (me, s);
160 Align_interface::set_interface (Score_element*me)
162 me->set_interface (ly_symbol2scm ("align-interface"));
164 Axis_group_interface::set_interface (me);
168 Align_interface::set_axis (Score_element*me,Axis a)
170 Axis_group_interface::set_axes (me, a,a );
174 Align_interface::has_interface (Score_element*me)
176 return me && me->has_interface (ly_symbol2scm ("align-interface"));