]> git.donarmstrong.com Git - lilypond.git/blob - lily/bar-number-engraver.cc
Issue 4550 (1/2) Avoid "using namespace std;" in included files
[lilypond.git] / lily / bar-number-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <algorithm> // for reverse
21
22 #include "paper-column.hh"
23 #include "output-def.hh"
24 #include "side-position-interface.hh"
25 #include "engraver.hh"
26 #include "context.hh"
27 #include "grob-array.hh"
28 #include "stream-event.hh"
29
30 #include "translator.icc"
31
32 using std::string;
33
34 /*
35   TODO: detect the top staff (stavesFound), and acknowledge staff-group
36   system-start-delims. If we find these, and the top staff is in the
37   staff-group, add padding to the bar number.
38 */
39 class Bar_number_engraver : public Engraver
40 {
41 protected:
42   Item *text_;
43   int alternative_starting_bar_number_;
44   int alternative_number_;
45   int alternative_number_increment_;
46   Stream_event *alternative_event_;
47
48 protected:
49   void stop_translation_timestep ();
50   DECLARE_TRANSLATOR_LISTENER (alternative);
51   DECLARE_ACKNOWLEDGER (break_alignment);
52   void process_music ();
53   void create_items ();
54   TRANSLATOR_DECLARATIONS (Bar_number_engraver);
55 };
56
57 IMPLEMENT_TRANSLATOR_LISTENER (Bar_number_engraver, alternative);
58 void
59 Bar_number_engraver::listen_alternative (Stream_event *ev)
60 {
61   if (alternative_event_)
62     return;
63
64   alternative_event_ = ev;
65   int current_barnumber = robust_scm2int (get_property ("currentBarNumber"), 0);
66   Direction alternative_dir = robust_scm2dir (ev->get_property ("alternative-dir"), CENTER);
67   bool make_alternative = scm_is_eq (get_property ("alternativeNumberingStyle"),
68                                      ly_symbol2scm ("numbers"))
69                           || scm_is_eq (get_property ("alternativeNumberingStyle"),
70                                         ly_symbol2scm ("numbers-with-letters"));
71   if (make_alternative)
72     {
73       /*
74         if we're starting the first alternative, we set the starting
75         bar number to the current bar number
76       */
77       if (alternative_dir == LEFT)
78         alternative_starting_bar_number_ = current_barnumber;
79
80       /*
81         if the alternative is not the last one, we send the
82         current bar number back to the alternative bar number.
83       */
84       if (alternative_dir < RIGHT)
85         current_barnumber = alternative_starting_bar_number_;
86
87       context ()->set_property ("currentBarNumber", scm_from_int (current_barnumber));
88     }
89 }
90
91 void
92 Bar_number_engraver::process_music ()
93 {
94   SCM wb = get_property ("whichBar");
95
96   if (scm_is_string (wb))
97     {
98       Moment mp (robust_scm2moment (get_property ("measurePosition"), Moment (0)));
99       SCM bn = get_property ("currentBarNumber");
100       SCM proc = get_property ("barNumberVisibility");
101       if (scm_is_number (bn) && ly_is_procedure (proc)
102           && to_boolean (scm_call_2 (proc, bn, mp.smobbed_copy ())))
103         {
104           create_items ();
105           SCM alternative_style = get_property ("alternativeNumberingStyle");
106           string text_tag = "";
107           if (scm_is_eq (alternative_style, ly_symbol2scm ("numbers-with-letters")))
108             {
109               if (alternative_event_)
110                 {
111                   Direction alternative_dir = robust_scm2dir (alternative_event_->get_property ("alternative-dir"), RIGHT);
112                   switch (alternative_dir)
113                     {
114                     case LEFT:
115                       alternative_number_ = 0;
116                       break;
117                     case CENTER:
118                       break;
119                     case RIGHT:
120                       alternative_number_ = INT_MIN;
121                       break;
122                     default:
123                       assert (false);
124                     }
125                   alternative_number_ += alternative_number_increment_;
126
127                   alternative_number_increment_ = robust_scm2int (alternative_event_->get_property ("alternative-increment"), 1);
128                 }
129             }
130           SCM formatter = get_property ("barNumberFormatter");
131           if (ly_is_procedure (formatter))
132             text_->set_property ("text", scm_call_4 (formatter,
133                                                      bn,
134                                                      mp.smobbed_copy (),
135                                                      scm_from_int (alternative_number_),
136                                                      context ()->self_scm ()));
137         }
138     }
139 }
140
141 Bar_number_engraver::Bar_number_engraver ()
142 {
143   text_ = 0;
144   alternative_starting_bar_number_ = 0;
145   alternative_number_increment_ = 0;
146   alternative_number_ = INT_MIN;
147   alternative_event_ = 0;
148 }
149
150 void
151 Bar_number_engraver::acknowledge_break_alignment (Grob_info inf)
152 {
153   Grob *s = inf.grob ();
154   if (text_
155       && dynamic_cast<Item *> (s))
156     {
157       text_->set_parent (s, X_AXIS);
158     }
159 }
160
161 void
162 Bar_number_engraver::stop_translation_timestep ()
163 {
164   alternative_event_ = 0;
165   if (text_)
166     {
167       text_->set_object ("side-support-elements",
168                          grob_list_to_grob_array (get_property ("stavesFound")));
169       text_ = 0;
170     }
171 }
172
173 void
174 Bar_number_engraver::create_items ()
175 {
176   if (text_)
177     return;
178
179   text_ = make_item ("BarNumber", SCM_EOL);
180 }
181
182 ADD_ACKNOWLEDGER (Bar_number_engraver, break_alignment);
183
184 ADD_TRANSLATOR (Bar_number_engraver,
185                 /* doc */
186                 "A bar number is created whenever @code{measurePosition} is"
187                 " zero and when there is a bar line (i.e., when"
188                 " @code{whichBar} is set).  It is put on top of all staves,"
189                 " and appears only at the left side of the staff.  The staves"
190                 " are taken from @code{stavesFound}, which is maintained by"
191                 " @ref{Staff_collecting_engraver}.",
192
193                 /* create */
194                 "BarNumber ",
195
196                 /* read */
197                 "currentBarNumber "
198                 "whichBar "
199                 "stavesFound "
200                 "barNumberFormatter "
201                 "barNumberVisibility "
202                 "alternativeNumberingStyle ",
203
204                 /* write */
205                 "currentBarNumber "
206                );