changeset 12440:2ed62b9f949e

synchronization of axes position and outerposition
author Konstantinos Poulios <logari81@googlemail.com>
date Sun, 13 Feb 2011 15:11:56 +0100
parents ab4c6bbff14a
children b932ae4381da
files scripts/ChangeLog scripts/plot/legend.m src/ChangeLog src/graphics.cc src/graphics.h.in
diffstat 5 files changed, 212 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Fri Feb 11 14:27:26 2011 -0500
+++ b/scripts/ChangeLog	Sun Feb 13 15:11:56 2011 +0100
@@ -1,3 +1,7 @@
+2011-02-13  Konstantinos Poulios  <logari81@gmail.com>
+
+	* plot/legend.m: Ignore outerposition.
+
 2011-02-10  Ben Abbott <bpabbott@mac.com>
 
 	* plot/legend.m, plot/plotyy.m, plot/sombrero.m, plot/shading.m, 
--- a/scripts/plot/legend.m	Fri Feb 11 14:27:26 2011 -0500
+++ b/scripts/plot/legend.m	Sun Feb 13 15:11:56 2011 +0100
@@ -120,7 +120,7 @@
   endif
 
   if (strcmp (get (ca, "tag"), "plotyy"))
-    plty = get(ca (strcmp (get (ca, "tag"), "plotyy")), "userdata");
+    plty = get(ca, "userdata");
     if (isscalar (plty))
       ca = [ca, plty];
     else
@@ -492,7 +492,7 @@
         if (isempty (hlegend))
           addprops = true;
           hlegend = axes ("tag", "legend", "userdata", struct ("handle", ud),
-                          "box", box, "outerposition", [0, 0, 0, 0],
+                          "box", box,
                           "xtick", [], "ytick", [], "xticklabel", "",
                           "yticklabel", "", "zticklabel", "",
                           "xlim", [0, 1], "ylim", [0, 1], "visible", "off",
@@ -582,8 +582,6 @@
                       lpos(4)];
 
               new_pos = [ca_pos(1), ca_pos(2), ca_pos(3), ca_pos(4) - lpos(4)];
-              new_outpos = [ca_outpos(1), ca_outpos(2), ca_outpos(3), ...
-                            ca_outpos(4) - lpos(4)];
             else
               lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ...
                       ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)];
@@ -594,8 +592,6 @@
                       ca_outpos(2) + ypad, lpos(3), lpos(4)];
               new_pos = [ca_pos(1), ca_pos(2) + lpos(4), ca_pos(3), ...
                          ca_pos(4) - lpos(4)];
-              new_outpos = [ca_outpos(1), ca_outpos(2) + lpos(4), ...
-                            ca_outpos(3), ca_outpos(4) - lpos(4)];
             else
               lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ...
                       ca_pos(2) + ypad, lpos(3), lpos(4)];
@@ -605,8 +601,6 @@
               lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3) - ypad, ...
                       ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)];
               new_pos = [ca_pos(1), ca_pos(2), ca_pos(3) - lpos(3), ca_pos(4)];
-              new_outpos = [ca_outpos(1), ca_outpos(2), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4)];
             else
               lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ...
                       ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)];
@@ -618,8 +612,6 @@
                       lpos(3), lpos(4)];
               new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ...
                          ca_pos(3) - lpos(3), ca_pos(4)];
-              new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4)];
             else
               lpos = [ca_pos(1) +  ypad, ...
                       ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)];
@@ -629,8 +621,6 @@
               lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3) - ypad, ...
                       ca_pos(2) + ca_pos(4) - lpos(4), lpos(3), lpos(4)];
               new_pos = [ca_pos(1), ca_pos(2), ca_pos(3) - lpos(3), ca_pos(4)];
-              new_outpos = [ca_outpos(1), ca_outpos(2), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4)];
             else
               lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ...
                       ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)];
@@ -641,8 +631,6 @@
                       lpos(3), lpos(4)];
               new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ...
                          ca_pos(3) - lpos(3), ca_pos(4)];
-              new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4)];
             else
               lpos = [ca_pos(1) + ypad, ...
                       ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)];
