]> git.donarmstrong.com Git - lilypond.git/blob - lily/staff-margin-engraver.cc
release: 1.3.38
[lilypond.git] / lily / staff-margin-engraver.cc
1 /*
2   staff-margin-engraver.cc -- implement Staff_margin_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1998--2000 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "translator.hh"
10 #include "engraver.hh"
11 #include "bar.hh"
12 #include "dimension-cache.hh"
13 #include "directional-element-interface.hh"
14 #include "timing-translator.hh"
15 #include "text-item.hh"
16 #include "side-position-interface.hh"
17 #include "bar-script-engraver.hh"
18 #include "staff-symbol-referencer.hh"
19 #include "staff-symbol.hh"
20
21 /*
22   TODO:
23
24     * align over full score
25     * text aligment: left, centred, right
26     * merge with/derive from/add functionality to Bar_script_engraver
27  */
28
29 /**
30    Hang on left edge of staff to provide suppor for simple items.
31  */
32 class Left_edge_item : public Item
33 {
34 public:
35   VIRTUAL_COPY_CONS (Score_element);
36 };
37
38 /**
39   put (instrument) text to left of line
40  */
41 class Staff_margin_engraver : public Engraver
42 {
43 public:
44   VIRTUAL_COPY_CONS (Translator);
45   Staff_margin_engraver ();
46
47 protected:
48   virtual void do_pre_move_processing ();
49   virtual void acknowledge_element (Score_element_info);
50
51 private:
52   String type_;
53   Text_item* text_p_;
54   Left_edge_item* left_edge_p_;
55   void create_text (SCM);
56 };
57
58 ADD_THIS_TRANSLATOR (Staff_margin_engraver);
59
60
61 Staff_margin_engraver::Staff_margin_engraver ()
62 {
63   type_ = "margin";
64   text_p_ = 0;
65   left_edge_p_ = 0;
66 }
67
68 void
69 Staff_margin_engraver::acknowledge_element (Score_element_info info)
70 {
71   SCM s = get_property ("instrument");
72   
73   if (now_mom () > Moment (0))
74     s = get_property ("instr");
75
76   //s = ly_str02scm ("HALLO");
77   
78   if (dynamic_cast<Bar*> (info.elem_l_) && gh_string_p (s))
79     create_text (s);
80 }
81
82 void
83 Staff_margin_engraver::create_text (SCM text)
84 {
85   if (!text_p_)
86     {
87       assert (!left_edge_p_);
88       Left_edge_item* l = new Left_edge_item;
89       
90       l->set_elt_property ("breakable", SCM_BOOL_T);
91       l->set_elt_property ("break-aligned", SCM_BOOL_T);
92
93       announce_element (Score_element_info (l, 0));
94
95       Staff_symbol_referencer_interface sl (l);
96       sl.set_interface ();
97       left_edge_p_ = l;
98       
99       Text_item* t = new Text_item;
100
101       t->set_elt_property ("self-alignment-Y", gh_int2scm (0));
102       t->add_offset_callback (Side_position_interface::aligned_on_self, Y_AXIS);
103
104       t->set_parent (l, X_AXIS);
105       t->set_parent (l, Y_AXIS);
106
107       // 'just to be sure': see Clef_item::do_add_processing
108       l->add_dependency (t);
109
110
111       /*
112         Hmm.
113         In almost every score that uses "instrument" and "instr"
114         we need two different paddings.
115         Let's try one of those first:
116         instrumentScriptPadding/instrScriptPadding
117       */
118       SCM s = get_property (String (now_mom () ? "instr" : "instrument")
119                             + "ScriptPadding");
120       if (!gh_number_p (s))
121         s = get_property (type_ + "ScriptPadding");
122
123       Real padding = 0;
124       if (gh_number_p (s))
125         padding = gh_scm2double (s);
126   
127       s = get_property (type_ + "ScriptTextStyle");
128       if (gh_string_p (s))
129         t->set_elt_property ("style", s);
130
131       s = get_property (type_ + "ScriptHorizontalAlignment");
132       /*
133         Allow centred,
134        */
135       if (gh_number_p (s) && !gh_scm2int (s))
136         {
137           t->set_elt_property ("self-alignment-X", gh_int2scm (0));
138           t->add_offset_callback (Side_position_interface::aligned_on_self, X_AXIS);
139           /*
140 %           Centred is still broken, it always requires proper padding.
141            */
142           padding *= -1;
143           if (padding)
144             t->translate_axis (padding, X_AXIS);
145         }
146       /*
147         left or right alignment.
148       */
149       else
150         {
151           side_position (t).set_axis (X_AXIS);
152           side_position (t).add_support (l);
153       
154           Direction d;
155           if (isdir_b (s))
156             d = to_dir (s);
157           /*
158             By default, align at left edge of Left_edge_item,
159             (which makes text right-aligned)
160             so that we don't collide with staff.
161           */
162           else
163             d = LEFT;
164           
165           directional_element (t).set (d);
166           padding *= -d;
167           if (padding)
168             t->set_elt_property ("padding", gh_double2scm (padding));
169         }
170
171
172       announce_element (Score_element_info (t, 0));
173       text_p_ = t;
174     }
175
176
177   text_p_->set_elt_property ("text", text);
178 }
179
180 void
181 Staff_margin_engraver::do_pre_move_processing ()
182 {
183   if (text_p_)
184     {
185       /*
186         Let's not allow user settings for visibility function (yet).
187         Although end-of-line would work, to some extent, we should
188         make a properly ordered Right_edge_item, if that need arises.
189        */
190       text_p_->set_elt_property("visibility-lambda",
191                                 scm_eval (ly_symbol2scm ("begin-of-line-visible")));
192       typeset_element (text_p_);
193       text_p_ = 0;
194       assert (left_edge_p_);
195       typeset_element (left_edge_p_);
196       left_edge_p_ = 0;
197     }
198 }