]> git.donarmstrong.com Git - lilypond.git/blob - lily/percent-repeat-engraver.cc
* lily/global-context-scheme.cc: Separated ly:run-translator into
[lilypond.git] / lily / percent-repeat-engraver.cc
1 /*
2   new-chord-tremolo-engraver.cc -- implement Chord_tremolo_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>, Erik Sandberg <mandolaerik@gmail.com>
7 */
8
9
10 #include "score-engraver.hh"
11
12 #include "bar-line.hh"
13 #include "global-context.hh"
14 #include "international.hh"
15 #include "item.hh"
16 #include "misc.hh"
17 #include "percent-repeat-iterator.hh"
18 #include "repeated-music.hh"
19 #include "side-position-interface.hh"
20 #include "spanner.hh"
21 #include "warn.hh"
22
23 #include "translator.icc"
24
25 /*
26 * TODO: Create separate Double_percent_repeat_engraver? 
27 * Or, at least move double percent handling to Slash_repeat_engraver
28 */
29
30 class Percent_repeat_engraver : public Engraver
31 {
32   void typeset_perc ();
33 public:
34   TRANSLATOR_DECLARATIONS (Percent_repeat_engraver);
35   
36 protected:
37   Music *percent_event_;
38
39   /// moment (global time) where percent started.
40   Moment stop_mom_;
41   Moment start_mom_;
42
43   enum Repeat_sign_type
44     {
45       UNKNOWN,
46       MEASURE,
47       DOUBLE_MEASURE,
48     };
49   Repeat_sign_type repeat_sign_type_;
50
51   Spanner *percent_;
52   Spanner *percent_counter_;
53
54 protected:
55   virtual void finalize ();
56   virtual bool try_music (Music *);
57
58   void stop_translation_timestep ();
59   void start_translation_timestep ();
60   void process_music ();
61 };
62
63 Percent_repeat_engraver::Percent_repeat_engraver ()
64 {
65   percent_ = 0;
66   percent_counter_ = 0;
67
68   percent_event_ = 0;
69 }
70
71 bool
72 Percent_repeat_engraver::try_music (Music *m)
73 {
74   if (m->is_mus_type ("percent-event")
75       && !percent_event_)
76     {
77       Moment body_length = m->get_length ();
78       Moment meas_len (robust_scm2moment (get_property ("measureLength"),
79                                           Moment (1)));
80
81       if (meas_len == body_length)
82       {
83         repeat_sign_type_ = MEASURE;
84         start_mom_ = now_mom ();
85         stop_mom_ = now_mom () + body_length;
86         get_global_context ()->add_moment_to_process (stop_mom_);
87       }
88       else if (Moment (2) * meas_len == body_length)
89       {
90         repeat_sign_type_ = DOUBLE_MEASURE;
91         start_mom_ = now_mom () + meas_len;
92         stop_mom_ = now_mom () + body_length; /* never used */
93         get_global_context ()->add_moment_to_process (start_mom_);
94       }
95       else
96         return false;
97
98       percent_event_ = m;
99
100       return true;
101     }
102
103   return false;
104 }
105
106 void
107 Percent_repeat_engraver::process_music ()
108 {
109   if (percent_event_ && now_mom ().main_part_ == start_mom_.main_part_)
110     {
111       if (repeat_sign_type_ == MEASURE)
112         {
113           if (percent_)
114             typeset_perc ();
115           percent_ = make_spanner ("PercentRepeat", percent_event_->self_scm ());
116
117           Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
118           percent_->set_bound (LEFT, col);
119
120           SCM count = percent_event_->get_property ("repeat-count");
121           if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats")))
122             {
123               percent_counter_
124                 = make_spanner ("PercentRepeatCounter", percent_event_->self_scm ());
125
126               SCM text = scm_number_to_string (count, scm_from_int (10));
127               percent_counter_->set_property ("text", text);
128               percent_counter_->set_bound (LEFT, col);
129               Side_position_interface::add_support (percent_counter_,
130                                                     percent_);
131               percent_counter_->set_parent (percent_, Y_AXIS);
132             }
133           else
134             percent_counter_ = 0;
135         }
136       else if (repeat_sign_type_ == DOUBLE_MEASURE)
137         {
138           Item *double_percent = make_item ("DoublePercentRepeat", percent_event_->self_scm ());
139
140           SCM count = percent_event_->get_property ("repeat-count");
141           if (count != SCM_EOL
142               && to_boolean (get_property ("countPercentRepeats")))
143             {
144               Item *double_percent_counter = make_item ("DoublePercentRepeatCounter",
145                                                         percent_event_->self_scm());
146
147               SCM text = scm_number_to_string (count,
148                                                scm_from_int (10));
149               double_percent_counter->set_property ("text", text);
150
151               Side_position_interface::add_support (double_percent_counter,
152                                                     double_percent);
153               double_percent_counter->set_parent (double_percent, Y_AXIS);
154               double_percent_counter->set_parent (double_percent, X_AXIS);
155             }
156           
157           /* forbid breaks on a % line. Should forbid all breaks, really. */
158           context ()->get_score_context ()->set_property ("forbidBreak", SCM_BOOL_T);
159
160           /* No more processing needed. */
161           repeat_sign_type_ = UNKNOWN;
162         }
163     }
164 }
165
166 void
167 Percent_repeat_engraver::finalize ()
168 {
169   if (percent_)
170     {
171       percent_event_->origin ()->warning (_ ("unterminated percent repeat"));
172       percent_->suicide ();
173       percent_counter_->suicide();
174     }
175 }
176
177 void
178 Percent_repeat_engraver::typeset_perc ()
179 {
180   if (percent_)
181     {
182       Grob *col = unsmob_grob (get_property ("currentCommandColumn"));
183
184       percent_->set_bound (RIGHT, col);
185       percent_ = 0;
186
187       if (percent_counter_)
188         percent_counter_->set_bound (RIGHT, col);
189       percent_counter_ = 0;
190     }
191 }
192
193 void
194 Percent_repeat_engraver::start_translation_timestep ()
195 {
196   if (stop_mom_.main_part_ == now_mom ().main_part_)
197     {
198       if (percent_)
199         typeset_perc ();
200       percent_event_ = 0;
201       repeat_sign_type_ = UNKNOWN;
202     }
203 }
204
205 void
206 Percent_repeat_engraver::stop_translation_timestep ()
207 {
208 }
209
210 ADD_TRANSLATOR (Percent_repeat_engraver,
211                 /* doc */
212                 "Make whole bar and double bar repeats.",
213                 
214                 /* create */
215                 "DoublePercentRepeat "
216                 "DoublePercentRepeatCounter "
217                 "PercentRepeat "
218                 "PercentRepeatCounter ",
219                 
220                 /* accept */
221                 "percent-event ",
222
223                 /* read */
224                 "countPercentRepeats "
225                 "currentCommandColumn "
226                 "measureLength ",
227
228                 /* write */
229                 "forbidBreak "
230                 );