]> git.donarmstrong.com Git - lilypond.git/blob - lily/break-align-engraver.cc
release: 1.3.43
[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->remove_elt_property ("breakable");
88       bool breakable = (to_boolean (bp));
89       if (!breakable)
90         return ;
91
92       SCM align_name = item_l->remove_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;
99           align_l_->set_elt_property ("breakable", SCM_BOOL_T);
100           announce_element (Score_element_info (align_l_,0));
101
102
103           Item * edge = new Item;
104           SCM edge_sym = ly_symbol2scm ("Left_edge_item");
105           edge->set_elt_property ("break-align-symbol", edge_sym);
106
107           /*
108             If the element is empty, it will be ignored in the break
109             alignment stuff.
110
111             TODO: switch off ignoring empty stuff?
112           */
113           edge->dim_cache_[X_AXIS]->set_extent_callback (Dimension_cache::point_dimension_callback);
114           
115           align_l_->set_elt_property ("group-center-element", edge->self_scm_);
116
117           announce_element (Score_element_info(edge, 0));
118           column_alist_ = scm_assoc_set_x (column_alist_, edge_sym, edge->self_scm_);
119         }
120
121       SCM s = scm_assoc (align_name, column_alist_);
122
123       Item * group = 0;
124
125       if (s != SCM_BOOL_F)
126         {
127           Score_element *e =  unsmob_element (gh_cdr(s));
128           group = dynamic_cast<Item*> (e);
129         }
130       else
131         {
132           group = new Item;
133
134           Axis_group_interface (group).set_interface ();
135           Axis_group_interface (group).set_axes (X_AXIS,X_AXIS);
136
137           group->set_elt_property ("break-align-symbol", align_name);
138           group->set_parent (align_l_, Y_AXIS);
139           announce_element (Score_element_info (group, 0));
140           column_alist_ = scm_assoc_set_x (column_alist_, align_name, group->self_scm_);
141         }
142       Axis_group_interface (group).add_element (item_l);
143     }
144 }