lilypond-1.4.1
[lilypond.git] / lily / key-engraver.cc
blob8dc62ea994507c898853b3cdf4cb0f76c75d568d
1 /*
2 key-engraver.cc -- implement Key_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
9 #include "key-item.hh"
10 #include "command-request.hh"
11 #include "musical-request.hh"
12 #include "item.hh"
13 #include "bar.hh"
14 #include "timing-translator.hh"
15 #include "staff-symbol-referencer.hh"
16 #include "translator-group.hh"
17 #include "engraver.hh"
18 #include "pitch.hh"
19 #include "protected-scm.hh"
20 #include "clef.hh"
22 /**
23 Make the key signature.
25 class Key_engraver : public Engraver
27 void create_key (bool);
28 void read_req (Key_change_req const * r);
30 public:
31 Key_engraver ();
33 VIRTUAL_COPY_CONS (Translator);
35 Key_change_req * keyreq_l_;
36 Item * item_p_;
37 Protected_scm old_accs_; // ugh. -> property
39 protected:
40 virtual void initialize ();
41 virtual void finalize ();
42 virtual bool try_music (Music *req_l);
43 virtual void stop_translation_timestep ();
44 virtual void start_translation_timestep ();
45 virtual void create_grobs ();
46 virtual void acknowledge_grob (Grob_info);
50 void
51 Key_engraver::finalize ()
53 old_accs_ = SCM_EOL; // unprotect can not be called from dtor.
56 Key_engraver::Key_engraver ()
58 keyreq_l_ = 0;
59 item_p_ = 0;
62 void
63 Key_engraver::create_key (bool def)
65 if (!item_p_)
67 item_p_ = new Item (get_property ("KeySignature"));
69 item_p_->set_grob_property ("c0-position", gh_int2scm (0));
71 // todo: put this in basic props.
72 item_p_->set_grob_property ("old-accidentals", old_accs_);
73 item_p_->set_grob_property ("new-accidentals", get_property ("keySignature"));
75 Staff_symbol_referencer::set_interface (item_p_);
76 Key_item::set_interface (item_p_);
79 announce_grob (item_p_,keyreq_l_);
83 if (!def)
85 SCM vis = get_property ("explicitKeySignatureVisibility");
86 if (gh_procedure_p (vis))
87 item_p_->set_grob_property ("visibility-lambda",vis);
92 bool
93 Key_engraver::try_music (Music * req_l)
95 if (Key_change_req *kc = dynamic_cast <Key_change_req *> (req_l))
97 if (keyreq_l_ && !keyreq_l_->equal_b (kc))
99 kc->origin ()->warning (_ ("Conflicting key signatures found."));
100 keyreq_l_->origin ()->warning (_ ("This was the other key definition."));
101 return false;
103 keyreq_l_ = kc;
104 read_req (keyreq_l_);
106 return true;
108 return false;
111 void
112 Key_engraver::acknowledge_grob (Grob_info info)
114 if (Clef::has_interface (info.elem_l_))
116 SCM c = get_property ("createKeyOnClefChange");
117 if (to_boolean (c))
119 create_key (false);
122 else if (Bar::has_interface (info.elem_l_)
123 && gh_pair_p (get_property ("keySignature")))
125 create_key (true);
130 void
131 Key_engraver::create_grobs ()
133 if (keyreq_l_ || old_accs_ != get_property ("keySignature"))
135 create_key (false);
139 void
140 Key_engraver::stop_translation_timestep ()
142 if (item_p_)
144 typeset_grob (item_p_);
145 item_p_ = 0;
149 void
150 Key_engraver::read_req (Key_change_req const * r)
152 SCM p = r->get_mus_property ("pitch-alist");
153 if (!gh_pair_p (p))
154 return;
156 SCM n = scm_list_copy (p);
157 SCM accs = SCM_EOL;
158 for (SCM s = get_property ("keyAccidentalOrder");
159 gh_pair_p (s); s = gh_cdr (s))
161 if (gh_pair_p (scm_member (gh_car (s), n)))
163 accs = gh_cons (gh_car (s), accs);
164 n = scm_delete_x (gh_car (s), n);
167 for (SCM s = n ; gh_pair_p (s); s = gh_cdr (s))
168 if (gh_scm2int (gh_cdar (s)))
169 accs = gh_cons (gh_car (s), accs);
171 old_accs_ = get_property ("keySignature");
172 daddy_trans_l_->set_property ("keySignature", accs);
175 void
176 Key_engraver::start_translation_timestep ()
178 keyreq_l_ = 0;
179 old_accs_ = get_property ("keySignature");
182 void
183 Key_engraver::initialize ()
185 daddy_trans_l_->set_property ("keySignature", SCM_EOL);
186 old_accs_ = SCM_EOL;
190 ADD_THIS_TRANSLATOR (Key_engraver);