]> git.donarmstrong.com Git - lilypond.git/blob - lily/break-align-engraver.cc
6cafa97a585b646cc85582cdd64913345f7497ff
[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--2001 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 finalize ();
23   virtual void acknowledge_grob (Grob_info i);
24   virtual void stop_translation_timestep ();
25   void add_column (SCM);
26   
27 public:
28   TRANSLATOR_DECLARATIONS(Break_align_engraver);
29 };
30
31 void
32 Break_align_engraver::add_column (SCM smob)
33 {
34   Grob * e = unsmob_grob (smob);
35   Break_align_interface::add_element (align_l_,e);
36   typeset_grob (e);
37 }
38
39 void
40 Break_align_engraver::finalize ()
41 {
42   column_alist_ = SCM_EOL;
43 }
44
45 void
46 Break_align_engraver::stop_translation_timestep ()
47 {
48   SCM order = get_property ("breakAlignOrder");
49   for (; gh_pair_p (order); order = ly_cdr (order))
50     {
51       SCM p = scm_assoc (ly_car (order), column_alist_);
52       if (gh_pair_p (p))
53         {
54           add_column (ly_cdr (p));
55           column_alist_ = scm_assoc_remove_x (column_alist_, ly_car (order));
56         }
57     }
58
59   for (SCM p = column_alist_; gh_pair_p (p); p = ly_cdr (p))
60     {
61       SCM pair = ly_car (p);
62       add_column (ly_cdr (pair));
63     }
64
65   
66   column_alist_ = SCM_EOL;
67
68   if (align_l_)
69     {
70       typeset_grob (align_l_);
71       align_l_ = 0;
72     }
73 }
74
75
76 Break_align_engraver::Break_align_engraver ()
77 {
78   column_alist_ = SCM_EOL;
79   align_l_ =0;
80 }
81
82 void
83 Break_align_engraver::acknowledge_grob (Grob_info inf)
84 {
85   if (Item * item_l = dynamic_cast <Item *> (inf.grob_l_))
86     {
87       if (item_l->empty_b (X_AXIS) || item_l->get_parent (X_AXIS))
88         return;
89
90       SCM bp=item_l->get_grob_property ("breakable");
91       bool breakable = (to_boolean (bp));
92       if (!breakable)
93         return ;
94
95       SCM align_name = item_l->get_grob_property ("break-align-symbol");
96       if (!gh_symbol_p (align_name))
97         return ;
98
99       if (!align_l_)
100         {
101           align_l_ = new Item (get_property ("BreakAlignment"));
102           Break_align_interface::set_interface (align_l_);
103           announce_grob (align_l_,0);
104
105           SCM edge_sym = ly_symbol2scm ("Left_edge_item");
106           Item * edge = new Item (get_property ("LeftEdge"));
107
108          
109
110           /*
111             If the element is empty, it will be ignored in the break
112             alignment stuff.
113
114             TODO: switch off ignoring empty stuff?
115           */
116           edge->set_extent_callback (Grob::point_dimension_callback_proc, X_AXIS);
117           
118           /*
119             We must have left-edge in the middle.  Instrument-names
120             are left to left-edge, so they don't enter the staff.
121           */
122           align_l_->set_grob_property ("self-alignment-X", edge->self_scm ());
123           
124           announce_grob (edge, 0);
125           column_alist_ = scm_assoc_set_x (column_alist_, edge_sym, edge->self_scm ());
126         }
127
128       SCM s = scm_assoc (align_name, column_alist_);
129
130       Item * group = 0;
131
132       if (s != SCM_BOOL_F)
133         {
134           Grob *e =  unsmob_grob (ly_cdr (s));
135           group = dynamic_cast<Item*> (e);
136         }
137       else
138         {
139           group = new Item (get_property ("BreakAlignGroup"));
140
141           Axis_group_interface::set_interface (group);
142           Axis_group_interface::set_axes (group, X_AXIS,X_AXIS);
143
144           group->set_grob_property ("break-align-symbol", align_name);
145           group->set_parent (align_l_, Y_AXIS);
146           announce_grob (group, 0);
147           column_alist_ = scm_assoc_set_x (column_alist_, align_name, group->self_scm ());
148
149         }
150       Axis_group_interface::add_element (group, item_l);
151     }
152 }
153 ENTER_DESCRIPTION(Break_align_engraver,
154 /* descr */       "Align grobs with corresponding break-align-symbols into groups, and order the groups according to breakAlignOrder",
155 /* creats*/       "BreakAlignment BreakAlignGroup LeftEdge",
156 /* acks  */       "grob-interface", // break-aligned-interface ?
157 /* reads */       "breakAlignOrder",
158 /* write */       "");