]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
release: 1.2.4
[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_sym) != SCM_BOOL_F;
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_scm_sym);
86   if (vis != SCM_BOOL_F)
87     {
88       SCM args = scm_listify (gh_int2scm (break_status_dir ()), SCM_UNDEFINED);
89       SCM result = gh_apply ( SCM_CDR(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_sym, 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 Item*
122 Item::find_prebroken_piece (Line_of_score*l) const
123 {
124   if (line_l() == l) 
125     return (Item*)(this);
126   else if (broken_to_drul_[LEFT] && broken_to_drul_[LEFT]->line_l() == l)
127     return broken_to_drul_[LEFT];
128   else if (broken_to_drul_[RIGHT] && broken_to_drul_[RIGHT]->line_l() == l)
129     return broken_to_drul_[RIGHT];
130
131   return 0;
132 }
133
134 Item*
135 Item::find_prebroken_piece (Direction d) const
136 {
137   if (!d)
138     return (Item *) (this);     // ugh
139   else
140     return dynamic_cast<Item*> (broken_to_drul_[d]);
141 }
142
143 void
144 Item::handle_prebroken_dependencies()
145 {
146   if (original_l_)
147     Score_element::handle_prebroken_dependencies();
148 }
149
150 bool
151 Item::broken_original_b () const
152 {
153   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
154 }
155
156 int
157 Item::left_right_compare(Item const *l, Item const *r)
158 {
159   Paper_column *p1 = l->column_l ();
160   Paper_column* p2 = r->column_l ();
161   return p1->rank_i () - p2->rank_i ();
162 }
163
164 Paper_column *
165 Item::column_l () const
166 {
167   return dynamic_cast<Item*> (parent_l (X_AXIS))->column_l ();
168 }
169
170 Item::Item (Item const &s)
171   : Score_element (s)
172 {
173   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
174 }
175
176
177 void
178 Item::handle_prebroken_dependents ()
179 {
180   Item * parent =  dynamic_cast<Item*> (parent_l (X_AXIS));
181   if (breakable_b () && parent)
182     {
183        if(!(broken_to_drul_[LEFT] || broken_to_drul_[RIGHT]))
184         do_break ();
185
186       Direction d = LEFT;
187       do
188         {
189           Item * broken_self = find_prebroken_piece (d);
190           Item * broken_parent = parent->find_prebroken_piece (d);
191
192           broken_self->set_parent (broken_parent, X_AXIS);
193
194           /*
195             ugh. Should do this is after breaking?
196            */
197           if (!broken_self->parent_l (Y_AXIS))
198             {
199               Score_element * yparent =dynamic_cast<Score_element*>(parent_l (Y_AXIS));
200               Item *yparenti = dynamic_cast<Item*> (yparent);
201               Item *broken_yparent = yparenti ?
202                 yparenti->find_prebroken_piece (d) : 0;
203               
204               if (!yparent)
205                 programming_error ("Vertical refpoint lost!");
206               else if (yparenti)
207                 {
208                   broken_self->set_parent (broken_yparent, Y_AXIS);
209                 }
210             }
211         }
212       while ((flip (&d))!=LEFT);
213     }
214 }
215
216 Direction
217 Item::break_status_dir () const
218 {
219   if (original_l_)
220     {
221       Item * i = dynamic_cast<Item*> (original_l_);
222
223       return (i->broken_to_drul_[LEFT] == this) ? LEFT : RIGHT;
224     }
225   else
226     return CENTER;
227 }