@@ -653,8 +641,6 @@
                       ca_pos(2), lpos(3), lpos(4)];
               new_pos = [ca_pos(1), ca_pos(2), ...
                          ca_pos(3) - lpos(3), ca_pos(4)];
-              new_outpos = [ca_outpos(1), ca_outpos(2), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4)];
             else
               lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ...
                       ca_pos(2) + ypad, lpos(3), lpos(4)];
@@ -664,8 +650,6 @@
               lpos = [ca_outpos(1) + ypad, ca_pos(2), lpos(3), lpos(4)];
               new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ...
                          ca_pos(3) - lpos(3), ca_pos(4)];
-              new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4)];
             else
               lpos = [ca_pos(1) + ypad, ca_pos(2) + ypad, lpos(3), lpos(4)];
             endif
@@ -674,7 +658,7 @@
         units = get (hlegend, "units");
         unwind_protect
           set (hlegend, "units", "points");
-          set (hlegend, "position", lpos, "outerposition", lpos);
+          set (hlegend, "position", lpos);
         unwind_protect_cleanup
           set (hlegend, "units", units);
         end_unwind_protect
@@ -750,7 +734,7 @@
             units = get (ca(i), "units");
             unwind_protect
               set (ca(i), "units", "points");
-              set (ca (i), "position", new_pos, "outerposition", new_outpos);
+              set (ca (i), "position", new_pos);
             unwind_protect_cleanup
               set (ca(i), "units", units);
             end_unwind_protect
@@ -759,8 +743,7 @@
           set (hlegend, "deletefcn", {@deletelegend2, ca, ...
                                       ca_pos, ca_outpos, t1, hplots});
           addlistener (hlegend, "visible", {@hideshowlegend, ca, ...
-                                            ca_pos, new_pos, ...
-                                            ca_outpos, new_outpos});
+                                            ca_pos, new_pos});
         else
           set (hlegend, "deletefcn", {@deletelegend2, ca, [], [], t1, hplots});
         endif
@@ -841,7 +824,7 @@
   endwhile
 endfunction
 
-function hideshowlegend (h, d, ca, pos1, pos2, outpos1, outpos2)
+function hideshowlegend (h, d, ca, pos1, pos2)
   isvisible = strcmp (get (h, "visible"), "off");
   if (! isvisible)
     kids = get (h, "children");
@@ -861,9 +844,9 @@
       unwind_protect
         set (ca(i), "units", "points");
         if (isvisible)
-          set (ca(i), "position", pos2, "outerposition", outpos2);
+          set (ca(i), "position", pos2);
         else
-          set (ca(i), "position", pos1, "outerposition", outpos1);
+          set (ca(i), "position", pos1);
         endif
       unwind_protect_cleanup
         set (ca(i), "units", units);
@@ -889,7 +872,7 @@
         units = get (ca(i), "units");
         unwind_protect
           set (ca(i), "units", "points");
-          set (ca(i), "position", pos, "outerposition", outpos, "deletefcn", "");
+          set (ca(i), "position", pos, "deletefcn", "");
         unwind_protect_cleanup
           set (ca(i), "units", units);
         end_unwind_protect
--- a/src/ChangeLog	Fri Feb 11 14:27:26 2011 -0500
+++ b/src/ChangeLog	Sun Feb 13 15:11:56 2011 +0100
@@ -1,3 +1,30 @@
+2011-02-13  Konstantinos Poulios  <logari81@googlemail.com>
+
+	* graphics.h.in (axes::properties::get_extent,
+	axes::properties::calc_tightbox): New functions prototypes.
+	(axes::properties::update_view): Hook sync_positions.
+	(axes::properties::update_outerposition,
+	axes::properties::update_position): Set activepositionproperty
+	appropriately.
+	(text::properties::update_string): Call	update_text_extent after
+	request_autopos.
+	* graphics.cc (axes::properties::sync_positions): Enable
+	synchronization of position and outer position. Take label and
+	title extents in the calculation of outerposition into account.
+	Do iterative calculation of position when activepositionproperty
+	is set to outerposition.
+	(axes::properties::update_title_position): Use new function
+	get_extent.
+	(axes::properties::update_autopos): Handle new tag "sync".
+	(axes::properties::get_extent): New function calculating the
+	tight box which contains all axes labels and axes title.
+	(axes::properties::calc_tightbox): New function calculating axes
+	tight box.
+	(axes::properties::update_units): Don't call any hooks and listeners
+	for position, outerposition and tightset.
+	(text::properties::update_text_extent): Request axes positions
+	synchronization when axes labels or title extents change.
+
 2011-02-11  John W. Eaton  <jwe@octave.org>
 
 	* load-path.cc (strip_trailing_separators): Declare K as size_t
