#include "axis-group-interface.hh"
#include "align-interface.hh"
+#include "directional-element-interface.hh"
#include "pointer-group-interface.hh"
#include "grob.hh"
#include "grob-array.hh"
#include "item.hh"
#include "paper-column.hh"
#include "paper-score.hh"
+#include "std-vector.hh"
#include "system.hh"
#include "warn.hh"
if (!scm_is_pair (axes))
programming_error ("axes should be nonempty");
- for (SCM ax = axes; ax != SCM_EOL; ax = scm_cdr (ax))
+ for (SCM ax = axes; scm_is_pair (ax); ax = scm_cdr (ax))
{
Axis a = (Axis) scm_to_int (scm_car (ax));
if (!e->get_parent (a))
e->set_parent (me, a);
- e->internal_set_object ((a == X_AXIS)
- ? ly_symbol2scm ("axis-group-parent-X")
- : ly_symbol2scm ("axis-group-parent-Y"),
- me->self_scm ());
+ e->set_object ((a == X_AXIS)
+ ? ly_symbol2scm ("axis-group-parent-X")
+ : ly_symbol2scm ("axis-group-parent-Y"),
+ me->self_scm ());
}
/* must be ordered, because Align_interface also uses
Axis_group_interface::generic_group_extent (Grob *me, Axis a)
{
extract_grob_set (me, "elements", elts);
+ if (a == Y_AXIS && to_boolean (me->get_property ("skyline-spacing")))
+ skyline_spacing (me, elts);
Grob *common = common_refpoint_of_array (elts, me, a);
Real my_coord = me->relative_coordinate (common, a);
}
}
+bool
+staff_priority_less (Grob * const &g1, Grob * const &g2)
+{
+ int priority_1 = robust_scm2int (g1->get_property ("outside-staff-priority"), INT_MIN);
+ int priority_2 = robust_scm2int (g2->get_property ("outside-staff-priority"), INT_MIN);
+
+ if (priority_1 < priority_2)
+ return true;
+ else if (priority_1 > priority_2)
+ return false;
+
+ /* if there is no preference in staff priority, choose the one with the lower rank */
+ int rank_1 = g1->spanned_rank_iv ()[LEFT];
+ int rank_2 = g2->spanned_rank_iv ()[LEFT];
+ return rank_1 < rank_2;
+}
+
+void
+Axis_group_interface::skyline_spacing (Grob *me, vector<Grob*> elements)
+{
+ vector_sort (elements, staff_priority_less);
+ Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS);
+ Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS);
+
+ vsize i = 0;
+ vector<Box> boxes;
+
+ for (i = 0; i < elements.size ()
+ && !scm_is_number (elements[i]->get_property ("outside-staff-priority")); i++)
+ boxes.push_back (Box (elements[i]->extent (x_common, X_AXIS),
+ elements[i]->extent (y_common, Y_AXIS)));
+
+
+ Drul_array<Skyline> skylines (Skyline (boxes, X_AXIS, DOWN),
+ Skyline (boxes, X_AXIS, UP));
+ for (; i < elements.size (); i++)
+ {
+ Direction dir = get_grob_direction (elements[i]);
+ if (dir == CENTER)
+ {
+ warning (_ ("an outside-staff object should have a direction"));
+ continue;
+ }
+
+ Box b (elements[i]->extent (x_common, X_AXIS),
+ elements[i]->extent (y_common, Y_AXIS));
+ boxes.clear ();
+ boxes.push_back (b);
+ Skyline other = Skyline (boxes, X_AXIS, -dir);
+ Real dist = skylines[dir].distance (other);
+
+ if (dist > 0)
+ {
+ b.translate (Offset (0, dir*dist));
+ elements[i]->translate_axis (dir*dist, Y_AXIS);
+ }
+ skylines[dir].insert (b, X_AXIS);
+ }
+}
+
ADD_INTERFACE (Axis_group_interface, "axis-group-interface",
"An object that groups other layout objects.",
"elements "
"common-refpoint-of-elements "
"pure-relevant-elements "
+ "skyline-spacing "
"cached-pure-extents "
);