(Which properties to
[lilypond.git] / lily / note-column.cc
blobd9a8ce307827d59bb63cb9a974abaeef157e6201
1 /*
2 note-column.cc -- implement Note_column
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include <math.h> // ceil
10 #include "axis-group-interface.hh"
11 #include "note-column.hh"
12 #include "stem.hh"
13 #include "warn.hh"
14 #include "paper-def.hh"
15 #include "group-interface.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "rest.hh"
18 #include "note-head.hh"
19 #include "accidental-placement.hh"
22 TODO: figure out if we can prune this class. This is just an
23 annoying layer between (rest)collision & (note-head + stem)
26 bool
27 Note_column::has_rests (Grob*me)
29 return unsmob_grob (me->get_property ("rest"));
32 int
33 Note_column::shift_compare (Grob *const &p1, Grob *const&p2)
35 SCM s1 = p1->get_property ("horizontal-shift");
36 SCM s2 = p2->get_property ("horizontal-shift");
38 int h1 = (gh_number_p (s1))? gh_scm2int (s1) :0;
39 int h2 = (gh_number_p (s2)) ? gh_scm2int (s2):0;
40 return h1 - h2;
43 Item *
44 Note_column::get_stem (Grob*me)
46 SCM s = me->get_property ("stem");
47 return unsmob_item (s);
50 Slice
51 Note_column::head_positions_interval (Grob *me)
53 Slice iv;
55 iv.set_empty ();
57 SCM h = me->get_property ("note-heads");
58 for (; gh_pair_p (h); h = ly_cdr (h))
60 Grob *se = unsmob_grob (ly_car (h));
62 int j = Staff_symbol_referencer::get_rounded_position (se);
63 iv.unite (Slice (j,j));
65 return iv;
68 Direction
69 Note_column::dir (Grob* me)
71 Grob *stem = unsmob_grob (me->get_property ("stem"));
72 if (stem && Stem::has_interface (stem))
73 return Stem::get_direction (stem);
74 else if (gh_pair_p (me->get_property ("note-heads")))
75 return (Direction)sign (head_positions_interval (me).center ());
77 programming_error ("Note column without heads and stem!");
78 return CENTER;
82 void
83 Note_column::set_stem (Grob*me,Grob * stem)
85 me->set_property ("stem", stem->self_scm ());
86 me->add_dependency (stem);
87 Axis_group_interface::add_element (me, stem);
91 Grob*
92 Note_column::get_rest (Grob*me)
94 return unsmob_grob (me->get_property ("rest"));
97 void
98 Note_column::add_head (Grob*me,Grob *h)
100 bool both = false;
101 if (Rest::has_interface (h))
103 if (gh_pair_p (me->get_property ("note-heads")))
104 both = true;
105 else
106 me->set_property ("rest", h->self_scm ());
108 else if (Note_head::has_interface (h))
110 if (unsmob_grob (me->get_property ("rest")))
111 both = true;
112 Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-heads"),h);
115 if (both)
116 me->warning ("Can't have rests and note heads together on a stem.");
117 else
118 Axis_group_interface::add_element (me, h);
122 translate the rest symbols vertically by amount DY, but only if
123 they have no staff-position set.
125 void
126 Note_column::translate_rests (Grob*me, int dy)
128 Grob * r = unsmob_grob (me->get_property ("rest"));
129 if (r && !gh_number_p (r->get_property ("staff-position")))
131 r->translate_axis (dy * Staff_symbol_referencer::staff_space (r)/2.0, Y_AXIS);
136 void
137 Note_column::set_dotcol (Grob*me,Grob *d)
139 Axis_group_interface::add_element (me, d);
145 Grob*
146 Note_column::first_head (Grob*me)
148 Grob * st = get_stem (me);
149 return st? Stem::first_head (st): 0;
154 Return the first Accidentals grob that we find in a note-head.
156 Grob*
157 Note_column::accidentals (Grob *me)
159 SCM heads = me->get_property ("note-heads");
160 Grob * acc = 0;
161 for (;gh_pair_p (heads); heads =gh_cdr (heads))
163 Grob * h = unsmob_grob (gh_car (heads));
164 acc = h ? unsmob_grob (h->get_property ("accidental-grob")) : 0;
165 if (acc)
166 break;
169 if (!acc)
170 return 0;
172 if (Accidental_placement::has_interface (acc->get_parent (X_AXIS)))
173 return acc->get_parent (X_AXIS);
175 /* compatibility. */
176 return acc;
181 ADD_INTERFACE (Note_column,"note-column-interface",
182 "Stem and noteheads combined",
183 "arpeggio note-heads rest-collision rest horizontal-shift stem accidentals force-hshift");