]> git.donarmstrong.com Git - lilypond.git/blob - lily/axis-group-engraver.cc
(process_acknowledged_grobs): catch
[lilypond.git] / lily / axis-group-engraver.cc
1 /*   
2   axis-group-engraver.cc --  implement Axis_group_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1999--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7  */
8
9 #include "spanner.hh"
10 #include "paper-column.hh"
11 #include "axis-group-interface.hh"
12 #include "engraver.hh"
13 #include "engraver-group-engraver.hh"
14 #include "warn.hh"
15 #include "context.hh"
16
17 /**
18    Put stuff in a Spanner with an Axis_group_interface.
19    Use as last element of a context. 
20  */
21 class Axis_group_engraver : public Engraver
22 {
23 protected:
24   Spanner *staffline_;
25   Link_array<Grob> elts_;
26   virtual void process_music ();
27   virtual void finalize ();
28   virtual void acknowledge_grob (Grob_info);
29   virtual void process_acknowledged_grobs ();
30   virtual Spanner* get_spanner () ;
31   virtual void add_element (Grob*) ;
32 public:  
33   TRANSLATOR_DECLARATIONS (Axis_group_engraver);
34 };
35
36 Axis_group_engraver::Axis_group_engraver ()
37 {
38   staffline_ = 0;
39 }
40
41 void
42 Axis_group_engraver::process_music ()
43 {
44   if (!staffline_)
45     {
46       staffline_ = get_spanner ();
47
48       Grob *  it = unsmob_grob (get_property ("currentCommandColumn"));
49
50       staffline_->set_bound (LEFT,it);
51     }
52
53
54 Spanner*
55 Axis_group_engraver::get_spanner () 
56 {
57   return make_spanner ("VerticalAxisGroup", SCM_EOL);
58 }
59
60 /*
61   TODO: should we junk minimumVerticalExtent/extraVerticalExtent ?  
62  */
63
64 void
65 Axis_group_engraver::finalize ()
66 {
67   if (!staffline_)
68     return ;
69   
70   String type = context ()->context_name ();
71   SCM dims = get_property ("verticalExtent");
72   
73   if (is_number_pair (dims))
74     staffline_->set_extent (dims, Y_AXIS);
75
76   dims = get_property ("minimumVerticalExtent");
77   if (is_number_pair (dims) )
78     staffline_->set_property ("minimum-Y-extent", dims);
79
80   dims = get_property ("extraVerticalExtent");
81   if (is_number_pair (dims))
82     staffline_->set_property ("extra-Y-extent", dims);
83
84   Grob *  it = unsmob_grob (get_property ("currentCommandColumn"));
85
86   staffline_->set_bound (RIGHT,it);
87
88   staffline_ = 0;
89 }
90
91 void
92 Axis_group_engraver::acknowledge_grob (Grob_info i)
93 {
94   elts_.push (i.grob_);
95 }
96
97 /*
98   maybe should check if our parent is set, because we now get a
99   cyclic parent relationship if we have two Axis_group_engravers in
100   the context.  */
101 void
102 Axis_group_engraver::process_acknowledged_grobs ()
103 {
104   if (!staffline_) 
105     return ;
106   
107   for (int i=0; i < elts_.size (); i++)
108     {
109       Grob *par = elts_[i]->get_parent (Y_AXIS);
110
111       if (!par || !Axis_group_interface::has_interface (par))
112         {
113           if (staffline_->get_parent (Y_AXIS)
114               && staffline_->get_parent (Y_AXIS) == elts_[i])
115             {
116               String msg = _("Axis_group_engraver: vertical group already has a parent.\n"
117                              "Do you have two Axis_group_engravers?\n"
118                              "Killing this vertical group.");
119               staffline_->warning (msg);
120               staffline_->suicide ();
121               staffline_ = 0;
122               break ;
123             }
124           else if (elts_[i]->is_empty (Y_AXIS))
125             {
126               /*
127                 We have to do _something_, otherwise staff objects will
128                 end up with System as parent.  
129               
130               */
131               elts_[i]->set_parent (staffline_, Y_AXIS);
132             }
133           else
134             add_element (elts_[i]);
135         }
136     }
137   elts_.clear ();
138 }
139
140 void
141 Axis_group_engraver::add_element (Grob*e)
142 {
143   Axis_group_interface::add_element (staffline_, e);
144 }
145
146 /****************************************************************/
147
148 /*
149   
150  maybenot such a good idea after all., to put class declarations in
151  .cc
152  
153 */
154
155 #include "hara-kiri-group-spanner.hh"
156 #include "rhythmic-head.hh"
157
158 class Hara_kiri_engraver : public Axis_group_engraver
159 {
160 protected:
161   virtual Spanner*get_spanner ();
162   virtual void acknowledge_grob (Grob_info);
163   virtual void add_element (Grob *e);
164 public:
165   TRANSLATOR_DECLARATIONS (Hara_kiri_engraver);
166 };
167
168 void
169 Hara_kiri_engraver::add_element (Grob*e)
170 {
171   Hara_kiri_group_spanner::add_element (staffline_, e);
172 }
173
174
175 Spanner*
176 Hara_kiri_engraver::get_spanner () 
177 {
178   Spanner * sp = make_spanner ("RemoveEmptyVerticalGroup", SCM_EOL);
179   
180   return sp;
181 }
182
183 void
184 Hara_kiri_engraver::acknowledge_grob (Grob_info i)
185 {
186   Axis_group_engraver::acknowledge_grob (i);
187   if (staffline_
188       && (i.grob_->internal_has_interface (ly_symbol2scm ("rhythmic-grob-interface"))
189           || i.grob_->internal_has_interface (ly_symbol2scm ("lyric-interface")))
190       )
191     {
192       Hara_kiri_group_spanner::add_interesting_item (staffline_, i.grob_);
193     }
194 }
195
196
197 Hara_kiri_engraver::Hara_kiri_engraver ()
198 {
199 }
200
201 ENTER_DESCRIPTION (Hara_kiri_engraver,
202 /* descr */       "Like Axis_group_engraver, but make a hara-kiri spanner, and add "
203 "interesting items (ie. note heads, lyric syllables and normal rests) ",
204 /* creats*/       "RemoveEmptyVerticalGroup",
205 /* accepts */     "",
206 /* acks  */      "grob-interface",
207 /* reads */       "",
208 /* write */       "");
209
210 ENTER_DESCRIPTION (Axis_group_engraver,
211 /* descr */       "Group all objects created in this context in a VerticalAxisGroup spanner.",
212 /* creats*/       "VerticalAxisGroup",
213 /* accepts */     "",
214 /* acks  */      "grob-interface",
215 /* reads */       "verticalExtent minimumVerticalExtent extraVerticalExtent",
216 /* write */       "");