]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/align-element.cc
release: 1.3.11
[lilypond.git] / lily / align-element.cc
index c10392cda4db8282e31d19ba144865d8f471f3ef..5f4080015c39040d4b9a1b3f2f90e4e2c3c47244 100644 (file)
 #include "align-element.hh"
 #include "interval.hh"
 #include "direction.hh"
+#include "debug.hh"
+#include "hash-table-iter.hh"
+#include "dimension-cache.hh"
 
-
-struct Align_element_content {
-  Score_element * elem_l_;
-  int priority_i_;
-  
-  static int compare (Align_element_content const &h1, 
-                     Align_element_content const &h2) 
-  {
-    return h1.priority_i_ - h2.priority_i_;
-  }
-  Align_element_content (Score_element *elem_l, int p) 
-  {
-    priority_i_ = p;
-    elem_l_ = elem_l;
-  }
-  Align_element_content () {
-    elem_l_ = 0;
-    priority_i_ = 0;
-  }
-};
-
-
-
-void
-Align_element::add_element (Score_element*el_l)
-{
-  int p = priority_i_arr_.size ();
-  add_element_priority (el_l, p);
-}
-
-void
-Align_element::add_element_priority (Score_element *el, int p)
-{
-  assert (! contains_b (el));
-  elem_l_arr_.push (el);
-  priority_i_arr_.push (p);
-  add_dependency (el);
-}
-
-void
-Align_element::do_substitute_element_pointer (Score_element*o,
-                                        Score_element*n)
-{
-  int i;
-  while ((i = elem_l_arr_.find_i (o))>=0) 
-    if (n) 
-      elem_l_arr_[i] = n;
-    else
-      elem_l_arr_.del (i);
-
-  if (o == center_l_)
-    {
-      center_l_ = n;
-    }
-}
-
-/**
-  Align elements top to bottom. 
-  The first element has its top at y = 0.0 afterwards
-
-  TODO configurable, like Horizontal_align_item
-
-  TODO should parametrise in direction and coordinate.
- */
 void
 Align_element::do_post_processing()
 {
-  if (axis_ == Y_AXIS)
+  if (axis () == Y_AXIS)
     do_side_processing ();
 }
 
 void
 Align_element::do_pre_processing ()
 {
-  if (axis_ == X_AXIS)
+  if (axis () == X_AXIS)
     do_side_processing ();
 }
 
 void
 Align_element::do_side_processing ()
 {
-  sort_elements ();
   Array<Interval> dims;
-  
-  for (int i=0; i < elem_l_arr_.size(); i++) 
+
+  Link_array<Score_element> elems;
+  Link_array<Score_element> all_elts (elem_l_arr ());
+  for (int i=0; i < elem_l_arr ().size(); i++) 
     {
-      Interval y = elem_l_arr_[i]->extent(axis_) ;
-      if (y.empty_b())
-       y = Interval (0,0);
-       
-      dims.push (y);
+      Interval y = all_elts[i]->extent(axis ()) + all_elts[i]->relative_coordinate (this, axis ());
+      if (!y.empty_b())
+       {
+         Score_element *e =dynamic_cast<Score_element*>(all_elts[i]);
+
+         // todo: fucks up if item both in Halign & Valign. 
+         SCM min_dims = e->remove_elt_property ("minimum-space");
+         if (min_dims != SCM_UNDEFINED)
+           {
+             y.unite (Interval (gh_scm2double (SCM_CAR (min_dims)),
+                                gh_scm2double (SCM_CDR (min_dims))));
+           }
+         
+         SCM extra_dims = e->remove_elt_property ("extra-space");
+         if (extra_dims != SCM_UNDEFINED)
+           {
+             y[LEFT] += gh_scm2double (SCM_CAR (extra_dims));
+             y[RIGHT] += gh_scm2double (SCM_CDR (extra_dims));
+           }
+
+         elems.push (e);
+         dims.push (y);          
+       }
     }
 
   Real where_f=0;
   Real center_f = 0.0;
-  for (int i=0 ;  i < elem_l_arr_.size(); i++) 
+  SCM scenter = get_elt_property ("center-element");
+  Score_element *center_elt = unsmob_element (scenter);
+  
+  for (int i=0 ;  i < elems.size(); i++) 
     {
       Real dy = - stacking_dir_ * dims[i][-stacking_dir_];
       if (i)
@@ -117,71 +78,66 @@ Align_element::do_side_processing ()
            <? threshold_interval_[BIGGER];
        }
 
-      
       if (!i && align_dir_ == LEFT)
        center_f = where_f;
-      else if (align_dir_ == CENTER && elem_l_arr_[i] == center_l_)
+      else if (align_dir_ == CENTER && elems[i] == center_elt)
        center_f = where_f;
 
       where_f += stacking_dir_ * dy;
-
-            
-      elem_l_arr_[i]->translate_axis (where_f, axis_);
+      elems[i]->translate_axis (where_f, axis ());
     }
 
+  if (dims.size ())
+    where_f += dims.top ()[stacking_dir_];
   if (align_dir_ == RIGHT)
     center_f = where_f;
-  
+  else if (align_dir_ == CENTER && !center_elt)
+    center_f = where_f / 2;
+    
   if (center_f)
-    for  (int i=0 ;  i < elem_l_arr_.size(); i++)
-      elem_l_arr_[i]->translate_axis (- center_f, axis_);
+    translate_axis ( - center_f, axis ());
+
+
+  //  dim_cache_[axis ()]->invalidate ();
+
 }
 
 Align_element::Align_element()
 {
   threshold_interval_ = Interval (0, Interval::infinity ());
-  transparent_b_ = true;
-  set_empty (true);
   stacking_dir_ = DOWN;
-  align_dir_ = LEFT;
-  axis_ = X_AXIS;
-  center_l_ =0;
+  align_dir_ = CENTER;
 }
 
-
-bool
-Align_element::contains_b (Score_element const *e) const
+int
+Align_element::get_count (Score_element*s)const
 {
-  return elem_l_arr_.find_l (e);
+  SCM e = get_elt_property ("elements");
+  int c =0;
+  while (gh_pair_p (e))
+    {
+      if (gh_car (e) == s->self_scm_)
+       break;
+      c++;
+      e = gh_cdr (e);
+    }
+  return c;
 }
 
-
-
-
-void
-Align_element::sort_elements ()
+Axis
+Align_element::axis () const
 {
-  Array<Align_element_content> content;
-  for  (int i =0; i < elem_l_arr_.size(); i++) 
-    content.push (Align_element_content (elem_l_arr_[i], priority_i_arr_[i]));
-  content.sort (Align_element_content::compare);
-  
-  elem_l_arr_.clear();
-  priority_i_arr_.clear();
-
-  for  (int i =0; i < content.size(); i++) 
-    {
-      elem_l_arr_.push (content[i].elem_l_);
-      priority_i_arr_.push (content[i].priority_i_);
-    }
+  return axes_[0];
 }
 
 void
-Align_element::do_print () const
+Align_element::set_axis (Axis a)
 {
-#if 0
-  DOUT << "contains: ";
-  for (int i=0 ;  i < item_l_arr_.size(); i++) 
-    DOUT << classname (item_l_arr_[i]) << ", ";
-#endif
+  set_axes (a,a);
 }
+
+
+
+
+
+