2 staff-side.cc -- implement Staff_side_element
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include <math.h> // ceil.
11 #include "side-position-interface.hh"
12 #include "staff-symbol.hh"
15 #include "dimensions.hh"
16 #include "dimension-cache.hh"
17 #include "staff-symbol-referencer.hh"
18 #include "group-interface.hh"
20 Side_position_interface::Side_position_interface (Score_element
const *e
)
22 elt_l_
= (Score_element
*)e
;
26 Side_position_interface::add_support (Score_element
*e
)
28 Pointer_group_interface (elt_l_
, "side-support-elements").add_element (e
);
34 Side_position_interface::get_direction () const
36 SCM d
= elt_l_
->get_elt_property ("direction");
38 return to_dir (d
) ? to_dir (d
) : DOWN
;
40 Direction relative_dir
= UP
;
41 SCM reldir
= elt_l_
->get_elt_property ("side-relative-direction"); // should use a lambda.
44 relative_dir
= to_dir (reldir
);
47 SCM other_elt
= elt_l_
->get_elt_pointer ("direction-source");
48 Score_element
* e
= unsmob_element(other_elt
);
51 return (Direction
)(relative_dir
* Side_position_interface (e
).get_direction ());
58 Callback that does the aligning. Puts the element next to the support
62 Side_position_interface::side_position (Score_element
const *cme
, Axis axis
)
64 Score_element
* me
= (Score_element
*)cme
;
65 Score_element
*common
= me
->parent_l (axis
);
66 SCM support
= me
->get_elt_pointer ("side-support-elements");
67 for (SCM s
= support
; s
!= SCM_EOL
; s
= gh_cdr (s
))
69 Score_element
* e
= unsmob_element (gh_car (s
));
71 common
= common
->common_refpoint (e
, axis
);
75 for (SCM s
= support
; s
!= SCM_EOL
; s
= gh_cdr (s
))
78 Score_element
* e
= unsmob_element ( gh_car (s
));
81 Real coord
= e
->relative_coordinate (common
, axis
);
83 dim
.unite (coord
+ e
->extent (axis
));
92 Direction dir
= Side_position_interface (me
).get_direction ();
94 Real off
= me
->parent_l (axis
)->relative_coordinate (common
, axis
);
95 SCM minimum
= me
->remove_elt_property ("minimum-space");
97 Real total_off
= dim
[dir
] + off
;
98 SCM padding
= me
->remove_elt_property ("padding");
99 if (gh_number_p (padding
))
101 total_off
+= gh_scm2double (padding
) * dir
;
103 if (gh_number_p (minimum
) && total_off
* dir
< gh_scm2double (minimum
))
105 total_off
= gh_scm2double (minimum
) * dir
;
107 if (fabs (total_off
) > 100 CM
)
108 programming_error ("Huh ? Improbable staff side dim.");
114 callback that centers the element on itself
117 Side_position_interface::aligned_on_self (Score_element
const*elm
, Axis ax
)
119 String
s ("self-alignment-");
121 s
+= (ax
== X_AXIS
) ? "X" : "Y";
123 SCM
align (elm
->get_elt_property (s
));
126 Direction d
= to_dir (align
);
127 Interval
ext(elm
->extent (ax
));
131 programming_error ("I'm empty. Can't align on self");
138 return - ext
.center ();
147 directed_round (Real f
, Direction d
)
156 Callback that quantises in staff-spaces, rounding in the direction
157 of the elements "direction" elt property. */
159 Side_position_interface::quantised_position (Score_element
const *me
, Axis a
)
161 Side_position_interface
s(me
);
162 Direction d
= s
.get_direction ();
163 Staff_symbol_referencer_interface
si (me
);
165 if (si
.has_interface_b ())
167 Real p
= si
.position_f ();
168 Real rp
= directed_round (p
, d
);
177 return (rp
- p
) * si
.staff_space () / 2.0;
183 Position next to support, taking into account my own dimensions and padding.
186 Side_position_interface::aligned_side (Score_element
const*me
, Axis ax
)
188 Side_position_interface
s(me
);
189 Direction d
= s
.get_direction ();
190 Real o
= side_position (me
,ax
);
192 Interval iv
= me
->extent (ax
);
198 SCM pad
= me
->get_elt_property ("padding");
199 if (gh_number_p (pad
))
200 o
+= d
*gh_scm2double (pad
) ;
206 Position centered on parent.
209 Side_position_interface::centered_on_parent (Score_element
const* me
, Axis a
)
211 Score_element
*him
= me
->parent_l (a
);
213 return him
->extent (a
).center ();
218 Side_position_interface::add_staff_support ()
220 Staff_symbol_referencer_interface
si (elt_l_
);
221 if (si
.staff_symbol_l ())
223 add_support (si
.staff_symbol_l ());
228 Side_position_interface::set_axis (Axis a
)
230 // prop transparent ?
231 if (elt_l_
->get_elt_pointer ("side-support-elements") == SCM_UNDEFINED
)
232 elt_l_
->set_elt_pointer ("side-support-elements" ,SCM_EOL
);
234 if (!elt_l_
->has_offset_callback_b (aligned_side
, a
))
235 elt_l_
->add_offset_callback (aligned_side
, a
);
240 Side_position_interface::set_quantised (Axis a
)
242 elt_l_
->add_offset_callback (quantised_position
, a
);
246 Side_position_interface::get_axis () const
248 if (elt_l_
->has_offset_callback_b (&side_position
, X_AXIS
)
249 || elt_l_
->has_offset_callback_b (&aligned_side
, X_AXIS
))
257 Side_position_interface::set_direction (Direction d
)
259 elt_l_
->set_elt_property ("direction", gh_int2scm (d
));
263 Side_position_interface::set_minimum_space (Real m
)
265 elt_l_
->set_elt_property ("minimum-space", gh_double2scm (m
));
269 Side_position_interface::set_padding (Real p
)
271 elt_l_
->set_elt_property ("padding", gh_double2scm (p
));
275 Side_position_interface::has_interface_b () const
277 return elt_l_
->get_elt_pointer ("side-support-elements") != SCM_UNDEFINED
;
281 Side_position_interface::supported_b () const
283 SCM s
=elt_l_
->get_elt_pointer ("side-support-elements");
284 return s
!= SCM_UNDEFINED
&& s
!= SCM_EOL
;