--- a/src/graphics.cc	Fri Feb 11 14:27:26 2011 -0500
+++ b/src/graphics.cc	Sun Feb 13 15:11:56 2011 +0100
@@ -3229,38 +3229,109 @@
   adopt (title.handle_value ());
 }
 
+Matrix
+axes::properties::calc_tightbox (const Matrix& init_pos)
+{
+  Matrix pos = init_pos;
+  graphics_object obj = gh_manager::get_object (get_parent ());
+  Matrix parent_bb = obj.get_properties ().get_boundingbox (true);
+  Matrix ext = get_extent (true);
+  ext(1) = parent_bb(3) - ext(1) - ext(3);
+  ext(0)++;
+  ext(1)++;
+  ext = convert_position (ext, "pixels", get_units (),
+                          parent_bb.extract_n (0, 2, 1, 2));
+  if (ext(0) < pos(0))
+    {
+      pos(2) += pos(0)-ext(0);
+      pos(0) = ext(0);
+    }
+  if (ext(0)+ext(2) > pos(0)+pos(2))
+    pos(2) = ext(0)+ext(2)-pos(0);
+
+  if (ext(1) < pos(1))
+    {
+      pos(3) += pos(1)-ext(1);
+      pos(1) = ext(1);
+    }
+  if (ext(1)+ext(3) > pos(1)+pos(3))
+    pos(3) = ext(1)+ext(3)-pos(1);
+  return pos;
+}
+
 void
 axes::properties::sync_positions (void)
 {
-#if 0
-  // FIXME -- this should take font metrics into consideration,
-  // and also the fact that the colorbox leaves the outerposition
-  // alone but alters the position. For now just don't adjust the
-  // positions relative to each other.
+  Matrix defpos = default_axes_position ();
 
   if (activepositionproperty.is ("outerposition"))
     {
       Matrix outpos = outerposition.get ().matrix_value ();
-      Matrix defpos = default_axes_position ();
       Matrix pos(outpos);
       pos(0) = outpos(0) + defpos(0) * outpos(2);
       pos(1) = outpos(1) + defpos(1) * outpos(3);
       pos(2) = outpos(2) * defpos(2);
       pos(3) = outpos(3) * defpos(3);
+
       position = pos;
+      update_transform ();
+      Matrix tightpos = calc_tightbox (pos);
+
+      double thrshldx = 0.005*outpos(2);
+      double thrshldy = 0.005*outpos(3);
+      for (int i = 0; i < 10; i++)
+        {
+          double dt;
+          bool modified = false;
+          dt = outpos(0)+outpos(2)-tightpos(0)-tightpos(2);
+          if (dt < -thrshldx)
+            {
+              pos(2) += dt;
+              modified = true;
+            }
+          dt = outpos(1)+outpos(3)-tightpos(1)-tightpos(3);
+          if (dt < -thrshldy)
+            {
+              pos(3) += dt;
+              modified = true;
+            }
+          dt = outpos(0)-tightpos(0);
+          if (dt > thrshldx)
+            {
+              pos(0) += dt;
+              pos(2) -= dt;
+              modified = true;
+            }
+          dt = outpos(1)-tightpos(1);
+          if (dt > thrshldy)
+            {
+              pos(1) += dt;
+              pos(3) -= dt;
+              modified = true;
+            }
+
+          if (modified)
+            {
+              position = pos;
+              update_transform ();
+              tightpos = calc_tightbox (pos);
+            }
+          else
+            break;
+        }
     }
   else
     {
+      update_transform ();
+
       Matrix pos = position.get ().matrix_value ();
-      pos(0) -= pos(2)*0.05;
-      pos(1) -= pos(3)*0.05;
-      pos(2) *= 1.1;
-      pos(3) *= 1.1;
-      outerposition = pos;
-    }
-#endif
-
-  update_transform ();
+      pos(0) -= pos(2)*defpos(0)/defpos(2);
+      pos(1) -= pos(3)*defpos(1)/defpos(3);
+      pos(2) /= defpos(2);
+      pos(3) /= defpos(3);
+
+      outerposition = calc_tightbox (pos);
+    }
 }
 
 void
