]> git.donarmstrong.com Git - lilypond.git/blob - lily/horizontal-bracket-engraver.cc
cfcd882a8eb0e512b3be9704e4943a425a7ebc34
[lilypond.git] / lily / horizontal-bracket-engraver.cc
1 /*
2   horizontal-bracket-engraver.cc -- implement
3   Horizontal_bracket_engraver
4
5   source file of the GNU LilyPond music typesetter
6
7   (c) 2002--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
8 */
9
10 #include "engraver.hh"
11 #include "international.hh"
12 #include "note-column.hh"
13 #include "pointer-group-interface.hh"
14 #include "side-position-interface.hh"
15 #include "stream-event.hh"
16
17 #include "translator.icc"
18
19 class Horizontal_bracket_engraver : public Engraver
20 {
21 public:
22   TRANSLATOR_DECLARATIONS (Horizontal_bracket_engraver);
23   vector<Spanner*> bracket_stack_;
24   vector<Stream_event*> events_;
25   vsize pop_count_;
26   vsize push_count_;
27
28   void stop_translation_timestep ();
29   void process_music ();
30   DECLARE_ACKNOWLEDGER (note_column);
31   DECLARE_TRANSLATOR_LISTENER (note_grouping);
32 };
33
34 ADD_ACKNOWLEDGER (Horizontal_bracket_engraver, note_column);
35 ADD_TRANSLATOR (Horizontal_bracket_engraver,
36                 "Create horizontal brackets over notes for musical analysis purposes.",
37                 "HorizontalBracket",
38                 "note-grouping-event",
39                 "",
40                 "");
41
42 Horizontal_bracket_engraver::Horizontal_bracket_engraver ()
43 {
44   pop_count_ = 0;
45   push_count_ = 0;
46 }
47
48 IMPLEMENT_TRANSLATOR_LISTENER (Horizontal_bracket_engraver, note_grouping);
49 void
50 Horizontal_bracket_engraver::listen_note_grouping (Stream_event *ev)
51 {
52   Direction d = to_dir (ev->get_property ("span-direction"));
53
54   if (d == STOP)
55     {
56       pop_count_++;
57       if (pop_count_ > bracket_stack_.size ())
58         ev->origin ()->warning (_ ("don't have that many brackets"));
59     }
60   else
61     {
62       push_count_++;
63       events_.push_back (ev);
64     }
65
66   if (pop_count_ && push_count_)
67     ev->origin ()->warning (_ ("conflicting note group events"));
68 }
69
70 void
71 Horizontal_bracket_engraver::acknowledge_note_column (Grob_info gi)
72 {
73   for (vsize i = 0; i < bracket_stack_.size (); i++)
74     {
75       Side_position_interface::add_support (bracket_stack_[i], gi.grob ());
76       Pointer_group_interface::add_grob (bracket_stack_[i],
77                                          ly_symbol2scm ("columns"), gi.grob ());
78       add_bound_item (bracket_stack_[i],
79                       gi.grob ());
80     }
81 }
82
83 void
84 Horizontal_bracket_engraver::process_music ()
85 {
86   for (vsize k = 0; k < push_count_; k++)
87     {
88       Spanner *sp = make_spanner ("HorizontalBracket", events_[k]->self_scm ());
89
90       for (vsize i = 0; i < bracket_stack_.size (); i++)
91         /* sp is the smallest, it should be added to the bigger brackets.  */
92         Side_position_interface::add_support (bracket_stack_[i], sp);
93       bracket_stack_.push_back (sp);
94     }
95 }
96
97 void
98 Horizontal_bracket_engraver::stop_translation_timestep ()
99 {
100   for (int i = pop_count_; i--;)
101     if (bracket_stack_.size ())
102       bracket_stack_.pop_back ();
103   pop_count_ = 0;
104   push_count_ = 0;
105 }
106