]> git.donarmstrong.com Git - lilypond.git/blob - lily/keep-alive-together-engraver.cc
Web-ja: update introduction
[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 (Context *c)
41   : Engraver (c)
42 {
43 }
44
45 void
46 Keep_alive_together_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
47 {
48   group_spanners_.push_back (i.grob ());
49 }
50
51 void
52 Keep_alive_together_engraver::finalize ()
53 {
54   for (vsize i = 0; i < group_spanners_.size (); ++i)
55     {
56       SCM this_layer = group_spanners_[i]->get_property ("remove-layer");
57       if (scm_is_false (this_layer))
58         continue;
59
60       SCM live_scm = Grob_array::make_array ();
61       Grob_array *live = unsmob<Grob_array> (live_scm);
62       SCM dead_scm = Grob_array::make_array ();
63       Grob_array *dead = unsmob<Grob_array> (dead_scm);
64
65       for (vsize j = 0; j < group_spanners_.size (); ++j)
66         {
67           if (i == j)
68             continue;
69
70           if (scm_is_symbol (this_layer))
71             {
72               if (scm_is_eq (this_layer, ly_symbol2scm ("any")))
73                 {
74                   // layer is kept alive by any other layer
75                   live->add (group_spanners_[j]);
76                   continue;
77                 }
78               else if (scm_is_eq (this_layer, ly_symbol2scm ("above")))
79                 {
80                   // layer is kept alive by the layer preceding it
81                   if (i == j + 1)
82                     live->add (group_spanners_[j]);
83                   continue;
84                 }
85               else if (scm_is_eq (this_layer, ly_symbol2scm ("below")))
86                 {
87                   // layer is kept alive by the layer following it
88                   if (i == j - 1)
89                     live->add (group_spanners_[j]);
90                   continue;
91                 }
92               else
93                 {
94                   group_spanners_[i]->warning (_f ("unknown remove-layer value `%s'",
95                                                    ly_symbol2string (this_layer).c_str ()));
96                   continue;
97                 }
98             }
99
100           SCM that_layer = group_spanners_[j]->get_property ("remove-layer");
101
102           if (scm_is_false (that_layer))
103             continue;
104           if (!scm_is_integer (this_layer))
105             {
106               // unset layers are kept alive by all but ignored layers
107               live->add (group_spanners_[j]);
108               continue;
109             }
110           // an explicit layer is only affected by explicit layers
111           if (!scm_is_integer (that_layer))
112             continue;
113           if (scm_is_true (scm_num_eq_p (that_layer, this_layer)))
114             live->add (group_spanners_[j]);
115           else if (scm_is_true (scm_less_p (that_layer, this_layer)))
116             dead->add (group_spanners_[j]);
117         }
118       if (!live->empty ())
119         group_spanners_[i]->set_object ("keep-alive-with", live_scm);
120       if (!dead->empty ())
121         group_spanners_[i]->set_object ("make-dead-when", dead_scm);
122     }
123 }
124
125
126 void
127 Keep_alive_together_engraver::boot ()
128 {
129   ADD_ACKNOWLEDGER (Keep_alive_together_engraver, hara_kiri_group_spanner);
130 }
131
132 ADD_TRANSLATOR (Keep_alive_together_engraver,
133                 /* doc */
134                 "This engraver collects all @code{Hara_kiri_group_spanner}s "
135                 "that are created in contexts at or below its own.  "
136                 "These spanners are then tied together so that one will "
137                 "be removed only if all are removed.  For example, "
138                 "if a @code{StaffGroup} uses this engraver, then the staves "
139                 "in the group will all be visible as long as there is a note "
140                 "in at least one of them.",
141
142                 /* create */
143                 "",
144
145                 /* read */
146                 "",
147
148                 /* write */
149                 ""
150                );