Nitpick: ly:spanner-bound grob name slur -> spanner.
[lilypond.git] / lily / dynamic-align-engraver.cc
blobac5e0e4c21ac6b7eed653a1dff9bff6e66500b9c
1 /*
2 dynamic-align-engraver.cc -- implement Dynamic_align_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2008--2009 Han-Wen Nienhuys <hanwen@lilypond.org>
8 */
10 #include <set>
12 #include "engraver.hh"
14 #include "axis-group-interface.hh"
15 #include "directional-element-interface.hh"
16 #include "item.hh"
17 #include "side-position-interface.hh"
18 #include "spanner.hh"
19 #include "stream-event.hh"
21 #include "translator.icc"
23 class Dynamic_align_engraver : public Engraver
25 TRANSLATOR_DECLARATIONS (Dynamic_align_engraver);
26 DECLARE_ACKNOWLEDGER (note_column);
27 DECLARE_ACKNOWLEDGER (dynamic);
28 DECLARE_END_ACKNOWLEDGER (dynamic);
30 protected:
31 virtual void stop_translation_timestep ();
33 private:
34 void create_line_spanner (Stream_event *cause);
35 Spanner* line_;
37 vector<Spanner*> ended_;
38 vector<Spanner*> started_;
39 vector<Grob*> scripts_;
40 vector<Grob*> support_;
42 set<Spanner*> running_;
45 Dynamic_align_engraver::Dynamic_align_engraver ()
47 line_ = 0;
50 ADD_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
51 ADD_ACKNOWLEDGER (Dynamic_align_engraver, note_column);
52 ADD_END_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
54 void
55 Dynamic_align_engraver::create_line_spanner (Stream_event* event)
57 if (!line_)
58 line_ = make_spanner ("DynamicLineSpanner",
59 event ? event->self_scm() : SCM_EOL);
62 void
63 Dynamic_align_engraver::acknowledge_end_dynamic (Grob_info info)
65 if (Spanner::has_interface(info.grob()))
66 ended_.push_back (info.spanner ());
69 void
70 Dynamic_align_engraver::acknowledge_note_column (Grob_info info)
72 support_.push_back (info.grob ());
75 void
76 Dynamic_align_engraver::acknowledge_dynamic (Grob_info info)
78 Stream_event *cause = info.event_cause ();
79 create_line_spanner (cause);
80 if (Spanner::has_interface(info.grob()))
81 started_.push_back (info.spanner ());
82 else if (info.item())
83 scripts_.push_back (info.item());
84 else
85 info.grob ()->programming_error ("Unknown dynamic grob.");
87 Axis_group_interface::add_element (line_, info.grob ());
89 if (cause)
91 if (Direction d = to_dir (cause->get_property ("direction")))
92 set_grob_direction (line_, d);
96 void
97 Dynamic_align_engraver::stop_translation_timestep ()
99 for (vsize i = 0; i < started_.size(); i++)
100 running_.insert (started_[i]);
101 for (vsize i = 0; i < ended_.size(); i++)
103 Spanner *sp = ended_[i];
105 set<Spanner*>::iterator it = running_.find (sp);
106 if (it != running_.end())
107 running_.erase (it);
108 else
109 started_[i]->programming_error ("Lost track of this dynamic spanner.");
112 bool end = line_ && running_.empty ();
113 Direction d = LEFT;
116 if (line_
117 && ((d == LEFT && !line_->get_bound (LEFT))
118 || (end && d == RIGHT && !line_->get_bound (RIGHT))))
120 vector<Spanner*> const &spanners =
121 (d == LEFT) ? started_ : ended_;
123 Grob *bound = 0;
124 if (scripts_.size())
125 bound = scripts_[0];
126 else if (spanners.size())
127 bound = spanners[0]->get_bound (d);
128 else
130 programming_error ("Started DynamicLineSpanner but have no left bound.");
131 bound = unsmob_grob (get_property ("currentMusicalColumn"));
134 line_->set_bound (d, bound);
137 while (flip (&d) != LEFT);
139 for (vsize i = 0; line_ && i < support_.size (); i++)
140 Side_position_interface::add_support (line_, support_[i]);
142 if (end)
143 line_ = 0;
145 ended_.clear ();
146 started_.clear ();
147 scripts_.clear ();
148 support_.clear ();
152 ADD_TRANSLATOR (Dynamic_align_engraver,
153 /* doc */
154 "Align hairpins and dynamic texts on a horizontal line",
156 /* create */
157 "DynamicLineSpanner ",
159 /* read */
160 "currentMusicalColumn ",
162 /* write */