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