lilypond-1.3.12
[lilypond.git] / lily / staff-column.cc
blob55871e0761b46c68c377eee33fb196ebf21e958a
1 /*
2 staff-column.cc -- implement Staff_column
4 source file of the GNU LilyPond music typesetter
6 (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8 #include "proto.hh"
9 #include "plist.hh"
10 #include "staff.hh"
11 #include "voice.hh"
12 #include "time-description.hh"
13 #include "score-column.hh"
14 #include "staff-column.hh"
15 #include "command-request.hh"
16 #include "musical-request.hh"
17 #include "interval.hh"
18 #include "p-score.hh"
19 #include "item.hh"
20 #include "p-col.hh"
21 #include "request-column.hh"
22 #include "grouping.hh"
24 void
25 Staff_column::OK() const
27 #ifndef NDEBUG
29 #endif
32 Moment
33 Staff_column::when() const
35 return req_col_l_->when();
38 void
39 Staff_column::add_reqs(Array<Request*> req_l_arr)
41 for (int i=0; i < req_l_arr.size(); i++) {
42 Request * j = req_l_arr[i];
43 if (j->command()) {
44 Command_req * c_l = j->command();
45 if (c_l->timing()) {
46 timing_req_l_arr_.push(j->command()->timing());
48 if (c_l->groupchange())
49 creationreq_l_arr_.push(c_l);
50 else if (!c_l->barcheck() && !c_l->partial() &&
51 !c_l->measuregrouping())
52 setup_one_request(j);
53 } else {
54 if (j->musical()) {
56 Musical_req*m = j->musical();
57 if (m->rhythmic()) {
58 req_col_l_->musical_column_l_->add_duration(m->rhythmic()->duration());
60 if(m->skip())
61 continue;
63 setup_one_request(j);
68 Staff_column::Staff_column()
70 staff_l_ = 0;
76 Staff_column::~Staff_column()
80 void
81 Staff_column::set_req_col(Request_column *col_l)
83 req_col_l_ = col_l;
86 void
87 Staff_column::setup_one_request(Request * j)
89 if (j->command()) // ugh
90 commandreq_l_arr_.push(j);
91 else if (j->musical())
92 musicalreq_l_arr_.push(j);
95 void
96 Staff_column::typeset_musical_item(Item*i)
98 assert(i);
99 Score_column * scorecolumn_l = req_col_l_->musical_column_l_;
100 scorecolumn_l->pcol_l_->pscore_l_->typeset_item(i, scorecolumn_l->pcol_l_);
104 align items in #item_l_arr#,
106 @return the width of the items after aligning.
108 Interval
109 align_items(Array<Item*> item_l_arr)
111 Interval wid(0,0);
112 for (int i =0; i < item_l_arr.size(); i++) {
113 Interval item_width= item_l_arr[i]->width();
114 if (item_width.empty_b()) {
115 item_width = Interval(0,0);
117 Real dx =wid.right - item_width.left;
118 item_width += dx;
119 item_l_arr[i]->translate(Offset(dx ,0));
120 wid.unite(item_width);
122 return wid;
125 void
126 translate_items(Real x, Array<Item*> item_l_arr)
128 for (int i =0; i < item_l_arr.size(); i++)
129 item_l_arr[i]->translate(Offset(x, 0));
132 TODO:
133 Write a "horizontal align" item, which aligns the pres, nobreaks, posts, etc.
136 void
137 Staff_column::typeset_breakable_items(Array<Item *> &pre_p_arr,
138 Array<Item *> &nobreak_p_arr,
139 Array<Item *> &post_p_arr)
141 Score_column * scol_l= req_col_l_->command_column_l_;
142 PCol * c= scol_l->pcol_l_;
143 PScore *ps_l=scol_l->pcol_l_->pscore_l_;
145 if (!c->breakable_b()) {
146 for (int i =0; i < pre_p_arr.size(); i++) {
147 pre_p_arr[i]->unlink();
148 delete pre_p_arr[i];
150 pre_p_arr.set_size(0);
151 for (int i =0; i < post_p_arr.size(); i++) {
152 post_p_arr[i]->unlink();
153 delete post_p_arr[i];
155 post_p_arr.set_size(0);
159 for (int i =0; i < pre_p_arr.size(); i++) {
160 ps_l->typeset_item(pre_p_arr[i], c,0);
162 for (int i =0; i < nobreak_p_arr.size(); i++) {
163 ps_l->typeset_item(nobreak_p_arr[i], c, 1);
165 for (int i =0; i < post_p_arr.size(); i++) {
166 ps_l->typeset_item(post_p_arr[i], c, 2);
169 Interval pre_wid= align_items(pre_p_arr);
170 translate_items( -pre_wid.right, pre_p_arr);
171 align_items(nobreak_p_arr);
172 Interval post_wid =align_items(post_p_arr);
173 translate_items (-post_wid.left , post_p_arr);
175 pre_p_arr.set_size(0);
176 post_p_arr.set_size(0);
177 nobreak_p_arr.set_size(0);
180 Score_column*
181 Staff_column::command_column_l()
183 return req_col_l_->command_column_l_;
186 Score_column*
187 Staff_column::musical_column_l()
189 return req_col_l_->musical_column_l_;
192 void
193 Staff_column::update_time(Time_description &time_,
194 Rhythmic_grouping *default_grouping)
196 // first all meter changes
197 for (int i=0; i < timing_req_l_arr_.size(); i++) {
198 Timing_req * tr_l = timing_req_l_arr_[i];
199 if (tr_l->meterchange()) {
200 int b_i=tr_l->meterchange()->beats_i_;
201 int o_i = tr_l->meterchange()->one_beat_i_;
202 if (! time_.allow_meter_change_b() )
203 tr_l->warning("Meter change not allowed here");
204 else{
205 time_.set_meter(b_i, o_i);
206 if (default_grouping)
207 *default_grouping =
208 Rhythmic_grouping(MInterval(0,Moment(b_i, o_i)), b_i);
213 // then do the rest
214 for (int i=0; i < timing_req_l_arr_.size(); i++) {
215 Timing_req * tr_l = timing_req_l_arr_[i];
216 if (tr_l->partial()) {
217 Moment m = tr_l->partial()->duration_;
218 String error = time_.try_set_partial_str(m);
219 if (error != "") {
220 tr_l->warning(error);
221 } else
222 time_.setpartial(m);
223 } else if (tr_l->barcheck() && time_.whole_in_measure_) {
224 tr_l ->warning( "Barcheck failed");
226 time_.whole_in_measure_ = 0; // resync
227 time_.error_b_ = true;
228 } else if (tr_l->cadenza()) {
229 time_.set_cadenza(tr_l->cadenza()->on_b_);
230 } else if (tr_l->measuregrouping()) {
231 if (default_grouping)
232 *default_grouping = parse_grouping(
233 tr_l->measuregrouping()->beat_i_arr_,
234 tr_l->measuregrouping()->elt_length_arr_);
237 time_.OK();