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"
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 (Score_element
*sc
, Axis ax
)
23 Score_element
* par
= sc
->parent_l (ax
);
24 if (par
&& par
->get_elt_property ("alignment-done") == SCM_UNDEFINED
)
26 Align_interface::do_side_processing (par
, ax
);
33 Align_interface::center_on_element (Score_element
*me
, Axis a
)
35 Score_element
*cent
= unsmob_element (me
->get_elt_property ("group-center-element"));
39 Real r
= cent
->relative_coordinate (me
, a
);
46 Hairy function to put elements where they should be. Can be tweaked
47 from the outside by setting minimum-space and extra-space in its
50 Align_interface::do_side_processing (Score_element
* me
, Axis a
)
52 me
->set_elt_property ("alignment-done", SCM_BOOL_T
);
54 SCM d
= me
->get_elt_property ("stacking-dir");
55 Direction stacking_dir
= gh_number_p(d
) ? to_dir (d
) : CENTER
;
62 Link_array
<Score_element
> elems
;
63 Link_array
<Score_element
> all_elts
64 = Pointer_group_interface__extract_elements ( me
, (Score_element
*) 0, "elements");
65 for (int i
=0; i
< all_elts
.size(); i
++)
67 Interval y
= all_elts
[i
]->extent(a
) + all_elts
[i
]->relative_coordinate (me
, a
);
70 Score_element
*e
=dynamic_cast<Score_element
*>(all_elts
[i
]);
72 // todo: fucks up if item both in Halign & Valign.
73 SCM min_dims
= e
->remove_elt_property ("minimum-space");
74 if (gh_pair_p (min_dims
) &&
75 gh_number_p (gh_car (min_dims
))
76 && gh_number_p (gh_cdr (min_dims
)))
78 y
.unite (Interval (gh_scm2double (gh_car (min_dims
)),
79 gh_scm2double (gh_cdr (min_dims
))));
82 SCM extra_dims
= e
->remove_elt_property ("extra-space");
83 if (gh_pair_p (extra_dims
) &&
84 gh_number_p (gh_car (extra_dims
))
85 && gh_number_p (gh_cdr (extra_dims
)))
87 y
[LEFT
] += gh_scm2double (gh_car (extra_dims
));
88 y
[RIGHT
] += gh_scm2double (gh_cdr (extra_dims
));
97 Interval threshold
= Interval (0, Interval::infinity ());
98 SCM thr
= me
->get_elt_property ("threshold");
101 threshold
[SMALLER
] = gh_scm2double (gh_car (thr
));
102 threshold
[BIGGER
] = gh_scm2double (gh_cdr (thr
));
106 for (int i
=0 ; i
< elems
.size(); i
++)
108 Real dy
= - stacking_dir
* dims
[i
][-stacking_dir
];
110 dy
+= stacking_dir
* dims
[i
-1][stacking_dir
];
114 dy
= (dy
>? threshold
[SMALLER
] )
115 <? threshold
[BIGGER
];
118 where_f
+= stacking_dir
* dy
;
119 elems
[i
]->translate_axis (where_f
, a
);
125 Align_interface::axis (Score_element
*me
)
127 return Axis (gh_scm2int (gh_car (me
->get_elt_property ("axes"))));
132 should use generic Scm funcs.
135 Align_interface::get_count (Score_element
*me
,Score_element
*s
)
137 SCM e
= me
->get_elt_property ("elements");
139 while (gh_pair_p (e
))
141 if (gh_car (e
) == s
->self_scm_
)
150 Align_interface::add_element (Score_element
*me
,Score_element
* s
)
152 s
->add_offset_callback (alignment_callback
, Align_interface::axis (me
));
153 Axis_group_interface::add_element (me
, s
);
158 Align_interface::set_interface (Score_element
*me
)
160 me
->set_interface (ly_symbol2scm ("align-interface"));
162 Axis_group_interface::set_interface (me
);
166 Align_interface::set_axis (Score_element
*me
,Axis a
)
168 Axis_group_interface::set_axes (me
, a
,a
);
172 Align_interface::has_interface (Score_element
*me
)
174 return me
&& me
->has_interface (ly_symbol2scm ("align-interface"));