]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
''
[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--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
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 #include "system.hh"
17 #include "group-interface.hh"
18
19 Item::Item (SCM s)
20   : Grob (s)
21 {
22   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT]=0;
23   Group_interface::add_thing (this, ly_symbol2scm ("interfaces"), ly_symbol2scm ("item-interface"));
24                      
25 }
26
27 /**
28    Item copy ctor.  Copy nothing: everything should be a elt property
29    or a special purpose pointer (such as broken_to_drul_[]) */
30 Item::Item (Item const &s)
31   : Grob (s)
32 {
33   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
34 }
35
36
37 bool
38 Item::breakable_b (Grob*me) 
39 {
40   if (me->original_l_)
41     return false;
42
43   if (!dynamic_cast<Item*> (me))
44     me->programming_error ("only items can be breakable.");
45   
46   Item * i  =dynamic_cast<Item*> (me->get_parent (X_AXIS));
47   return (i) ?  Item::breakable_b (i) : to_boolean (me->get_grob_property ("breakable"));
48 }
49
50 Paper_column *
51 Item::column_l () const
52 {
53   Item *parent = dynamic_cast<Item*> (get_parent (X_AXIS));
54   return parent ? parent->column_l () : 0;
55 }
56
57 System *
58 Item::line_l () const
59 {
60   Grob *g = get_parent (X_AXIS);
61   return g ?  g->line_l () : 0;
62 }
63
64
65 void
66 Item::copy_breakable_items ()
67 {
68   Drul_array<Item *> new_copies;
69   Direction  i=LEFT;
70   do 
71     {
72       Grob * dolly = clone ();
73       Item * item_p = dynamic_cast<Item*> (dolly);
74       pscore_l_->line_l_->typeset_grob (item_p);
75       new_copies[i] =item_p;
76     }
77   while (flip (&i) != LEFT);
78   broken_to_drul_= new_copies;
79 }
80
81
82 bool
83 Item::broken_b () const
84 {
85   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
86 }
87
88
89 /*
90   Generate items for begin and end-of line.
91  */
92 void
93 Item::discretionary_processing ()
94 {
95   if (broken_b ())
96     return;
97
98   if (Item::breakable_b (this))
99     copy_breakable_items ();
100 }
101
102 Grob*
103 Item::find_broken_piece (System*l) const
104 {
105   if (line_l () == l) 
106     return (Item*) (this);
107
108   Direction d = LEFT;
109   do {
110     Grob *s = broken_to_drul_[d];
111     if (s && s->line_l () == l)
112       return s;
113   }
114   while (flip (&d) != LEFT);
115
116   return 0;
117 }
118
119
120 Item*
121 Item::find_prebroken_piece (Direction d) const
122 {
123   Item * me = (Item *) (this);  
124   if (!d)
125     return me;
126   return dynamic_cast<Item*> (broken_to_drul_[d]);
127 }
128
129
130 Direction
131 Item::break_status_dir () const
132 {
133   if (original_l_)
134     {
135       Item * i = dynamic_cast<Item*> (original_l_);
136
137       return (i->broken_to_drul_[LEFT] == this) ? LEFT : RIGHT;
138     }
139   else
140     return CENTER;
141 }
142
143 void
144 Item::handle_prebroken_dependencies ()
145 {
146   if (original_l_)
147     {
148       set_break_subsititution (gh_int2scm (break_status_dir ()));
149       mutable_property_alist_ = do_break_substitution(original_l_->mutable_property_alist_);
150
151     }
152   
153   /*
154     Can't do this earlier, because try_visibility_lambda () might set
155     the elt property transparent, which would then be copied.
156
157     TODO:
158
159     handle break-visibility the item itself iso. breakstatusdir, so
160     the function can do more complicated things.
161     
162   */
163   SCM vis = get_grob_property ("break-visibility");
164   if (gh_procedure_p (vis))
165     {
166       SCM args = scm_list_n (gh_int2scm (break_status_dir ()), SCM_UNDEFINED);
167       SCM result = gh_apply (vis, args);
168       bool trans = gh_scm2bool (ly_car (result));
169       bool empty = gh_scm2bool (ly_cdr (result));
170       
171       if (empty && trans)
172         suicide ();
173       else if (empty)
174         {
175           set_extent (SCM_EOL, X_AXIS);
176           set_extent (SCM_EOL, Y_AXIS);
177         }
178       else if (trans)
179         set_grob_property ("molecule-callback", SCM_EOL);
180     }
181 }
182
183 SCM
184 Item::do_derived_mark ()
185 {
186   if (broken_to_drul_[LEFT])
187     scm_gc_mark (broken_to_drul_[LEFT]->self_scm ());
188   if (broken_to_drul_[RIGHT])
189     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
190   return SCM_EOL;
191 }
192
193 Item*
194 unsmob_item (SCM s )
195 {
196   return dynamic_cast<Item*> (unsmob_grob (s));
197 }
198
199
200
201 ADD_INTERFACE(Item,
202               "item-interface",
203               "",
204               "no-spacing-rods break-visibility breakable")