]> git.donarmstrong.com Git - lilypond.git/blob - lily/align-element.cc
release: 1.1.6
[lilypond.git] / lily / align-element.cc
1 /*
2   align-elem.cc -- implement Align_elem
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "align-element.hh"
10 #include "interval.hh"
11 #include "direction.hh"
12
13
14 struct Align_element_content {
15   Score_element * elem_l_;
16   int priority_i_;
17   
18   static int compare (Align_element_content const &h1, 
19                       Align_element_content const &h2) 
20   {
21     return h1.priority_i_ - h2.priority_i_;
22   }
23   Align_element_content (Score_element *elem_l, int p) 
24   {
25     priority_i_ = p;
26     elem_l_ = elem_l;
27   }
28   Align_element_content () {
29     elem_l_ = 0;
30     priority_i_ = 0;
31   }
32 };
33
34
35
36 void
37 Align_element::add_element (Score_element*el_l)
38 {
39   int p = priority_i_arr_.size ();
40   add_element_priority (el_l, p);
41 }
42
43 void
44 Align_element::add_element_priority (Score_element *el, int p)
45 {
46   assert (! contains_b (el));
47   elem_l_arr_.push (el);
48   priority_i_arr_.push (p);
49   add_dependency (el);
50 }
51
52 void
53 Align_element::do_substitute_dependency (Score_element*o,
54                                          Score_element*n)
55 {
56   int i;
57   while ((i = elem_l_arr_.find_i (o))>=0) 
58     if (n) 
59       elem_l_arr_[i] = n;
60     else
61       elem_l_arr_.del (i);
62
63   if (o == center_l_)
64     {
65       center_l_ = n;
66     }
67 }
68
69 /**
70   Align elements top to bottom. 
71   The first element has its top at y = 0.0 afterwards
72
73   TODO configurable, like Horizontal_align_item
74
75   TODO should parametrise in direction and coordinate.
76  */
77 void
78 Align_element::do_post_processing()
79 {
80   if (axis_ == Y_AXIS)
81     do_side_processing ();
82 }
83
84 void
85 Align_element::do_pre_processing ()
86 {
87   if (axis_ == X_AXIS)
88     do_side_processing ();
89 }
90
91 void
92 Align_element::do_side_processing ()
93 {
94   sort_elements ();
95   Array<Interval> dims;
96   
97   for (int i=0; i < elem_l_arr_.size(); i++) 
98     {
99       Interval y = elem_l_arr_[i]->extent(axis_) ;
100       if (y.empty_b())
101         y = Interval (0,0);
102         
103       dims.push (y);
104     }
105
106   Real where_f=0;
107   Real center_f = 0.0;
108   for (int i=0 ;  i < elem_l_arr_.size(); i++) 
109     {
110       Real dy = - stacking_dir_ * dims[i][-stacking_dir_];
111       if (i)
112         dy += stacking_dir_ * dims[i-1][stacking_dir_];
113
114       if (i)
115         {
116           dy = (dy >? threshold_interval_[SMALLER] )
117             <? threshold_interval_[BIGGER];
118         }
119
120       
121       if (!i && align_dir_ == LEFT)
122         center_f = where_f;
123       else if (align_dir_ == CENTER && elem_l_arr_[i] == center_l_)
124         center_f = where_f;
125
126       where_f += stacking_dir_ * dy;
127
128             
129       elem_l_arr_[i]->translate_axis (where_f, axis_);
130     }
131
132   if (align_dir_ == RIGHT)
133     center_f = where_f;
134   
135   if (center_f)
136     for  (int i=0 ;  i < elem_l_arr_.size(); i++)
137       elem_l_arr_[i]->translate_axis (- center_f, axis_);
138 }
139
140 Align_element::Align_element()
141 {
142   threshold_interval_ = Interval (0, Interval::infinity ());
143   transparent_b_ = true;
144   set_empty (true);
145   stacking_dir_ = DOWN;
146   align_dir_ = LEFT;
147   axis_ = X_AXIS;
148   center_l_ =0;
149 }
150
151
152 bool
153 Align_element::contains_b (Score_element const *e) const
154 {
155   return elem_l_arr_.find_l (e);
156 }
157
158
159
160
161 void
162 Align_element::sort_elements ()
163 {
164   Array<Align_element_content> content;
165   for  (int i =0; i < elem_l_arr_.size(); i++) 
166     content.push (Align_element_content (elem_l_arr_[i], priority_i_arr_[i]));
167   content.sort (Align_element_content::compare);
168   
169   elem_l_arr_.clear();
170   priority_i_arr_.clear();
171
172   for  (int i =0; i < content.size(); i++) 
173     {
174       elem_l_arr_.push (content[i].elem_l_);
175       priority_i_arr_.push (content[i].priority_i_);
176     }
177 }
178
179 void
180 Align_element::do_print () const
181 {
182 #if 0
183   DOUT << "contains: ";
184   for (int i=0 ;  i < item_l_arr_.size(); i++) 
185     DOUT << classname (item_l_arr_[i]) << ", ";
186 #endif
187 }