]> git.donarmstrong.com Git - lilypond.git/blob - lily/break-align-engraver.cc
release: 1.3.55
[lilypond.git] / lily / break-align-engraver.cc
1 /*   
2   break-align-engraver.cc --  implement Break_align_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1999--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9 #include "engraver.hh"
10 #include "protected-scm.hh"
11 #include "break-align-item.hh"
12 #include "align-interface.hh"
13 #include "axis-group-interface.hh"
14 #include "dimension-cache.hh"
15
16 class Break_align_engraver : public Engraver
17 {
18   Break_align_item *align_l_;
19   Protected_scm column_alist_;
20 protected:
21   virtual void acknowledge_element(Score_element_info i);
22   virtual void do_pre_move_processing ();
23   void add_column (SCM);
24   
25 public:
26   VIRTUAL_COPY_CONS(Translator);
27   Break_align_engraver ();
28 };
29
30
31
32 ADD_THIS_TRANSLATOR(Break_align_engraver);
33
34 void
35 Break_align_engraver::add_column (SCM smob)
36 {
37   Score_element * e = unsmob_element (smob);
38   Align_interface (align_l_).add_element (e);
39   typeset_element (e);
40 }
41
42 void
43 Break_align_engraver::do_pre_move_processing ()
44 {
45   SCM order = get_property ("breakAlignOrder");
46   for (; gh_pair_p (order); order = gh_cdr (order))
47     {
48       SCM p = scm_assoc ( gh_car (order), column_alist_);
49       if (gh_pair_p (p))
50         {
51           add_column (gh_cdr (p));
52           column_alist_ = scm_assoc_remove_x (column_alist_, gh_car (order));
53         }
54     }
55
56   for (SCM p = column_alist_; gh_pair_p (p); p = gh_cdr (p))
57     {
58       SCM pair = gh_car (p);
59       add_column (gh_cdr (pair));
60     }
61
62   
63   column_alist_ = SCM_EOL;
64
65   if (align_l_)
66     {
67       typeset_element (align_l_);
68       align_l_ = 0;
69     }
70 }
71
72
73 Break_align_engraver::Break_align_engraver ()
74 {
75   column_alist_ = SCM_EOL;
76   align_l_ =0;
77 }
78
79 void
80 Break_align_engraver::acknowledge_element (Score_element_info inf)
81 {
82   if (Item * item_l = dynamic_cast <Item *> (inf.elem_l_))
83     {
84       if (item_l->empty_b (X_AXIS) || item_l->parent_l (X_AXIS))
85         return;
86
87       SCM bp=item_l->get_elt_property ("breakable");
88       bool breakable = (to_boolean (bp));
89       if (!breakable)
90         return ;
91
92       SCM align_name = item_l->get_elt_property ("break-align-symbol");
93       if (!gh_symbol_p (align_name))
94         return ;
95
96       if (!align_l_)
97         {
98           align_l_ = new Break_align_item (get_property ("basicBreakAlignProperties"));
99           announce_element (Score_element_info (align_l_,0));
100
101           SCM edge_sym = ly_symbol2scm ("Left_edge_item");
102           Item * edge = new Item (get_property ("leftEdgeBasicProperties"));
103
104           /*
105             If the element is empty, it will be ignored in the break
106             alignment stuff.
107
108             TODO: switch off ignoring empty stuff?
109           */
110           edge->set_extent_callback (Score_element::point_dimension_callback,X_AXIS);
111           
112           align_l_->set_elt_pointer ("group-center-element", edge->self_scm_);
113
114           announce_element (Score_element_info(edge, 0));
115           column_alist_ = scm_assoc_set_x (column_alist_, edge_sym, edge->self_scm_);
116         }
117
118       SCM s = scm_assoc (align_name, column_alist_);
119
120       Item * group = 0;
121
122       if (s != SCM_BOOL_F)
123         {
124           Score_element *e =  unsmob_element (gh_cdr(s));
125           group = dynamic_cast<Item*> (e);
126         }
127       else
128         {
129           group = new Item (SCM_EOL);
130
131           Axis_group_interface (group).set_interface ();
132           Axis_group_interface (group).set_axes (X_AXIS,X_AXIS);
133
134           group->set_elt_property ("break-align-symbol", align_name);
135           group->set_parent (align_l_, Y_AXIS);
136           announce_element (Score_element_info (group, 0));
137           column_alist_ = scm_assoc_set_x (column_alist_, align_name, group->self_scm_);
138         }
139       Axis_group_interface (group).add_element (item_l);
140     }
141 }