@@ -4408,27 +4479,7 @@
           graphics_xform xform = get_transform ();
 
           // FIXME: bbox should be stored in axes::properties
-          ColumnVector bbox(4);
-          bbox(0) = octave_Inf;
-          bbox(1) = octave_Inf;
-          bbox(2) = -octave_Inf;
-          bbox(3) = -octave_Inf;
-          for (int i = 0; i <= 1; i++)
-            for (int j = 0; j <= 1; j++)
-              for (int k = 0; k <= 1; k++)
-                {
-                  ColumnVector p = xform.transform (i ? xPlaneN : xPlane,
-                                                    j ? yPlaneN : yPlane,
-                                                    k ? zPlaneN : zPlane, false);
-                  bbox(0) = std::min (bbox(0), p(0));
-                  bbox(1) = std::min (bbox(1), p(1));
-                  bbox(2) = std::max (bbox(2), p(0));
-                  bbox(3) = std::max (bbox(3), p(1));
-                }
-
-          bbox(2) = bbox(2)-bbox(0);
-          bbox(3) = bbox(3)-bbox(1);
-
+          Matrix bbox = get_extent (false);
           ColumnVector p = xform.untransform (bbox(0)+bbox(2)/2, (bbox(1)-10),
                                               (x_zlim(0)+x_zlim(1))/2, true);
 
@@ -4451,6 +4502,8 @@
     update_zlabel_position ();
   else if (elem_type == "title")
     update_title_position ();
+  else if (elem_type == "sync")
+    sync_positions ();
 }
 
 static void
@@ -4615,7 +4668,6 @@
                   get_position ().matrix_value ()
                   : get_outerposition ().matrix_value ());
 
-
   pos = convert_position (pos, get_units (), "pixels",
                           parent_bb.extract_n (0, 2, 1, 2));
 
@@ -4626,6 +4678,66 @@
   return pos;
 }
 
+Matrix
+axes::properties::get_extent (bool with_text) const
+{
+  graphics_xform xform = get_transform ();
+
+  Matrix ext (1, 4, 0.0);
+  ext(0) = octave_Inf;
+  ext(1) = octave_Inf;
+  ext(2) = -octave_Inf;
+  ext(3) = -octave_Inf;
+  for (int i = 0; i <= 1; i++)
+    for (int j = 0; j <= 1; j++)
+      for (int k = 0; k <= 1; k++)
+        {
+          ColumnVector p = xform.transform (i ? xPlaneN : xPlane,
+                                            j ? yPlaneN : yPlane,
+                                            k ? zPlaneN : zPlane, false);
+          ext(0) = std::min (ext(0), p(0));
+          ext(1) = std::min (ext(1), p(1));
+          ext(2) = std::max (ext(2), p(0));
+          ext(3) = std::max (ext(3), p(1));
+        }
+
+  if (with_text)
+    {
+      for (int i = 0; i < 4; i++)
+        {
+          graphics_handle text_handle;
+          if (i == 0)
+            text_handle = get_title ();
+          else if (i == 1)
+            text_handle = get_xlabel ();
+          else if (i == 2)
+            text_handle = get_ylabel ();
+          else if (i == 3)
+            text_handle = get_zlabel ();
+
+          text::properties& text_props = reinterpret_cast<text::properties&>
+            (gh_manager::get_object (text_handle).get_properties ());
+
+          if (! text_props.get_string ().empty ())
+            {
+              Matrix text_ext = text_props.get_extent_matrix ();
+              Matrix text_pos = text_props.get_position ().matrix_value ();
+              text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2));
+
+              ext(0) = std::min (ext(0), text_pos(0)+text_ext(0));
+              ext(1) = std::min (ext(1), text_pos(1)-text_ext(1)-text_ext(3));
+              ext(2) = std::max (ext(2), text_pos(0)+text_ext(0)+text_ext(2));
+              ext(3) = std::max (ext(3), text_pos(1)-text_ext(1));
+            }
+        }
+    }
+
+  ext(2) = ext(2)-ext(0);
+  ext(3) = ext(3)-ext(1);
+  
+  return ext;
+}
+
 void
 axes::properties::set_units (const octave_value& v)
 {
@@ -4646,9 +4758,9 @@
   graphics_object obj = gh_manager::get_object (get_parent ());
   Matrix parent_bb = obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
   caseless_str new_units = get_units ();
-  set_position (octave_value (convert_position (get_position().matrix_value(), old_units, new_units, parent_bb)));
-  set_outerposition (octave_value (convert_position (get_outerposition().matrix_value(), old_units, new_units, parent_bb)));
-  set_tightinset (octave_value (convert_position (get_tightinset().matrix_value(), old_units, new_units, parent_bb)));
+  position.set (octave_value (convert_position (get_position().matrix_value(), old_units, new_units, parent_bb)), false);
+  outerposition.set (octave_value (convert_position (get_outerposition().matrix_value(), old_units, new_units, parent_bb)), false);
+  tightinset.set (octave_value (convert_position (get_tightinset().matrix_value(), old_units, new_units, parent_bb)), false);
 }
 
 void
