]> git.donarmstrong.com Git - lilypond.git/blob - lily/horizontal-bracket-engraver.cc
0a4a388fb9e3590dfd6867c700ddd2d78cc2e677
[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--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
9
10 #include "engraver.hh"
11 #include "side-position-interface.hh"
12 #include "note-column.hh"
13 #include "pointer-group-interface.hh"
14
15 class Horizontal_bracket_engraver : public Engraver
16 {
17 public:
18   TRANSLATOR_DECLARATIONS (Horizontal_bracket_engraver);
19   Link_array<Spanner> bracket_stack_;
20   Link_array<Music> events_;
21   int pop_count_;
22   int push_count_;
23
24   virtual bool try_music (Music *);
25   PRECOMPUTED_VIRTUAL void stop_translation_timestep ();
26   PRECOMPUTED_VIRTUAL void process_music ();
27   virtual void acknowledge_grob (Grob_info);
28 };
29
30 #include "translator.icc"
31
32 ADD_TRANSLATOR (Horizontal_bracket_engraver,
33                 "Create horizontal brackets over notes for musical analysis purposes.",
34                 "HorizontalBracket",
35                 "note-grouping-event",
36                 "note-column-interface",
37                 "",
38                 "");
39
40 Horizontal_bracket_engraver::Horizontal_bracket_engraver ()
41 {
42   pop_count_ = 0;
43   push_count_ = 0;
44 }
45
46 bool
47 Horizontal_bracket_engraver::try_music (Music *m)
48 {
49   if (m->is_mus_type ("note-grouping-event"))
50     {
51       Direction d = to_dir (m->get_property ("span-direction"));
52
53       if (d == STOP)
54         {
55           pop_count_++;
56           if (pop_count_ > bracket_stack_.size ())
57             m->origin ()->warning (_ ("don't have that many brackets"));
58         }
59       else
60         {
61           push_count_++;
62           events_.push (m);
63         }
64
65       if (pop_count_ && push_count_)
66         m->origin ()->warning (_ ("conflicting note group events"));
67
68       return true;
69     }
70   return false;
71 }
72
73 void
74 Horizontal_bracket_engraver::acknowledge_grob (Grob_info gi)
75 {
76   if (Note_column::has_interface (gi.grob ()))
77     {
78       for (int i = 0; i < bracket_stack_.size (); i++)
79         {
80           Side_position_interface::add_support (bracket_stack_[i], gi.grob ());
81           Pointer_group_interface::add_grob (bracket_stack_[i],
82                                              ly_symbol2scm ("columns"), gi.grob ());
83           add_bound_item (bracket_stack_[i],
84                           gi.grob ());
85         }
86     }
87 }
88
89 void
90 Horizontal_bracket_engraver::process_music ()
91 {
92   for (int k = 0; k < push_count_; k++)
93     {
94       Spanner *sp = make_spanner ("HorizontalBracket", events_[k]->self_scm ());
95
96       for (int i = 0; i < bracket_stack_.size (); i++)
97         {
98           /*
99             sp is the smallest, it should be added to the bigger brackets.
100           */
101           Side_position_interface::add_support (bracket_stack_[i], sp);
102         }
103       bracket_stack_.push (sp);
104     }
105 }
106
107 void
108 Horizontal_bracket_engraver::stop_translation_timestep ()
109 {
110   for (int i = pop_count_; i--;)
111     {
112       if (bracket_stack_.size ())
113         bracket_stack_.pop ();
114     }
115   pop_count_ = 0;
116   push_count_ = 0;
117 }
118