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"
14 #include "dimensions.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "group-interface.hh"
20 Side_position::add_support (Score_element
*me
, Score_element
*e
)
22 Pointer_group_interface (me
, "side-support-elements").add_element (e
);
28 Side_position::get_direction (Score_element
*me
)
30 SCM d
= me
->get_elt_property ("direction");
32 return to_dir (d
) ? to_dir (d
) : DOWN
;
34 Direction relative_dir
= UP
;
35 SCM reldir
= me
->get_elt_property ("side-relative-direction"); // should use a lambda.
38 relative_dir
= to_dir (reldir
);
41 SCM other_elt
= me
->get_elt_property ("direction-source");
42 Score_element
* e
= unsmob_element(other_elt
);
45 return (Direction
)(relative_dir
* Side_position::get_direction (e
));
52 Callback that does the aligning. Puts the element next to the support
56 Side_position::side_position (Score_element
*cme
, Axis axis
)
58 Score_element
* me
= (Score_element
*)cme
;
59 Score_element
*common
= me
->parent_l (axis
);
60 SCM support
= me
->get_elt_property ("side-support-elements");
61 for (SCM s
= support
; s
!= SCM_EOL
; s
= gh_cdr (s
))
63 Score_element
* e
= unsmob_element (gh_car (s
));
65 common
= common
->common_refpoint (e
, axis
);
69 for (SCM s
= support
; s
!= SCM_EOL
; s
= gh_cdr (s
))
72 Score_element
* e
= unsmob_element ( gh_car (s
));
75 Real coord
= e
->relative_coordinate (common
, axis
);
77 dim
.unite (coord
+ e
->extent (axis
));
86 Direction dir
= Side_position::get_direction (me
);
88 Real off
= me
->parent_l (axis
)->relative_coordinate (common
, axis
);
89 SCM minimum
= me
->remove_elt_property ("minimum-space");
91 Real total_off
= dim
[dir
] + off
;
92 SCM padding
= me
->remove_elt_property ("padding");
93 if (gh_number_p (padding
))
95 total_off
+= gh_scm2double (padding
) * dir
;
97 if (gh_number_p (minimum
) && total_off
* dir
< gh_scm2double (minimum
))
99 total_off
= gh_scm2double (minimum
) * dir
;
101 if (fabs (total_off
) > 100 CM
)
102 programming_error ("Huh ? Improbable staff side dim.");
108 callback that centers the element on itself
111 Side_position::aligned_on_self (Score_element
*elm
, Axis ax
)
113 String
s ("self-alignment-");
115 s
+= (ax
== X_AXIS
) ? "X" : "Y";
117 SCM
align (elm
->get_elt_property (s
.ch_C()));
120 Direction d
= to_dir (align
);
121 Interval
ext(elm
->extent (ax
));
125 programming_error ("I'm empty. Can't align on self");
132 return - ext
.center ();
141 directed_round (Real f
, Direction d
)
150 Callback that quantises in staff-spaces, rounding in the direction
151 of the elements "direction" elt property. */
153 Side_position::quantised_position (Score_element
*me
, Axis
)
155 Direction d
= Side_position::get_direction (me
);
157 if (Staff_symbol_referencer::has_interface (me
))
159 Real p
= Staff_symbol_referencer::position_f (me
);
160 Real rp
= directed_round (p
, d
);
169 return (rp
- p
) * Staff_symbol_referencer::staff_space (me
) / 2.0;
175 Position next to support, taking into account my own dimensions and padding.
178 Side_position::aligned_side (Score_element
*me
, Axis ax
)
181 Direction d
= Side_position ::get_direction (me
);
182 Real o
= side_position (me
,ax
);
184 Interval iv
= me
->extent (ax
);
190 SCM pad
= me
->get_elt_property ("padding");
191 if (gh_number_p (pad
))
192 o
+= d
*gh_scm2double (pad
) ;
198 Position centered on parent.
201 Side_position::centered_on_parent (Score_element
* me
, Axis a
)
203 Score_element
*him
= me
->parent_l (a
);
205 return him
->extent (a
).center ();
210 Side_position::add_staff_support (Score_element
*me
)
212 Score_element
* st
= Staff_symbol_referencer::staff_symbol_l (me
);
220 Side_position::set_axis (Score_element
*me
, Axis a
)
222 // prop transparent ?
223 if (me
->get_elt_property ("side-support-elements") == SCM_UNDEFINED
)
224 me
->set_elt_property ("side-support-elements" ,SCM_EOL
);
226 if (!me
->has_offset_callback_b (aligned_side
, a
))
227 me
->add_offset_callback (aligned_side
, a
);
234 Side_position::get_axis (Score_element
*me
)
236 if (me
->has_offset_callback_b (&side_position
, X_AXIS
)
237 || me
->has_offset_callback_b (&aligned_side
, X_AXIS
))
245 Side_position::set_direction (Score_element
*me
, Direction d
)
247 me
->set_elt_property ("direction", gh_int2scm (d
));
251 Side_position::set_minimum_space (Score_element
*me
, Real m
)
253 me
->set_elt_property ("minimum-space", gh_double2scm (m
));
257 Side_position::set_padding (Score_element
*me
, Real p
)
259 me
->set_elt_property ("padding", gh_double2scm (p
));
263 Side_position::has_interface (Score_element
*me
)
265 return me
->get_elt_property ("side-support-elements") != SCM_UNDEFINED
;
269 Side_position::supported_b (Score_element
*me
)
271 SCM s
=me
->get_elt_property ("side-support-elements");
272 return s
!= SCM_UNDEFINED
&& s
!= SCM_EOL
;