# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1400707664 -7200
# Node ID d0386e6bf053aac8e4ffd447b12edc1e1d3352e6
# Parent  79f69742971ac3c9c436e92f722ea475a7be7b2c
Handle figure paperpositionmode "auto" (bug #37554)

* graphics.cc (figure::properties::get_auto_paperposition): new method to compute paperposition from on screen figure position
* graphics.cc (figure::properties::set_position, figure::properties::update_papertype, update_papersize, update_paperorientation): use new method to update paperposition when mode is "auto"
* graphics.cc: add %!test for bug #37554 
* graphics.in.h (figure::properties): let paperposition update paperpositionmode
* graphics.in.h (figure::properties::update_paperpositionmode): use new method to update paperposition when mode is "auto"

diff -r 79f69742971a -r d0386e6bf053 libinterp/corefcn/graphics.cc
--- a/libinterp/corefcn/graphics.cc	Mon May 19 22:17:48 2014 -0700
+++ b/libinterp/corefcn/graphics.cc	Wed May 21 23:27:44 2014 +0200
@@ -3743,6 +3743,9 @@
           position.run_listeners (POSTSET);
           mark_modified ();
         }
+      
+      if (paperpositionmode.is ("auto"))
+        paperposition.set (get_auto_paperposition ());
     }
 }
 
@@ -3962,6 +3965,83 @@
   return ret;
 }
 
+
+Matrix
+figure::properties::get_auto_paperposition (void)
+{
+  Matrix pos = get_position ().matrix_value ();
+  Matrix sz;
+  
+  caseless_str funits = get_units ();
+  caseless_str punits = get_paperunits ();
+
+  // Convert position from figure units to paperunits 
+  if (funits == "normalized" || punits == "normalized")
+    {
+      sz = screen_size_pixels ();
+      pos = convert_position (pos, funits, "inches", sz);
+
+      if (punits == "normalized")
+        sz = papersize_from_type ("points", get_papertype ());
+
+      pos = convert_position (pos, "inches", punits, sz);
+    }
+  else
+    pos = convert_position (pos, funits, punits, sz);
+
+  // Center the figure on the page
+  sz = get_papersize ().matrix_value ();
+
+  pos(0) = sz(0)/2 - pos(2)/2;
+  pos(1) = sz(1)/2 - pos(3)/2;
+
+  return pos;
+}
+
+/*
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   ## paperpositionmode "auto" converts figure size to paper units 
+%!   set (hf, "units", "inches");
+%!   set (hf, "position", [0 0 4 5]);
+%!   set (hf, "paperunits", "centimeters");
+%!   psz = get (hf, "papersize");
+%!   fsz = [10.16 12.7];
+%!   pos = [(psz/2 .- fsz/2) fsz];  
+%!   set (hf, "paperpositionmode", "auto");
+%!   assert (get (hf, "paperposition"), pos)
+%!   
+%!   ## likewise with normalized units 
+%!   set (hf, "paperunits", "normalized");
+%!   fsz = [10.16 12.7]./psz;
+%!   pos = [([0.5 0.5] .- fsz/2) fsz];  
+%!   assert (get (hf, "paperposition"), pos)
+%!   
+%!   ## changing papertype updates paperposition 
+%!   set (hf, "paperunits", "centimeters");
+%!   set  (hf, "papertype", "a4");
+%!   psz = get (hf, "papersize");
+%!   fsz = [10.16 12.7];
+%!   pos = [(psz/2 .- fsz/2) fsz];  
+%!   assert (get (hf, "paperposition"), pos)
+%!
+%!   ## lanscape updates paperposition
+%!   set (hf, "paperorientation", "landscape");
+%!   psz = get (hf, "papersize");
+%!   fsz = [10.16 12.7];
+%!   pos = [(psz/2 .- fsz/2) fsz];  
+%!   assert (get (hf, "paperposition"), pos)
+%!   
+%!   ## back to manual mode
+%!   set (hf, "paperposition", pos+eps)
+%!   assert (get (hf, "paperpositionmode"), "manual")
+%!   assert (get (hf, "paperposition"), pos + eps)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+*/
+
 void
 figure::properties::update_paperunits (const caseless_str& old_paperunits)
 {
@@ -4030,6 +4110,9 @@
       // between update_papersize and update_papertype
       papersize.set (octave_value (sz));
     }
+
+  if (paperpositionmode.is ("auto"))
+    paperposition.set (get_auto_paperposition ());
 }
 
 void
@@ -4162,6 +4245,9 @@
       std::swap (sz(0), sz(1));
       papersize.set (octave_value (sz));
     }
+
+  if (paperpositionmode.is ("auto"))
+    paperposition.set (get_auto_paperposition ());
 }
 
 /*
@@ -4213,6 +4299,9 @@
       papersize.set (octave_value (sz));
       paperposition.set (octave_value (pos));
     }
+
+  if (paperpositionmode.is ("auto"))
+    paperposition.set (get_auto_paperposition ());
 }
 
 /*
diff -r 79f69742971a -r d0386e6bf053 libinterp/corefcn/graphics.in.h
--- a/libinterp/corefcn/graphics.in.h	Mon May 19 22:17:48 2014 -0700
+++ b/libinterp/corefcn/graphics.in.h	Wed May 21 23:27:44 2014 +0200
@@ -3349,8 +3349,8 @@
       bool_property numbertitle , "on"
       array_property outerposition s , Matrix (1, 4, -1.0)
       radio_property paperorientation U , "{portrait}|landscape|rotated"
-      array_property paperposition , default_figure_paperposition ()
-      radio_property paperpositionmode , "auto|{manual}"
+      array_property paperposition m , default_figure_paperposition ()
+      radio_property paperpositionmode au , "auto|{manual}"
       array_property papersize U , default_figure_papersize ()
       radio_property papertype SU , "{usletter}|uslegal|a0|a1|a2|a3|a4|a5|b0|b1|b2|b3|b4|b5|arch-a|arch-b|arch-c|arch-d|arch-e|a|b|c|d|e|tabloid|<custom>"
       radio_property paperunits Su , "{inches}|centimeters|normalized|points"
@@ -3397,7 +3397,15 @@
       position.add_constraint (dim_vector (1, 4));
     }
 
-  private:
+  private:    
+    Matrix get_auto_paperposition (void);
+
+    void update_paperpositionmode (void)
+    {
+      if (paperpositionmode.is ("auto"))
+        paperposition.set (get_auto_paperposition ());
+    }
+
     mutable graphics_toolkit toolkit;
   };
 
