]> git.donarmstrong.com Git - lilypond.git/blob - lily/separation-item.cc
78126e69b25bc4238d22d68003904ac2bf0ba7bc
[lilypond.git] / lily / separation-item.cc
1 /*
2   separation-item.cc -- implement Separation_item
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1998--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "separation-item.hh"
10
11 #include "paper-column.hh"
12 #include "warn.hh"
13 #include "pointer-group-interface.hh"
14 #include "accidental-placement.hh"
15
16 void
17 Separation_item::add_item (Grob *s, Item *i)
18 {
19   assert (i);
20   Pointer_group_interface::add_grob (s, ly_symbol2scm ("elements"), i);
21 }
22
23 void
24 Separation_item::add_conditional_item (Grob *me, Grob *e)
25 {
26   Pointer_group_interface::add_grob (me, ly_symbol2scm ("conditional-elements"), e);
27 }
28
29 /*
30   Return the width of ME given that we are considering the object on
31   the LEFT.
32 */
33 Interval
34 Separation_item::conditional_width (Grob *me, Grob *left)
35 {
36   Interval w = width (me);
37
38   Item *item = dynamic_cast<Item *> (me);
39   Paper_column *pc = item->get_column ();
40
41   extract_grob_set (me, "conditional-elements", elts);
42   for (int i = 0; i < elts.size (); i++)
43     {
44       Item *il = dynamic_cast<Item *> (elts[i]);
45       if (pc != il->get_column ())
46         {
47           /* this shouldn't happen, but let's continue anyway. */
48           programming_error ("Separation_item:  I've been drinking too much");
49           continue;             /*UGH UGH*/
50         }
51
52       if (to_boolean (il->get_property ("no-spacing-rods")))
53         continue;
54
55       if (Accidental_placement::has_interface (il))
56         w.unite (Accidental_placement::get_relevant_accidental_extent (il, pc, left));
57     }
58
59   SCM pad = me->get_property ("padding");
60
61   w.widen (robust_scm2double (pad, 0.0));
62   return w;
63 }
64
65 Interval
66 Separation_item::width (Grob *me)
67 {
68   SCM sw = me->get_property ("X-extent");
69   if (is_number_pair (sw))
70     return ly_scm2interval (sw);
71
72   Item *item = dynamic_cast<Item *> (me);
73   Paper_column *pc = item->get_column ();
74   Interval w;
75
76   extract_grob_set (me, "elements", elts);
77   for (int i = 0; i < elts.size (); i++)
78     {
79       Item *il = dynamic_cast<Item *> (elts[i]);
80       if (pc != il->get_column ())
81         {
82           /* this shouldn't happen, but let's continue anyway. */
83           programming_error ("Separation_item:  I've been drinking too much");
84           continue;             /*UGH UGH*/
85         }
86
87       if (to_boolean (il->get_property ("no-spacing-rods")))
88         continue;
89
90       Interval iv (il->extent (pc, X_AXIS));
91       if (!iv.is_empty ())
92         w.unite (iv);
93     }
94
95   SCM pad = me->get_property ("padding");
96
97   w.widen (robust_scm2double (pad, 0.0));
98
99   me->set_property ("X-extent", ly_interval2scm (w));
100
101   return w;
102 }
103
104 Interval
105 Separation_item::relative_width (Grob *me, Grob *common)
106 {
107   Interval iv = width (me);
108
109   return dynamic_cast<Item *> (me)->get_column ()->relative_coordinate (common, X_AXIS) + iv;
110 }
111
112 /*
113   Try to find the break-aligned symbol in SEPARATION_ITEM that is
114   sticking out at direction D. The x size is put in LAST_EXT
115 */
116 Grob *
117 Separation_item::extremal_break_aligned_grob (Grob *me,
118                                               Direction d,
119                                               Interval *last_ext)
120 {
121   Grob *col = dynamic_cast<Item *> (me)->get_column ();
122   last_ext->set_empty ();
123   Grob *last_grob = 0;
124
125   extract_grob_set (me, "elements", elts);
126   for (int i = elts.size (); i--;)
127     {
128       Grob *break_item = elts[i];
129       if (!scm_is_symbol (break_item->get_property ("break-align-symbol")))
130         continue;
131
132       if (!scm_is_pair (break_item->get_property ("space-alist")))
133         continue;
134
135       Interval ext = break_item->extent (col, X_AXIS);
136
137       if (ext.is_empty ())
138         continue;
139
140       if (!last_grob
141           || (last_grob && d * (ext[d]- (*last_ext)[d]) > 0))
142         {
143           *last_ext = ext;
144           last_grob = break_item;
145         }
146     }
147
148   return last_grob;
149 }
150
151 ADD_INTERFACE (Separation_item, "separation-item-interface",
152                "Item that computes widths to generate spacing rods. "
153                "This is done in concert with @ref{separation-spanner-interface}.",
154                "padding X-extent conditional-elements elements");