@@ -5724,6 +5836,10 @@
 
   set_extent (bbox);
 #endif
+
+  if (autopos_tag_is ("xlabel") || autopos_tag_is ("ylabel") ||
+      autopos_tag_is ("zlabel") || autopos_tag_is ("title"))
+    update_autopos ("sync");
 }
 
 void
--- a/src/graphics.h.in	Fri Feb 11 14:27:26 2011 -0500
+++ b/src/graphics.h.in	Sun Feb 13 15:11:56 2011 +0100
@@ -3077,6 +3077,7 @@
     const scaler& get_z_scaler (void) const { return sz; }
 
     Matrix get_boundingbox (bool internal = false) const;
+    Matrix get_extent (bool with_text = false) const;
 
     void update_boundingbox (void)
       {
@@ -3305,7 +3306,7 @@
     void update_yscale (void) { sy = get_yscale (); }
     void update_zscale (void) { sz = get_zscale (); }
 
-    void update_view (void) { update_camera (); update_axes_layout (); }
+    void update_view (void) { sync_positions (); }
     void update_dataaspectratio (void) { update_transform (); }
     void update_dataaspectratiomode (void) { update_transform (); }
     void update_plotboxaspectratio (void) { update_transform (); }
@@ -3381,8 +3382,17 @@
       }
 
     void sync_positions (void);
-    void update_outerposition (void) { sync_positions ();}
-    void update_position (void) { sync_positions (); }
+    void update_outerposition (void)
+    {
+      set_activepositionproperty ("outerposition");
+      sync_positions ();
+    }
+
+    void update_position (void)
+    {
+      set_activepositionproperty ("position");
+      sync_positions ();
+    }
 
     double calc_tick_sep (double minval, double maxval);
     void calc_ticks_and_lims (array_property& lims, array_property& ticks, array_property& mticks,
@@ -3412,6 +3422,8 @@
         }
     }
 
+    Matrix calc_tightbox (const Matrix& init_pos);
+
   public:
     Matrix get_axis_limits (double xmin, double xmax, double min_pos, bool logscale);
 
@@ -3713,7 +3725,7 @@
     void update_horizontalalignmentmode (void) { request_autopos (); }
     void update_verticalalignmentmode (void) { request_autopos (); }
 
-    void update_string (void) { update_text_extent ();  request_autopos ();}
+    void update_string (void) { request_autopos (); update_text_extent (); }
     void update_rotation (void) { update_text_extent (); }
     void update_fontname (void) { update_text_extent (); }
     void update_fontsize (void) { update_text_extent (); }