]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
patch::: 1.3.1.hwn1
[lilypond.git] / lily / item.cc
1 /*
2   item.cc -- implement Item
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include "dimension-cache.hh"
9
10 #include "paper-score.hh"
11 #include "debug.hh"
12 #include "item.hh"
13 #include "paper-column.hh"
14 #include "spanner.hh"
15 #include "lily-guile.hh"
16
17 Item::Item ()
18 {
19   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT]=0;
20 }
21
22 bool
23 Item::breakable_b () const
24 {
25   if (original_l_ )
26     return false;
27   
28   Item * i  =dynamic_cast<Item*> (parent_l (X_AXIS));
29   return (i) ?  i->breakable_b () : get_elt_property( "breakable") != SCM_UNDEFINED;
30 }
31
32 void
33 Item::do_print() const
34 {
35 }
36
37
38 Real 
39 Item::hpos_f() const
40 {
41   return relative_coordinate (0, X_AXIS);
42 }
43
44 Line_of_score *
45 Item::line_l() const
46 {
47   Graphical_element *g = parent_l (X_AXIS);
48   if (!g)
49     return 0;
50   return dynamic_cast<Score_element *> (g)-> line_l ();
51 }
52
53
54 void
55 Item::copy_breakable_items()
56 {
57   if (broken_to_drul_[LEFT] || broken_to_drul_[RIGHT]
58       || !breakable_b ())
59     return ;
60
61   Drul_array<Item *> new_copies;
62   Direction  i=LEFT;
63   do 
64     {
65       Score_element * dolly = clone();
66       Item * item_p = dynamic_cast<Item*>(dolly);
67       pscore_l_->typeset_element (item_p);
68       new_copies[i] =item_p;
69     }
70   while (flip(&i) != LEFT);
71   broken_to_drul_= new_copies;
72
73   do 
74     {
75        broken_to_drul_[i]->handle_prebroken_dependencies();
76        broken_to_drul_[i]->try_visibility_lambda();
77     }
78   while (flip(&i) != LEFT);
79   try_visibility_lambda ();
80 }
81
82 void
83 Item::try_visibility_lambda ()
84 {
85   SCM vis = remove_elt_property ("visibility-lambda");
86   if (vis != SCM_UNDEFINED)
87     {
88       SCM args = scm_listify (gh_int2scm (break_status_dir ()), SCM_UNDEFINED);
89       SCM result = gh_apply (vis, args);
90       int trans = gh_scm2bool (gh_car (result));
91       int empty = gh_scm2bool (gh_cdr (result));
92
93       if (empty)
94         set_empty (true, X_AXIS, Y_AXIS);
95       if (trans)
96         set_elt_property ("transparent", SCM_BOOL_T);
97     }
98 }
99
100 void
101 Item::do_break ()
102 {
103   copy_breakable_items();
104   handle_prebroken_dependencies();
105   
106   /*
107     Otherwise the broken items won't be pre_process()'ed.
108   */
109   add_dependency (broken_to_drul_[LEFT]);
110   add_dependency (broken_to_drul_[RIGHT]);
111 }
112
113 void
114 Item::do_breakable_col_processing()
115 {
116   if (breakable_b ())
117     do_break ();
118   else
119     try_visibility_lambda ();
120 }
121
122 Score_element*
123 Item::find_broken_piece (Line_of_score*l) const
124 {
125   if (line_l() == l) 
126     return (Item*)(this);
127   else if (broken_to_drul_[LEFT] && broken_to_drul_[LEFT]->line_l() == l)
128     return broken_to_drul_[LEFT];
129   else if (broken_to_drul_[RIGHT] && broken_to_drul_[RIGHT]->line_l() == l)
130     return broken_to_drul_[RIGHT];
131
132   return 0;
133 }
134
135 Item*
136 Item::find_broken_piece (Direction d) const
137 {
138   if (!d)
139     return (Item *) (this);     // ugh
140   else
141     return dynamic_cast<Item*> (broken_to_drul_[d]);
142 }
143
144 void
145 Item::handle_prebroken_dependencies()
146 {
147   if (original_l_)
148     Score_element::handle_prebroken_dependencies();
149 }
150
151 bool
152 Item::broken_original_b () const
153 {
154   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
155 }
156
157 int
158 Item::left_right_compare(Item const *l, Item const *r)
159 {
160   Paper_column *p1 = l->column_l ();
161   Paper_column* p2 = r->column_l ();
162   return p1->rank_i () - p2->rank_i ();
163 }
164
165 Paper_column *
166 Item::column_l () const
167 {
168   return dynamic_cast<Item*> (parent_l (X_AXIS))->column_l ();
169 }
170
171 Item::Item (Item const &s)
172   : Score_element (s)
173 {
174   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
175 }
176
177
178 void
179 Item::handle_prebroken_dependents ()
180 {
181   Item * parent =  dynamic_cast<Item*> (parent_l (X_AXIS));
182   if (breakable_b () && parent)
183     {
184        if(!(broken_to_drul_[LEFT] || broken_to_drul_[RIGHT]))
185         do_break ();
186
187       Direction d = LEFT;
188       do
189         {
190           Item * broken_self = find_broken_piece (d);
191           Item * broken_parent = parent->find_broken_piece (d);
192
193           broken_self->set_parent (broken_parent, X_AXIS);
194
195           /*
196             ugh. Should do this is after breaking?
197            */
198           if (!broken_self->parent_l (Y_AXIS))
199             {
200               Score_element * yparent =dynamic_cast<Score_element*>(parent_l (Y_AXIS));
201               Item *yparenti = dynamic_cast<Item*> (yparent);
202               Item *broken_yparent = yparenti ?
203                 yparenti->find_broken_piece (d) : 0;
204               
205               if (!yparent)
206                 programming_error ("Vertical refpoint lost!");
207               else if (yparenti)
208                 {
209                   broken_self->set_parent (broken_yparent, Y_AXIS);
210                 }
211             }
212         }
213       while ((flip (&d))!=LEFT);
214     }
215 }
216
217 Direction
218 Item::break_status_dir () const
219 {
220   if (original_l_)
221     {
222       Item * i = dynamic_cast<Item*> (original_l_);
223
224       return (i->broken_to_drul_[LEFT] == this) ? LEFT : RIGHT;
225     }
226   else
227     return CENTER;
228 }
229
230