/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 2010 Joe Neeman <joeneeman@gmail.com>
+ Copyright (C) 2010--2015 Joe Neeman <joeneeman@gmail.com>
LilyPond is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "engraver.hh"
#include "grob.hh"
#include "grob-array.hh"
+#include "international.hh"
#include "translator.icc"
class Keep_alive_together_engraver: public Engraver
{
- vector<Grob*> group_spanners_;
+ vector<Grob *> group_spanners_;
public:
TRANSLATOR_DECLARATIONS (Keep_alive_together_engraver);
- DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
+ void acknowledge_hara_kiri_group_spanner (Grob_info);
virtual void finalize ();
};
-Keep_alive_together_engraver::Keep_alive_together_engraver ()
+Keep_alive_together_engraver::Keep_alive_together_engraver (Context *c)
+ : Engraver (c)
{
}
{
for (vsize i = 0; i < group_spanners_.size (); ++i)
{
- SCM grob_array_scm = Grob_array::make_array ();
- Grob_array *ga = unsmob_grob_array (grob_array_scm);
-
- // It would make Hara_kiri_group_spanner::request_suicide a _little_
- // faster if we removed each grob from its own array. It seems
- // unnecessary for now, though.
- ga->set_array (group_spanners_);
- group_spanners_[i]->set_object ("keep-alive-with", grob_array_scm);
+ SCM this_layer = group_spanners_[i]->get_property ("remove-layer");
+ if (scm_is_false (this_layer))
+ continue;
+
+ SCM live_scm = Grob_array::make_array ();
+ Grob_array *live = unsmob<Grob_array> (live_scm);
+ SCM dead_scm = Grob_array::make_array ();
+ Grob_array *dead = unsmob<Grob_array> (dead_scm);
+
+ for (vsize j = 0; j < group_spanners_.size (); ++j)
+ {
+ if (i == j)
+ continue;
+
+ if (scm_is_symbol (this_layer))
+ {
+ if (scm_is_eq (this_layer, ly_symbol2scm ("any")))
+ {
+ // layer is kept alive by any other layer
+ live->add (group_spanners_[j]);
+ continue;
+ }
+ else if (scm_is_eq (this_layer, ly_symbol2scm ("above")))
+ {
+ // layer is kept alive by the layer preceding it
+ if (i == j + 1)
+ live->add (group_spanners_[j]);
+ continue;
+ }
+ else if (scm_is_eq (this_layer, ly_symbol2scm ("below")))
+ {
+ // layer is kept alive by the layer following it
+ if (i == j - 1)
+ live->add (group_spanners_[j]);
+ continue;
+ }
+ else
+ {
+ group_spanners_[i]->warning (_f ("unknown remove-layer value `%s'",
+ ly_symbol2string (this_layer).c_str ()));
+ continue;
+ }
+ }
+
+ SCM that_layer = group_spanners_[j]->get_property ("remove-layer");
+
+ if (scm_is_false (that_layer))
+ continue;
+ if (!scm_is_integer (this_layer))
+ {
+ // unset layers are kept alive by all but ignored layers
+ live->add (group_spanners_[j]);
+ continue;
+ }
+ // an explicit layer is only affected by explicit layers
+ if (!scm_is_integer (that_layer))
+ continue;
+ if (scm_is_true (scm_num_eq_p (that_layer, this_layer)))
+ live->add (group_spanners_[j]);
+ else if (scm_is_true (scm_less_p (that_layer, this_layer)))
+ dead->add (group_spanners_[j]);
+ }
+ if (!live->empty ())
+ group_spanners_[i]->set_object ("keep-alive-with", live_scm);
+ if (!dead->empty ())
+ group_spanners_[i]->set_object ("make-dead-when", dead_scm);
}
}
-ADD_ACKNOWLEDGER (Keep_alive_together_engraver, hara_kiri_group_spanner);
+
+void
+Keep_alive_together_engraver::boot ()
+{
+ ADD_ACKNOWLEDGER (Keep_alive_together_engraver, hara_kiri_group_spanner);
+}
ADD_TRANSLATOR (Keep_alive_together_engraver,
- /* doc */
- "This engraver collects all @code{Hara_kiri_group_spanner}s "
- "that are created in contexts at or below its own. "
- "These spanners are then tied together so that one will "
- "be removed only if all are removed. For example, "
- "if a @code{StaffGroup} uses this engraver, then the staves "
- "in the group will all be visible as long as there is a note "
- "in at least one of them.",
-
- /* create */
- "",
-
- /* read */
- "",
-
- /* write */
- ""
- );
+ /* doc */
+ "This engraver collects all @code{Hara_kiri_group_spanner}s "
+ "that are created in contexts at or below its own. "
+ "These spanners are then tied together so that one will "
+ "be removed only if all are removed. For example, "
+ "if a @code{StaffGroup} uses this engraver, then the staves "
+ "in the group will all be visible as long as there is a note "
+ "in at least one of them.",
+
+ /* create */
+ "",
+
+ /* read */
+ "",
+
+ /* write */
+ ""
+ );