]> git.donarmstrong.com Git - lilypond.git/blob - lily/separating-line-group-engraver.cc
use springs in simple-spacer and scrap separating-group-spanner
[lilypond.git] / lily / separating-line-group-engraver.cc
1 /*
2   separating-line-group-engraver.cc -- implement Separating_line_group_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1998--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "engraver.hh"
10
11 #include "separating-group-spanner.hh"
12 #include "separation-item.hh"
13 #include "paper-column.hh"
14 #include "output-def.hh"
15 #include "axis-group-interface.hh"
16 #include "note-spacing.hh"
17 #include "accidental-placement.hh"
18 #include "context.hh"
19 #include "spanner.hh"
20 #include "grob-array.hh"
21 #include "pointer-group-interface.hh"
22
23 #include "translator.icc"
24
25 struct Spacings
26 {
27   Item *staff_spacing_;
28   vector<Item*> note_spacings_;
29
30   Spacings ()
31   {
32     staff_spacing_ = 0;
33   }
34
35   bool is_empty () const
36   {
37     return !staff_spacing_ && !note_spacings_.size ();
38   }
39   void clear ()
40   {
41     staff_spacing_ = 0;
42     note_spacings_.clear ();
43   }
44 };
45
46 class Separating_line_group_engraver : public Engraver
47 {
48 protected:
49   Item *break_item_;
50   Item *musical_item_;
51   Item *last_musical_item_;
52
53   Spacings current_spacings_;
54   Spacings last_spacings_;
55
56   DECLARE_ACKNOWLEDGER (item);
57   void stop_translation_timestep ();
58   void start_translation_timestep ();
59 public:
60   TRANSLATOR_DECLARATIONS (Separating_line_group_engraver);
61 };
62
63 Separating_line_group_engraver::Separating_line_group_engraver ()
64 {
65   break_item_ = 0;
66   musical_item_ = 0;
67 }
68
69 void
70 Separating_line_group_engraver::acknowledge_item (Grob_info i)
71 {
72   Item *it = i.item ();
73   if (it->get_parent (X_AXIS)
74       && it->get_parent (X_AXIS) == it->get_parent (Y_AXIS)
75       && Axis_group_interface::has_axis (it->get_parent (X_AXIS), X_AXIS)
76       && Axis_group_interface::has_axis (it->get_parent (Y_AXIS), Y_AXIS))
77     return;
78
79   if (to_boolean (it->get_property ("no-spacing-rods")))
80     return;
81
82   if (Note_spacing::has_interface (it))
83     {
84       current_spacings_.note_spacings_.push_back (it);
85       return;
86     }
87
88   bool ib = Item::is_non_musical (it);
89   Item *&p_ref_ (ib ? break_item_
90                  : musical_item_);
91
92   if (!p_ref_)
93     {
94       p_ref_ = make_item ("SeparationItem", SCM_EOL);
95
96       if (ib)
97         {
98           p_ref_->set_property ("non-musical", SCM_BOOL_T);
99           context ()->set_property ("breakableSeparationItem", p_ref_->self_scm ());
100         }
101
102       if (to_boolean (get_property ("createSpacing"))
103           && p_ref_ == break_item_)
104         {
105           Item *it = make_item ("StaffSpacing", SCM_EOL);
106           current_spacings_.staff_spacing_ = it;
107           Pointer_group_interface::add_grob (it, ly_symbol2scm ("left-items"),
108                                              break_item_);
109
110           if (!last_spacings_.note_spacings_.size ()
111               && last_spacings_.staff_spacing_)
112             {
113               SCM ri = last_spacings_.staff_spacing_->get_object ("right-items");
114               Grob_array *ga = unsmob_grob_array (ri);
115               if (!ga)
116                 {
117                   SCM ga_scm = Grob_array::make_array ();
118                   last_spacings_.staff_spacing_->set_object ("right-items", ga_scm);
119                   ga = unsmob_grob_array (ga_scm);
120                 }
121
122               ga->clear ();
123               ga->add (break_item_);
124             }
125         }
126     }
127
128   if (Accidental_placement::has_interface (it))
129     Separation_item::add_conditional_item (p_ref_, it);
130   else
131     Separation_item::add_item (p_ref_, it);
132 }
133
134 void
135 Separating_line_group_engraver::start_translation_timestep ()
136 {
137   if (break_item_)
138     {
139       context ()->unset_property (ly_symbol2scm ("breakableSeparationItem"));
140       break_item_ = 0;
141     }
142 }
143
144 void
145 Separating_line_group_engraver::stop_translation_timestep ()
146 {
147   if (Item *sp = current_spacings_.staff_spacing_)
148     {
149       /*
150         TODO: should really look at the left-items of following
151         note-spacing grobs.
152       */
153       if (musical_item_)
154         Pointer_group_interface::add_grob (sp, ly_symbol2scm ("right-items"),
155                                            musical_item_);
156     }
157
158   if (!current_spacings_.is_empty ())
159     last_spacings_ = current_spacings_;
160
161   current_spacings_.clear ();
162
163   musical_item_ = 0;
164 }
165
166 ADD_ACKNOWLEDGER (Separating_line_group_engraver, item);
167 ADD_TRANSLATOR (Separating_line_group_engraver,
168                 /* doc */ "Generates objects for computing spacing parameters.",
169
170                 /* create */
171                 "SeparationItem "
172                 "SeparatingGroupSpanner "
173                 "StaffSpacing",
174                 /* read */ "createSpacing",
175                 /* write */ "breakableSeparationItem");