lilypond-1.1.55
[lilypond.git] / lily / align-element.cc
bloba92f7502b3946908aa7743a01d6a84094607001a
1 /*
2 align-elem.cc -- implement Align_elem
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
9 #include "align-element.hh"
10 #include "interval.hh"
11 #include "direction.hh"
12 #include "debug.hh"
13 #include "hash-table-iter.hh"
15 struct Align_element_content {
16 Graphical_element * elem_l_;
17 int priority_i_;
19 static int compare (Align_element_content const &h1,
20 Align_element_content const &h2)
22 return h1.priority_i_ - h2.priority_i_;
24 Align_element_content (Graphical_element *elem_l, int p)
26 priority_i_ = p;
27 elem_l_ = elem_l;
29 Align_element_content () {
30 elem_l_ = 0;
31 priority_i_ = 0;
37 void
38 Align_element::add_element (Score_element*el_l)
40 int p = elem_l_arr_.size ();
41 add_element_priority (el_l, p);
44 void
45 Align_element::add_element_priority (Score_element *el, int p)
47 assert (! contains_b (el));
48 Axis_group_element::add_element (el);
49 priority_i_hash_[el] = p;
50 add_dependency (el);
53 void
54 Align_element::do_substitute_element_pointer (Score_element*o,
55 Score_element*n)
57 Axis_group_element :: do_substitute_element_pointer (o,n);
58 if (o == center_l_)
60 center_l_ = n;
62 if (priority_i_hash_.elem_b (o))
64 priority_i_hash_[n] = priority_i_hash_[o];
66 Huh? It seems the old pointers are still used. Why?
68 // priority_i_hash_.remove (o);
72 void
73 Align_element::do_post_processing()
75 if (axis () == Y_AXIS)
76 do_side_processing ();
79 void
80 Align_element::do_pre_processing ()
82 if (axis () == X_AXIS)
83 do_side_processing ();
86 void
87 Align_element::do_side_processing ()
89 Array<Interval> dims;
91 Link_array<Score_element> elems;
92 for (int i=0; i < elem_l_arr_.size(); i++)
94 Interval y = elem_l_arr_[i]->extent(axis ());
95 if (!y.empty_b())
98 Score_element *e =dynamic_cast<Score_element*>(elem_l_arr_[i]);
100 // todo: fucks up if item both in Halign & Valign.
101 SCM min_dims = e->remove_elt_property (minimum_space_scm_sym);
102 if (min_dims != SCM_BOOL_F)
104 min_dims = SCM_CDR (min_dims);
105 y.unite (Interval (gh_scm2double (SCM_CAR (min_dims)),
106 gh_scm2double (SCM_CDR (min_dims))));
109 SCM extra_dims = e->remove_elt_property (extra_space_scm_sym);
110 if (extra_dims != SCM_BOOL_F)
112 extra_dims = SCM_CDR (extra_dims);
113 y[LEFT] += gh_scm2double (SCM_CAR (extra_dims));
114 y[RIGHT] += gh_scm2double (SCM_CDR (extra_dims));
117 elems.push (e);
118 dims.push (y);
122 Real where_f=0;
123 Real center_f = 0.0;
124 for (int i=0 ; i < elems.size(); i++)
126 Real dy = - stacking_dir_ * dims[i][-stacking_dir_];
127 if (i)
128 dy += stacking_dir_ * dims[i-1][stacking_dir_];
130 if (i)
132 dy = (dy >? threshold_interval_[SMALLER] )
133 <? threshold_interval_[BIGGER];
136 if (!i && align_dir_ == LEFT)
137 center_f = where_f;
138 else if (align_dir_ == CENTER && elems[i] == center_l_)
139 center_f = where_f;
141 where_f += stacking_dir_ * dy;
142 elems[i]->translate_axis (where_f, axis ());
145 if (dims.size ())
146 where_f += dims.top ()[stacking_dir_];
147 if (align_dir_ == RIGHT)
148 center_f = where_f;
149 else if (align_dir_ == CENTER && !center_l_)
150 center_f = where_f / 2;
152 if (center_f)
153 translate_axis ( - center_f, axis ());
155 dim_cache_[axis ()]->invalidate ();
158 Align_element::Align_element()
160 ordered_b_ = true;
161 threshold_interval_ = Interval (0, Interval::infinity ());
162 stacking_dir_ = DOWN;
163 align_dir_ = CENTER;
164 center_l_ =0;
165 priority_i_hash_.hash_func_ = pointer_hash;
168 Axis
169 Align_element::axis () const
171 return axes_[0];
174 void
175 Align_element::set_axis (Axis a)
177 set_axes (a,a);
181 bool
182 Align_element::contains_b (Score_element const *e) const
184 return elem_l_arr_.find_l (e);
187 void
188 Align_element::sort_elements ()
190 Array<Align_element_content> content;
191 for (int i =0; i < elem_l_arr_.size(); i++)
193 Score_element * e = dynamic_cast<Score_element*> (elem_l_arr_[i]);
194 assert (priority_i_hash_.elem_b (e));
195 int p = priority_i_hash_[e];
196 content.push (Align_element_content (e, p));
198 content.sort (Align_element_content::compare);
200 elem_l_arr_.clear();
201 priority_i_hash_.clear();
203 for (int i =0; i < content.size(); i++)
205 elem_l_arr_.push (content[i].elem_l_);
209 void
210 Align_element::do_print () const
212 #ifndef NPRINT
213 DOUT << "contains: ";
214 for (int i=0 ; i < elem_l_arr_.size(); i++)
215 DOUT << classname (elem_l_arr_[i]) << ", ";
216 #endif
219 Score_element*
220 Align_element::get_elt_by_priority (int p) const
222 for (Hash_table_iter<Score_element*, int> i(priority_i_hash_); i.ok (); i++)
224 if (i.val () == p)
225 return i.key();
227 return 0;
231 Align_element::get_priority (Score_element* e) const
233 if ( priority_i_hash_.elem_b (e))
234 return priority_i_hash_[e];
235 else
236 return elem_l_arr_.find_i (e);