*** empty log message ***
[lilypond.git] / lily / multi-measure-rest-engraver.cc
blob252036beab2737ffd3d8be8eb19e9639589c202e
1 /*
2 multi_measure_rest-engraver.cc -- implement Multi_measure_rest_engraver
4 (c) 1998--2003 Jan Nieuwenhuizen <janneke@gnu.org>
5 Han-Wen Nienhuys <hanwen@cs.uu.nl>
6 */
8 #include "event.hh"
9 #include "multi-measure-rest.hh"
10 #include "paper-column.hh"
11 #include "engraver-group-engraver.hh"
12 #include "side-position-interface.hh"
13 #include "staff-symbol-referencer.hh"
14 #include "engraver.hh"
15 #include "moment.hh"
16 #include "spanner.hh"
18 /**
19 The name says it all: make multi measure rests
22 class Multi_measure_rest_engraver : public Engraver
24 public:
25 TRANSLATOR_DECLARATIONS(Multi_measure_rest_engraver);
27 protected:
28 virtual bool try_music (Music*);
29 virtual void process_music ();
30 virtual void stop_translation_timestep ();
31 virtual void start_translation_timestep ();
32 virtual void finalize ();
34 private:
35 Music * new_req_;
36 Music * busy_span_req_;
37 Music * stop_req_;
38 int start_measure_;
39 Moment start_moment_;
42 Spanner *mmrest_;
43 Spanner *number_;
45 Spanner *last_number_;
46 Spanner *last_rest_;
49 Multi_measure_rest_engraver::Multi_measure_rest_engraver ()
51 start_measure_ = 0;
52 mmrest_ = 0;
53 last_rest_ =0;
54 number_ = 0;
55 new_req_ = busy_span_req_ = stop_req_ =0;
58 bool
59 Multi_measure_rest_engraver::try_music (Music* req)
61 if (req->is_mus_type ("multi-measure-rest-event"))
63 Direction d = to_dir (req->get_mus_property ("span-direction"));
64 if (d == STOP)
66 stop_req_ = req;
68 else if (d == START&& !new_req_)
70 new_req_ = req;
72 return true;
74 return false;
77 void
78 Multi_measure_rest_engraver::process_music ()
80 if (new_req_ && stop_req_)
81 stop_req_ = 0;
83 if (new_req_)
84 start_moment_ = now_mom ();
86 if (stop_req_)
88 busy_span_req_ =0;
89 stop_req_ = 0;
92 if (new_req_)
94 busy_span_req_ = new_req_;
95 new_req_ =0;
98 if (busy_span_req_ && !mmrest_)
100 mmrest_ = new Spanner (get_property ("MultiMeasureRest"));
101 number_ = new Spanner (get_property ("MultiMeasureRestNumber"));
103 Side_position_interface::add_support (number_, mmrest_);
104 number_->set_parent (mmrest_, Y_AXIS);
106 announce_grob (mmrest_, busy_span_req_->self_scm());
107 announce_grob (number_, busy_span_req_->self_scm());
108 start_measure_
109 = gh_scm2int (get_property ("currentBarNumber"));
112 if (gh_string_p (get_property ("whichBar")))
114 Grob *cmc = unsmob_grob (get_property( "currentCommandColumn"));
115 Item *it = dynamic_cast<Item*> (cmc);
116 if (mmrest_)
118 add_bound_item (mmrest_, it);
119 add_bound_item (number_, it);
121 if (last_rest_)
123 add_bound_item (last_rest_,it);
124 add_bound_item (last_number_, it);
129 void
130 Multi_measure_rest_engraver::stop_translation_timestep ()
132 SCM smp = get_property ("measurePosition");
133 Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
135 if (mmrest_ && (now_mom () >= start_moment_)
136 && !mp.to_bool ()
137 && mmrest_->get_bound (LEFT) && mmrest_->get_bound (RIGHT))
139 typeset_grob (mmrest_);
140 typeset_grob (number_);
141 Side_position_interface::add_staff_support (number_);
143 we must keep mmrest_ around to set measure-count, so
144 no mmrest_ = 0 here.
150 if (last_rest_)
152 /* sanity check */
153 if (last_rest_->get_bound (LEFT) && last_rest_->get_bound (RIGHT)
154 && last_rest_->get_bound (LEFT) != last_rest_->get_bound (RIGHT))
156 typeset_grob (last_rest_);
157 typeset_grob (last_number_);
159 last_rest_ = 0;
160 last_number_ = 0;
163 if (new_req_)
165 busy_span_req_ = new_req_;
166 new_req_ =0;
171 void
172 Multi_measure_rest_engraver::start_translation_timestep ()
174 SCM smp = get_property ("measurePosition");
175 Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
177 if (mmrest_ && !mp.to_bool ())
179 last_rest_ = mmrest_;
180 last_number_ = number_;
182 int cur = gh_scm2int (get_property ("currentBarNumber"));
183 int num = cur - start_measure_;
184 last_rest_->set_grob_property ("measure-count", gh_int2scm (num));
186 SCM sml = get_property ("measureLength");
187 Rational ml = (unsmob_moment (sml)) ? unsmob_moment (sml)->main_part_ : Rational (1);
188 if (ml >= Rational (2))
190 last_rest_->set_grob_property ("use-breve-rest", SCM_BOOL_T);
193 mmrest_ = 0;
195 SCM text =last_number_->get_grob_property ("text");
196 SCM thres = get_property ("restNumberThreshold");
197 int t = 1;
198 if (gh_number_p (thres))
199 t = gh_scm2int (thres);
201 if (text == SCM_EOL && num <= t)
202 last_number_->suicide();
203 else if (text == SCM_EOL)
205 text = scm_number_to_string (gh_int2scm (num), SCM_MAKINUM (10));
206 last_number_->set_grob_property ("text", text);
212 void
213 Multi_measure_rest_engraver::finalize ()
215 if (mmrest_)
217 typeset_grob (mmrest_);
218 typeset_grob (number_);
220 if (last_rest_)
222 typeset_grob (last_rest_);
223 typeset_grob (last_number_);
227 ENTER_DESCRIPTION(Multi_measure_rest_engraver,
228 /* descr */
229 "Engraves multi-measure rests that are produced with @code{R}. Reads "
230 "measurePosition and currentBarNumber to determine what number to print "
231 "over the MultiMeasureRest. Reads measureLength to determine if it "
232 "should use a whole rest or a breve rest to represent 1 measure "
234 /* creats*/ "MultiMeasureRest MultiMeasureRestNumber",
235 /* accepts */ "multi-measure-rest-event",
236 /* acks */ "",
237 /* reads */ "currentBarNumber restNumberThreshold currentCommandColumn measurePosition measureLength",
238 /* write */ "");