]> git.donarmstrong.com Git - lilypond.git/blob - lily/bar-number-engraver.cc
Web-ja: update introduction
[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 /*
33   TODO: detect the top staff (stavesFound), and acknowledge staff-group
34   system-start-delims. If we find these, and the top staff is in the
35   staff-group, add padding to the bar number.
36 */
37 class Bar_number_engraver : public Engraver
38 {
39 protected:
40   Item *text_;
41   int alternative_starting_bar_number_;
42   int alternative_number_;
43   int alternative_number_increment_;
44   Stream_event *alternative_event_;
45
46 protected:
47   void stop_translation_timestep ();
48   void listen_alternative (Stream_event *);
49   void acknowledge_break_alignment (Grob_info);
50   void process_music ();
51   void create_items ();
52   TRANSLATOR_DECLARATIONS (Bar_number_engraver);
53 };
54
55 void
56 Bar_number_engraver::listen_alternative (Stream_event *ev)
57 {
58   if (alternative_event_)
59     return;
60
61   alternative_event_ = ev;
62   int current_barnumber = robust_scm2int (get_property ("currentBarNumber"), 0);
63   Direction alternative_dir = robust_scm2dir (ev->get_property ("alternative-dir"), CENTER);
64   bool make_alternative = scm_is_eq (get_property ("alternativeNumberingStyle"),
65                                      ly_symbol2scm ("numbers"))
66                           || scm_is_eq (get_property ("alternativeNumberingStyle"),
67                                         ly_symbol2scm ("numbers-with-letters"));
68   if (make_alternative)
69     {
70       /*
71         if we're starting the first alternative, we set the starting
72         bar number to the current bar number
73       */
74       if (alternative_dir == LEFT)
75         alternative_starting_bar_number_ = current_barnumber;
76
77       /*
78         if the alternative is not the last one, we send the
79         current bar number back to the alternative bar number.
80       */
81       if (alternative_dir < RIGHT)
82         current_barnumber = alternative_starting_bar_number_;
83
84       context ()->set_property ("currentBarNumber", scm_from_int (current_barnumber));
85     }
86 }
87
88 void
89 Bar_number_engraver::process_music ()
90 {
91   SCM wb = get_property ("whichBar");
92
93   if (scm_is_string (wb))
94     {
95       Moment mp (robust_scm2moment (get_property ("measurePosition"), Moment (0)));
96       SCM bn = get_property ("currentBarNumber");
97       SCM proc = get_property ("barNumberVisibility");
98       if (scm_is_number (bn) && ly_is_procedure (proc)
99           && to_boolean (scm_call_2 (proc, bn, mp.smobbed_copy ())))
100         {
101           create_items ();
102           SCM alternative_style = get_property ("alternativeNumberingStyle");
103           string text_tag = "";
104           if (scm_is_eq (alternative_style, ly_symbol2scm ("numbers-with-letters")))
105             {
106               if (alternative_event_)
107                 {
108                   Direction alternative_dir = robust_scm2dir (alternative_event_->get_property ("alternative-dir"), RIGHT);
109                   switch (alternative_dir)
110                     {
111                     case LEFT:
112                       alternative_number_ = 0;
113                       break;
114                     case CENTER:
115                       break;
116                     case RIGHT:
117                       alternative_number_ = INT_MIN;
118                       break;
119                     default:
120                       assert (false);
121                     }
122                   alternative_number_ += alternative_number_increment_;
123
124                   alternative_number_increment_ = robust_scm2int (alternative_event_->get_property ("alternative-increment"), 1);
125                 }
126             }
127           SCM formatter = get_property ("barNumberFormatter");
128           if (ly_is_procedure (formatter))
129             text_->set_property ("text", scm_call_4 (formatter,
130                                                      bn,
131                                                      mp.smobbed_copy (),
132                                                      scm_from_int (alternative_number_),
133                                                      context ()->self_scm ()));
134         }
135     }
136 }
137
138 Bar_number_engraver::Bar_number_engraver (Context *c)
139   : Engraver (c)
140 {
141   text_ = 0;
142   alternative_starting_bar_number_ = 0;
143   alternative_number_increment_ = 0;
144   alternative_number_ = INT_MIN;
145   alternative_event_ = 0;
146 }
147
148 void
149 Bar_number_engraver::acknowledge_break_alignment (Grob_info inf)
150 {
151   Grob *s = inf.grob ();
152   if (text_
153       && dynamic_cast<Item *> (s))
154     {
155       text_->set_parent (s, X_AXIS);
156     }
157 }
158
159 void
160 Bar_number_engraver::stop_translation_timestep ()
161 {
162   alternative_event_ = 0;
163   if (text_)
164     {
165       text_->set_object ("side-support-elements",
166                          grob_list_to_grob_array (get_property ("stavesFound")));
167       text_ = 0;
168     }
169 }
170
171 void
172 Bar_number_engraver::create_items ()
173 {
174   if (text_)
175     return;
176
177   text_ = make_item ("BarNumber", SCM_EOL);
178 }
179
180
181 void
182 Bar_number_engraver::boot ()
183 {
184   ADD_LISTENER (Bar_number_engraver, alternative);
185   ADD_ACKNOWLEDGER (Bar_number_engraver, break_alignment);
186 }
187
188 ADD_TRANSLATOR (Bar_number_engraver,
189                 /* doc */
190                 "A bar number is created whenever @code{measurePosition} is"
191                 " zero and when there is a bar line (i.e., when"
192                 " @code{whichBar} is set).  It is put on top of all staves,"
193                 " and appears only at the left side of the staff.  The staves"
194                 " are taken from @code{stavesFound}, which is maintained by"
195                 " @ref{Staff_collecting_engraver}.",
196
197                 /* create */
198                 "BarNumber ",
199
200                 /* read */
201                 "currentBarNumber "
202                 "whichBar "
203                 "stavesFound "
204                 "barNumberFormatter "
205                 "barNumberVisibility "
206                 "alternativeNumberingStyle ",
207
208                 /* write */
209                 "currentBarNumber "
210                );