]> git.donarmstrong.com Git - lilypond.git/blob - lily/note-head-line-engraver.cc
patch::: 1.3.139.jcn1
[lilypond.git] / lily / note-head-line-engraver.cc
1 /*   
2   note-head-line-engraver.cc -- implement Note_head_line_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000--2001 Jan Nieuwenhuizen <janneke@gnu.org>
7  */
8
9 #include "engraver.hh"
10 #include "group-interface.hh"
11 #include "item.hh"
12 #include "musical-request.hh"
13 #include "spanner.hh"
14 #include "stem.hh"
15 #include "rhythmic-head.hh"
16 #include "side-position-interface.hh"
17 #include "staff-symbol-referencer.hh"
18 #include "translator-group.hh"
19
20 /**
21    Create line-spanner grobs for glissandi (and possibly other) lines
22    that connect note heads.
23
24
25    TODO: have the line commit suicide if the notes are connected with
26    either slur or beam.
27
28 */
29 class Note_head_line_engraver : public Engraver
30 {
31 public:
32   VIRTUAL_COPY_CONS (Translator);
33   Note_head_line_engraver ();
34
35 protected:
36   virtual void acknowledge_grob (Grob_info);
37   virtual void create_grobs ();
38   virtual void stop_translation_timestep ();
39   virtual bool try_music (Music *);
40
41 private:
42   Spanner* line_; 
43   Request* req_;
44   Request* last_req_;
45   Translator* last_staff_;
46   bool follow_;
47   Grob* head_;
48   Grob* last_head_;
49 };
50
51 Note_head_line_engraver::Note_head_line_engraver ()
52 {
53   line_ = 0;
54   req_ = 0;
55   last_req_ = 0;
56   follow_ = false;
57   head_ = 0;
58   last_head_ = 0;
59   last_staff_ = 0;
60 }
61
62 bool
63 Note_head_line_engraver::try_music (Music* m)
64 {
65   if (!req_)
66     {
67       if (Glissando_req *r = dynamic_cast<Glissando_req*> (m))
68         {
69           req_ = r;
70           return true;
71         }
72     }
73   return false;
74 }
75
76 void
77 Note_head_line_engraver::acknowledge_grob (Grob_info info)
78 {
79   if (Rhythmic_head::has_interface (info.elem_l_))
80     {
81       head_ = info.elem_l_;
82       if (to_boolean (get_property ("followVoice")))
83         {
84           Translator_group  * tr = daddy_trans_l_;
85           while (tr && tr->type_str_ != "Staff")
86             tr = tr->daddy_trans_l_ ;
87
88           if (tr && tr->type_str_ == "Staff" && tr != last_staff_)
89             {
90               if (last_head_)
91                 follow_ = true;
92               last_staff_ = tr;
93             }
94         }
95     }
96 }
97
98
99 void
100 Note_head_line_engraver::create_grobs ()
101 {
102   if (!line_ && (follow_ || last_req_) && last_head_ && head_
103       && (last_head_ != head_))
104     {
105       /* TODO: Don't follow if there's a beam.
106
107          We can't do beam-stuff here, since beam doesn't exist yet.
108          Should probably store follow_ in line_, and suicide at some
109          later point */
110       if (follow_)
111         line_ = new Spanner (get_property ("VoiceFollower"));
112       else
113         line_ = new Spanner (get_property ("Glissando"));
114           
115       line_->set_bound (LEFT, last_head_);
116       line_->set_bound (RIGHT, head_);
117           
118           /* Note, mustn't set y-parent of breakable symbol to simple item:
119              one of the two broken parts won't have an y-parent! */
120           /* X parent is set by set_bound */
121       line_->set_parent (Staff_symbol_referencer::staff_symbol_l (last_head_),
122                          Y_AXIS);
123           
124       announce_grob (line_, last_req_);
125       last_req_ = 0;    
126
127       follow_ = false;
128     }
129 }
130
131 void
132 Note_head_line_engraver::stop_translation_timestep ()
133 {
134   if (line_)
135     {
136       typeset_grob (line_);
137       line_ = 0;
138     }
139   if (head_)
140     last_head_ = head_;
141   head_ = 0;
142
143   if (req_)
144     {
145       last_req_ = req_;
146       req_ =0;
147     }
148 }
149
150
151 ADD_THIS_TRANSLATOR (Note_head_line_engraver);
152