]> git.donarmstrong.com Git - lilypond.git/blob - lily/keep-alive-together-engraver.cc
Merge branch 'master' of /home/jcharles/GIT/Lily/. into translation
[lilypond.git] / lily / keep-alive-together-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2010--2015 Joe Neeman <joeneeman@gmail.com>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "context.hh"
21 #include "dispatcher.hh"
22 #include "engraver.hh"
23 #include "grob.hh"
24 #include "grob-array.hh"
25 #include "international.hh"
26
27 #include "translator.icc"
28
29 class Keep_alive_together_engraver: public Engraver
30 {
31   vector<Grob *> group_spanners_;
32
33 public:
34   TRANSLATOR_DECLARATIONS (Keep_alive_together_engraver);
35   void acknowledge_hara_kiri_group_spanner (Grob_info);
36
37   virtual void finalize ();
38 };
39
40 Keep_alive_together_engraver::Keep_alive_together_engraver ()
41 {
42 }
43
44 void
45 Keep_alive_together_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
46 {
47   group_spanners_.push_back (i.grob ());
48 }
49
50 void
51 Keep_alive_together_engraver::finalize ()
52 {
53   for (vsize i = 0; i < group_spanners_.size (); ++i)
54     {
55       SCM this_layer = group_spanners_[i]->get_property ("remove-layer");
56       if (scm_is_false (this_layer))
57         continue;
58
59       SCM live_scm = Grob_array::make_array ();
60       Grob_array *live = unsmob<Grob_array> (live_scm);
61       SCM dead_scm = Grob_array::make_array ();
62       Grob_array *dead = unsmob<Grob_array> (dead_scm);
63
64       for (vsize j = 0; j < group_spanners_.size (); ++j)
65         {
66           if (i == j)
67             continue;
68
69           if (scm_is_symbol (this_layer))
70             {
71               if (scm_is_eq (this_layer, ly_symbol2scm ("any")))
72                 {
73                   // layer is kept alive by any other layer
74                   live->add (group_spanners_[j]);
75                   continue;
76                 }
77               else if (scm_is_eq (this_layer, ly_symbol2scm ("above")))
78                 {
79                   // layer is kept alive by the layer preceding it
80                   if (i == j + 1)
81                     live->add (group_spanners_[j]);
82                   continue;
83                 }
84               else if (scm_is_eq (this_layer, ly_symbol2scm ("below")))
85                 {
86                   // layer is kept alive by the layer following it
87                   if (i == j - 1)
88                     live->add (group_spanners_[j]);
89                   continue;
90                 }
91               else
92                 {
93                   group_spanners_[i]->warning (_f ("unknown remove-layer value `%s'",
94                                                    ly_symbol2string (this_layer).c_str ()));
95                   continue;
96                 }
97             }
98
99           SCM that_layer = group_spanners_[j]->get_property ("remove-layer");
100
101           if (scm_is_false (that_layer))
102             continue;
103           if (!scm_is_integer (this_layer))
104             {
105               // unset layers are kept alive by all but ignored layers
106               live->add (group_spanners_[j]);
107               continue;
108             }
109           // an explicit layer is only affected by explicit layers
110           if (!scm_is_integer (that_layer))
111             continue;
112           if (scm_is_true (scm_num_eq_p (that_layer, this_layer)))
113             live->add (group_spanners_[j]);
114           else if (scm_is_true (scm_less_p (that_layer, this_layer)))
115             dead->add (group_spanners_[j]);
116         }
117       if (!live->empty ())
118         group_spanners_[i]->set_object ("keep-alive-with", live_scm);
119       if (!dead->empty ())
120         group_spanners_[i]->set_object ("make-dead-when", dead_scm);
121     }
122 }
123
124
125 void
126 Keep_alive_together_engraver::boot ()
127 {
128   ADD_ACKNOWLEDGER (Keep_alive_together_engraver, hara_kiri_group_spanner);
129 }
130
131 ADD_TRANSLATOR (Keep_alive_together_engraver,
132                 /* doc */
133                 "This engraver collects all @code{Hara_kiri_group_spanner}s "
134                 "that are created in contexts at or below its own.  "
135                 "These spanners are then tied together so that one will "
136                 "be removed only if all are removed.  For example, "
137                 "if a @code{StaffGroup} uses this engraver, then the staves "
138                 "in the group will all be visible as long as there is a note "
139                 "in at least one of them.",
140
141                 /* create */
142                 "",
143
144                 /* read */
145                 "",
146
147                 /* write */
148                 ""
149                );