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>
9 #include "align-element.hh"
10 #include "interval.hh"
11 #include "direction.hh"
13 #include "hash-table-iter.hh"
14 #include "dimension-cache.hh"
16 struct Align_element_content {
17 Graphical_element * elem_l_;
20 static int compare (Align_element_content const &h1,
21 Align_element_content const &h2)
23 return h1.priority_i_ - h2.priority_i_;
25 Align_element_content (Graphical_element *elem_l, int p)
30 Align_element_content () {
39 Align_element::add_element (Score_element*el_l)
41 int p = elem_l_arr_.size ();
42 add_element_priority (el_l, p);
46 Align_element::add_element_priority (Score_element *el, int p)
48 assert (! contains_b (el));
49 Axis_group_element::add_element (el);
50 priority_i_hash_[el] = p;
55 Align_element::do_substitute_element_pointer (Score_element*o,
58 Axis_group_element :: do_substitute_element_pointer (o,n);
63 if (priority_i_hash_.elem_b (o))
65 priority_i_hash_[n] = priority_i_hash_[o];
67 Huh? It seems the old pointers are still used. Why?
69 // priority_i_hash_.remove (o);
74 Align_element::do_post_processing()
76 if (axis () == Y_AXIS)
77 do_side_processing ();
81 Align_element::do_pre_processing ()
83 if (axis () == X_AXIS)
84 do_side_processing ();
88 Align_element::do_side_processing ()
92 Link_array<Score_element> elems;
93 for (int i=0; i < elem_l_arr_.size(); i++)
95 Interval y = elem_l_arr_[i]->extent(axis ());
99 Score_element *e =dynamic_cast<Score_element*>(elem_l_arr_[i]);
101 // todo: fucks up if item both in Halign & Valign.
102 SCM min_dims = e->remove_elt_property (minimum_space_scm_sym);
103 if (min_dims != SCM_BOOL_F)
105 min_dims = SCM_CDR (min_dims);
106 y.unite (Interval (gh_scm2double (SCM_CAR (min_dims)),
107 gh_scm2double (SCM_CDR (min_dims))));
110 SCM extra_dims = e->remove_elt_property (extra_space_scm_sym);
111 if (extra_dims != SCM_BOOL_F)
113 extra_dims = SCM_CDR (extra_dims);
114 y[LEFT] += gh_scm2double (SCM_CAR (extra_dims));
115 y[RIGHT] += gh_scm2double (SCM_CDR (extra_dims));
125 for (int i=0 ; i < elems.size(); i++)
127 Real dy = - stacking_dir_ * dims[i][-stacking_dir_];
129 dy += stacking_dir_ * dims[i-1][stacking_dir_];
133 dy = (dy >? threshold_interval_[SMALLER] )
134 <? threshold_interval_[BIGGER];
137 if (!i && align_dir_ == LEFT)
139 else if (align_dir_ == CENTER && elems[i] == center_l_)
142 where_f += stacking_dir_ * dy;
143 elems[i]->translate_axis (where_f, axis ());
147 where_f += dims.top ()[stacking_dir_];
148 if (align_dir_ == RIGHT)
150 else if (align_dir_ == CENTER && !center_l_)
151 center_f = where_f / 2;
154 translate_axis ( - center_f, axis ());
156 dim_cache_[axis ()]->invalidate ();
159 Align_element::Align_element()
162 threshold_interval_ = Interval (0, Interval::infinity ());
163 stacking_dir_ = DOWN;
166 priority_i_hash_.hash_func_ = pointer_hash;
170 Align_element::axis () const
176 Align_element::set_axis (Axis a)
183 Align_element::contains_b (Score_element const *e) const
185 return elem_l_arr_.find_l (e);
189 Align_element::sort_elements ()
191 Array<Align_element_content> content;
192 for (int i =0; i < elem_l_arr_.size(); i++)
194 Score_element * e = dynamic_cast<Score_element*> (elem_l_arr_[i]);
195 assert (priority_i_hash_.elem_b (e));
196 int p = priority_i_hash_[e];
197 content.push (Align_element_content (e, p));
199 content.sort (Align_element_content::compare);
202 priority_i_hash_.clear();
204 for (int i =0; i < content.size(); i++)
206 elem_l_arr_.push (content[i].elem_l_);
211 Align_element::do_print () const
214 DOUT << "contains: ";
215 for (int i=0 ; i < elem_l_arr_.size(); i++)
216 DOUT << classname (elem_l_arr_[i]) << ", ";
221 Align_element::get_elt_by_priority (int p) const
223 for (Hash_table_iter<Score_element*, int> i(priority_i_hash_); i.ok (); i++)
232 Align_element::get_priority (Score_element* e) const
234 if ( priority_i_hash_.elem_b (e))
235 return priority_i_hash_[e];
237 return elem_l_arr_.find_i (e);