Move ambitus print callback to scheme.
[lilypond/mpolesky.git] / lily / percent-repeat-engraver.cc
blobea77254cfc1d29cfbfa18b24b3945b3a7d4fbb24
1 /*
2 percent-repeat-engraver.cc -- implement Percent_repeat_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>, Erik Sandberg <mandolaerik@gmail.com>
7 */
10 #include "score-engraver.hh"
12 #include "bar-line.hh"
13 #include "global-context.hh"
14 #include "international.hh"
15 #include "item.hh"
16 #include "misc.hh"
17 #include "repeated-music.hh"
18 #include "side-position-interface.hh"
19 #include "spanner.hh"
20 #include "stream-event.hh"
21 #include "warn.hh"
23 #include "translator.icc"
26 * TODO: Create separate Double_percent_repeat_engraver?
27 * Or, at least move double percent handling to Slash_repeat_engraver
30 class Percent_repeat_engraver : public Engraver
32 void typeset_perc ();
33 bool check_count_visibility (SCM count);
34 public:
35 TRANSLATOR_DECLARATIONS (Percent_repeat_engraver);
37 protected:
38 Stream_event *percent_event_;
40 /// moment (global time) where percent started.
41 Moment stop_mom_;
42 Moment start_mom_;
44 enum Repeat_sign_type
46 UNKNOWN,
47 MEASURE,
48 DOUBLE_MEASURE,
50 Repeat_sign_type repeat_sign_type_;
52 Spanner *percent_;
53 Spanner *percent_counter_;
56 Grob *first_command_column_;
57 Moment command_moment_;
59 protected:
60 virtual void finalize ();
61 DECLARE_TRANSLATOR_LISTENER (percent);
63 void stop_translation_timestep ();
64 void start_translation_timestep ();
65 void process_music ();
68 Percent_repeat_engraver::Percent_repeat_engraver ()
70 percent_ = 0;
71 percent_counter_ = 0;
72 percent_event_ = 0;
74 first_command_column_ = 0;
75 command_moment_ = Moment (-1);
78 void
79 Percent_repeat_engraver::start_translation_timestep ()
81 if (now_mom ().main_part_ != command_moment_.main_part_)
83 first_command_column_ = unsmob_grob (get_property ("currentCommandColumn"));
84 command_moment_ = now_mom ();
87 if (stop_mom_.main_part_ == now_mom ().main_part_)
89 if (percent_)
90 typeset_perc ();
91 percent_event_ = 0;
92 repeat_sign_type_ = UNKNOWN;
96 IMPLEMENT_TRANSLATOR_LISTENER (Percent_repeat_engraver, percent);
97 void
98 Percent_repeat_engraver::listen_percent (Stream_event *ev)
100 if (!percent_event_)
102 Moment body_length = get_event_length (ev);
103 Moment meas_len (robust_scm2moment (get_property ("measureLength"),
104 Moment (1)));
105 if (meas_len == body_length)
107 repeat_sign_type_ = MEASURE;
108 start_mom_ = now_mom ();
109 stop_mom_ = now_mom () + body_length;
110 get_global_context ()->add_moment_to_process (stop_mom_);
112 else if (Moment (2) * meas_len == body_length)
114 repeat_sign_type_ = DOUBLE_MEASURE;
115 start_mom_ = now_mom () + meas_len;
116 stop_mom_ = now_mom () + body_length; /* never used */
117 get_global_context ()->add_moment_to_process (start_mom_);
119 else
122 don't warn about percent repeats: slash repeats are not
123 exactly 1 or 2 measures long.
125 return;
127 percent_event_ = ev;
129 else
130 /* print a warning: no assignment happens because
131 percent_event_ != 0 */
132 ASSIGN_EVENT_ONCE (percent_event_, ev);
135 void
136 Percent_repeat_engraver::process_music ()
138 if (percent_event_ && now_mom ().main_part_ == start_mom_.main_part_)
140 if (repeat_sign_type_ == MEASURE)
142 if (percent_)
143 typeset_perc ();
145 percent_ = make_spanner ("PercentRepeat", percent_event_->self_scm ());
147 Grob *col = first_command_column_;
148 percent_->set_bound (LEFT, col);
150 SCM count = percent_event_->get_property ("repeat-count");
151 if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats"))
152 && check_count_visibility (count))
154 percent_counter_
155 = make_spanner ("PercentRepeatCounter", percent_event_->self_scm ());
157 SCM text = scm_number_to_string (count, scm_from_int (10));
158 percent_counter_->set_property ("text", text);
159 percent_counter_->set_bound (LEFT, col);
160 Side_position_interface::add_support (percent_counter_,
161 percent_);
162 percent_counter_->set_parent (percent_, Y_AXIS);
164 else
165 percent_counter_ = 0;
167 else if (repeat_sign_type_ == DOUBLE_MEASURE)
169 Item *double_percent = make_item ("DoublePercentRepeat", percent_event_->self_scm ());
171 SCM count = percent_event_->get_property ("repeat-count");
172 if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats"))
173 && check_count_visibility (count))
175 Item *double_percent_counter = make_item ("DoublePercentRepeatCounter",
176 percent_event_->self_scm ());
178 SCM text = scm_number_to_string (count,
179 scm_from_int (10));
180 double_percent_counter->set_property ("text", text);
182 Side_position_interface::add_support (double_percent_counter,
183 double_percent);
184 double_percent_counter->set_parent (double_percent, Y_AXIS);
185 double_percent_counter->set_parent (double_percent, X_AXIS);
188 /* forbid breaks on a % line. Should forbid all breaks, really. */
189 context ()->get_score_context ()->set_property ("forbidBreak", SCM_BOOL_T);
191 /* No more processing needed. */
192 repeat_sign_type_ = UNKNOWN;
197 void
198 Percent_repeat_engraver::finalize ()
200 if (percent_)
202 percent_event_->origin ()->warning (_ ("unterminated percent repeat"));
203 percent_->suicide ();
204 percent_counter_->suicide ();
208 void
209 Percent_repeat_engraver::typeset_perc ()
211 if (percent_)
213 Grob *col = first_command_column_;
215 percent_->set_bound (RIGHT, col);
216 percent_ = 0;
218 if (percent_counter_)
219 percent_counter_->set_bound (RIGHT, col);
220 percent_counter_ = 0;
224 bool
225 Percent_repeat_engraver::check_count_visibility (SCM count)
227 SCM proc = get_property ("repeatCountVisibility");
228 return (ly_is_procedure (proc) && to_boolean (scm_call_2 (proc,
229 count,
230 context ()->self_scm ())));
234 void
235 Percent_repeat_engraver::stop_translation_timestep ()
239 ADD_TRANSLATOR (Percent_repeat_engraver,
240 /* doc */
241 "Make whole bar and double bar repeats.",
243 /* create */
244 "DoublePercentRepeat "
245 "DoublePercentRepeatCounter "
246 "PercentRepeat "
247 "PercentRepeatCounter ",
249 /* read */
250 "countPercentRepeats "
251 "currentCommandColumn "
252 "measureLength "
253 "repeatCountVisibility ",
255 /* write */
256 "forbidBreak "