+2005-05-09 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * input/regression/alignment-order.ly: new file.
+
+ * lily/vertical-align-engraver.cc (acknowledge_grob): read
+ alignAboveContext and alignBelowContext
+
2005-05-08 Han-Wen Nienhuys <hanwen@xs4all.nl>
* lily/pfb.cc (LY_DEFINE): add cast.
@itemize @bullet
+@item
+Newly created staves and lyric lines, can be put in any vertical order,
+by setting @code{alignBelowContext} or @code{alignAboveContext}
+properties in the newly created context. An example of the use of this
+is in @inputfileref{input/regression,alignment-order.ly}.
+
+This feature has been sponsored by Bertalan Fodor.
+
+
@item
Staves may be stopped and started halfway a line, e.g.
SPONSORS
+Bertalan Fodor
Jonathan Walther
Steve Doonan
Marcus Macauley
--- /dev/null
+\header {
+ texidoc = "Newly created contexts can be inserted
+anywhere in the vertical alignment. "
+}
+
+\version "2.5.23"
+
+\paper {
+ raggedright = ##t
+}
+
+\relative <<
+ \context Staff = "1" { c4 c s2 }
+ \context Staff = "2" { c c s2 }
+ \context Staff = "3" { c c s2 }
+ { \skip 2
+ <<
+ \lyrics {
+ \set alignBelowContext = #"1"
+ below8 first staff
+ }
+ \lyrics {
+ \set alignAboveContext = #"3"
+ above8 last staff
+ }
+ >> }
+>>
Accidental_entry entry;
entry.head_ = info.grob_;
- entry.origin_trans_ = dynamic_cast<Engraver *> (info.origin_trans_);
- entry.origin_ = info.origin_trans_->context ();
+ entry.origin_trans_ = dynamic_cast<Engraver *> (info.origin_translator ());
+ entry.origin_ = entry.origin_trans_->context ();
entry.melodic_ = note;
accidentals_.push (entry);
}
void
-Align_interface::add_element (Grob *me, Grob *s, SCM cb)
+Align_interface::add_element (Grob *me, Grob *element, SCM call_back)
{
- s->add_offset_callback (cb, Align_interface::axis (me));
- Axis_group_interface::add_element (me, s);
+ element->add_offset_callback (call_back, Align_interface::axis (me));
+ Axis_group_interface::add_element (me, element);
}
void
{
String type = ly_symbol2string (cdef->get_context_name ());
Object_key const *key = get_context_key (type, id);
- Context *new_group
+ Context *new_context
= cdef->instantiate (ops, key);
- new_group->id_string_ = id;
- add_context (new_group);
- apply_property_operations (new_group, ops);
+ new_context->id_string_ = id;
+ add_context (new_context);
+ apply_property_operations (new_context, ops);
- return new_group;
+ return new_context;
}
Object_key const *
{
Translator *t = unsmob_translator (scm_car (p));
Engraver *eng = dynamic_cast<Engraver *> (t);
- if (eng && eng != info.origin_trans_)
+ if (eng && eng != info.origin_translator ())
eng->acknowledge_grob (info);
}
}
/*
We only want to process a grob once.
*/
- if (gi.origin_trans_->context () != context ())
+ if (gi.context () != context ())
return;
if (scm_is_number (sz) && scm_to_double (sz))
return;
if (!scm_is_vector (doc_hash_table))
- doc_hash_table = scm_make_vector (scm_int2num (59), SCM_EOL);
+ doc_hash_table = scm_c_make_hash_table (59);
String s = String (" - ") + "LilyPond procedure: " + fname + " " + varlist
+ "\n" + doc;
*/
#include "grob-info.hh"
-
#include "grob.hh"
#include "music.hh"
#include "translator-group.hh"
#include "context.hh"
+
+Grob_info::Grob_info (Translator *t, Grob *g)
+{
+ origin_trans_ = t;
+ grob_ = g;
+}
+
Grob_info::Grob_info ()
{
grob_ = 0;
return r;
}
+
+Context*
+Grob_info::context () const
+{
+ return origin_trans_->context ();
+}
+
/*
Data container for broadcasts.
*/
-struct Grob_info
+class Grob_info
{
Translator *origin_trans_;
friend class Engraver;
- Grob *grob_;
-
public:
+ Grob *grob_;
+ Context *context () const;
+ Translator *origin_translator () const { return origin_trans_; }
Music *music_cause ();
Link_array<Context> origin_contexts (Translator *) const;
+ Grob_info (Translator *, Grob *);
Grob_info ();
};
}
else
{
- Context * d =
- dynamic_cast<Context *> (inf.origin_trans_);
-
- if (!d)
- d = dynamic_cast<Context *> (inf.origin_trans_->context ());
-
+ Context * d = inf.context ();
SCM proc = o->get_property ("procedure");
scm_call_3 (proc,
inf.grob_->self_scm (),
Object_key const *key2 = context ()->get_grob_key ("PaperColumn");
set_columns (new Paper_column (nmp, key1), new Paper_column (pc, key2));
- Grob_info i1;
- i1.grob_ = command_column_;
- i1.origin_trans_ = this;
-
+ Grob_info i1 (this, command_column_);
announce_grob (i1);
- Grob_info i2;
- i2.grob_ = musical_column_;
- i2.origin_trans_ = this;
-
+ Grob_info i2 (this, musical_column_);
announce_grob (i2);
}
}
{
Spanner *valign_;
bool qualifies (Grob_info) const;
-
+ SCM id_to_group_hashtab_;
+
public:
TRANSLATOR_DECLARATIONS (Vertical_align_engraver);
protected:
+ virtual void derived_mark () const;
virtual void acknowledge_grob (Grob_info);
virtual void process_music ();
virtual void finalize ();
+ virtual void initialize ();
};
+
+ADD_TRANSLATOR (Vertical_align_engraver,
+ "Catch groups (staffs, lyrics lines, etc.) and stack "
+ "them vertically.",
+ /* creats*/ "VerticalAlignment",
+ /* accepts */ "",
+ /* acks */ "axis-group-interface",
+ /* reads */ "",
+ /* write */ "");
+
+
Vertical_align_engraver::Vertical_align_engraver ()
{
valign_ = 0;
+ id_to_group_hashtab_ = SCM_EOL;
+}
+
+void
+Vertical_align_engraver::derived_mark () const
+{
+ scm_gc_mark (id_to_group_hashtab_);
}
+void
+Vertical_align_engraver::initialize ()
+{
+ id_to_group_hashtab_ = scm_c_make_hash_table (11);
+}
+
+
void
Vertical_align_engraver::process_music ()
{
{
if (qualifies (i))
{
- Align_interface::add_element (valign_, i.grob_, get_property ("verticalAlignmentChildCallback"));
+ String id = i.context ()->id_string ();
+
+ scm_hash_set_x (id_to_group_hashtab_, scm_makfrom0str (id.to_str0 ()),
+ i.grob_->self_scm ());
+
+
+ SCM before_id = i.context ()->get_property ("alignAboveContext");
+ SCM after_id = i.context ()->get_property ("alignBelowContext");
+
+ SCM before = scm_hash_ref (id_to_group_hashtab_, before_id, SCM_BOOL_F);
+ SCM after = scm_hash_ref (id_to_group_hashtab_, after_id, SCM_BOOL_F);
+
+
+ Align_interface::add_element (valign_, i.grob_,
+ get_property ("verticalAlignmentChildCallback"));
+
+ if (unsmob_grob (before) || unsmob_grob (after))
+ {
+ SCM elts = valign_->get_property ("elements");
+ SCM new_order = scm_cdr (elts);
+ SCM *current = &new_order;
+
+ for (SCM s = new_order; scm_is_pair (s); s = scm_cdr (s))
+ {
+ if (scm_car (s) == after)
+ {
+ *current = scm_cons (i.grob_->self_scm(), s);
+ break;
+ }
+ else if (scm_car (s) == before)
+ {
+ scm_set_cdr_x (s, scm_cons (i.grob_->self_scm (),
+ scm_cdr (s)));
+ break;
+ }
+
+ current = SCM_CDRLOC (s);
+ }
+
+ valign_->set_property ("elements", new_order);
+ }
}
}
-
-ADD_TRANSLATOR (Vertical_align_engraver,
- /* descr */ "Catch Vertical axis groups and stack them.",
- /* creats*/ "VerticalAlignment",
- /* accepts */ "",
- /* acks */ "axis-group-interface",
- /* reads */ "",
- /* write */ "");
(apply translator-property-description x))
`(
(aDueText ,string? "Text to print at a unisono passage.")
+ (alignBelowContext ,string? "Where to insert newly created context in vertiical alignment.")
+ (alignAboveContext ,string? "Where to insert newly created context in vertiical alignment.")
(alignBassFigureAccidentals ,boolean?
"If true, then the accidentals are aligned in bass figure context.")
(debug-enable 'backtrace)
(read-enable 'positions)))
-
-
;; initialize defaults.
(ly:set-option 'command-line-settings
'((resolution . 90)