changeset 10990:529b36293297

Backed out changeset 6ea65c5de87a
author David Bateman <dbateman@free.fr>
date Thu, 16 Sep 2010 23:25:18 +0200
parents 6ea65c5de87a
children 9d3a7ad94ee6
files scripts/plot/__go_draw_axes__.m scripts/plot/__plt_get_axis_arg__.m scripts/plot/legend.m src/ChangeLog src/graphics.cc src/graphics.h.in
diffstat 6 files changed, 80 insertions(+), 1009 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/plot/__go_draw_axes__.m	Thu Sep 16 23:13:22 2010 +0200
+++ b/scripts/plot/__go_draw_axes__.m	Thu Sep 16 23:25:18 2010 +0200
@@ -1342,7 +1342,7 @@
     else
       if (nd == 3)
         fputs (plot_stream, "set border 895;\n");
-      elseif (! isempty (axis_obj.ytick))
+      else
         if (strcmpi (axis_obj.yaxislocation, "right"))
           fprintf (plot_stream, "unset ytics; set y2tics %s nomirror\n",
                    axis_obj.tickdir);
--- a/scripts/plot/__plt_get_axis_arg__.m	Thu Sep 16 23:13:22 2010 +0200
+++ b/scripts/plot/__plt_get_axis_arg__.m	Thu Sep 16 23:25:18 2010 +0200
@@ -40,8 +40,7 @@
       && varargin{1}(1) != 0 && ! isfigure (varargin{1}(1)))
     tmp = varargin{1};
     obj = get (tmp);
-    if ((strcmp (obj.type, "axes") && ! strcmp (obj.tag, "legend")) 
-        || strcmp (obj.type, "hggroup"))
+    if (strcmp (obj.type, "axes") || strcmp (obj.type, "hggroup"))
       h = ancestor (tmp, "axes");
       varargin(1) = [];
       if (isempty (varargin))
--- a/scripts/plot/legend.m	Thu Sep 16 23:13:22 2010 +0200
+++ b/scripts/plot/legend.m	Thu Sep 16 23:25:18 2010 +0200
@@ -1,4 +1,5 @@
-## Copyright (C) 2010 David Bateman
+## Copyright (C) 2001, 2006, 2007, 2008, 2009 Laurent Mazet
+## Copyright (C) 2006 John W. Eaton
 ##
 ## This file is part of Octave.
 ##
@@ -21,7 +22,6 @@
 ## @deftypefnx {Function File} {} legend (@var{matstr})
 ## @deftypefnx {Function File} {} legend (@var{cell})
 ## @deftypefnx {Function File} {} legend (@dots{}, "location", @var{pos})
-## @deftypefnx {Function File} {} legend (@dots{}, "orientation", @var{orient})
 ## @deftypefnx {Function File} {} legend (@var{hax}, @dots{})
 ## @deftypefnx {Function File} {} legend (@var{hobjs}, @dots{})
 ## @deftypefnx {Function File} {} legend (@var{hax}, @var{hobjs}, @dots{})
@@ -70,10 +70,6 @@
 ##   can be appended to any location string
 ## @end multitable
 ##
-## The optional parameter @var{orient} determines if the key elements
-## are placed vertically or horizontally. The allowed values are "vertical"
-## or "horizontal" with the default being "vertical".
-##
 ## The following customizations are available using @var{option}:
 ##
 ## @table @asis
@@ -98,53 +94,25 @@
 ## @end table
 ## @end deftypefn
 
-function [hlegend2, hobjects2, hplot2, text_strings2] = legend (varargin)
+function legend (varargin)
 
-  [ca, varargin, nargs] = __plt_get_axis_arg__ (true, "legend", varargin{:});
-  if (isnan (ca))
-    fig = get (0, "currentfigure");
-    if (isempty (fig))
-      ca = gca ();
-      fig = get (ca, "parent");
-    else
-      ca = get (fig, "children");
-      ca ( ! strcmp (get (get (fig, "children"), "type"), "axes")) = [];
-      ca_pos = get (get (fig, "currentaxes"), "position");
-      ca_outpos = get (get (fig, "currentaxes"), "outerposition");
-      for i = numel (ca) : -1 : 1
-        if (! all (ca_pos, get (ca(i), "position") )
-            || ! all (ca_outpos, get (ca(i), "outerposition")))
-          ca(i) = [];
-        endif
-      endfor
-    endif
-  else
-    fig = get (ca, "parent");
-  endif
+  [ca, varargin, nargin] = __plt_get_axis_arg__ ("legend", varargin{:});
+  nargs = nargin;
 
   if (all (ishandle (varargin{1})))
     kids = flipud (varargin{1}(:));
     varargin(1) = [];
     nargs = numel (varargin);
   else
-    kids = get (fig, "children");
-    kids (strcmp (get (kids, "tag"), "legend")) = [];
-    if (isscalar (kids))
-      kids = get(kids, "children")(:);
-    else
-      kids = [get(kids, "children"){:}](:);
-    endif
+    kids = get (ca, "children");
   endif
   nkids = numel (kids);
 
-  position = "northeast";
-  orientation = "vertical";
   if (nargs > 0)
     pos = varargin{nargs};
     if (isnumeric (pos) && isscalar (pos) && round (pos) == pos)
       if (pos >= -1 && pos <= 4)
-        position = {"northeastoutside", "best", "northeast",
-                    "northwest", "southwest", "southeast"} (pos + 2);
+        set (ca, "keypos", pos);
         nargs--;
       else
         error ("legend: invalid position specified");
@@ -152,64 +120,17 @@
     endif
   endif
   
-  while (nargs > 1)
+  if (nargs > 1)
     pos = varargin{nargs-1};
     str = varargin{nargs};
     if (strcmpi (pos, "location")  && ischar (str))
-      position = lower (str);
+      set (ca, "keypos", str);
       nargs -= 2;
-    elseif (strcmpi (pos, "orientation")  && ischar (str))
-      orientation = lower (str);
-      nargs -= 2;
-    else
-      break;
     endif
-  endwhile
-
-  ## Validate the orientation 
-  switch (orientation)
-    case {"vertical", "horizontal"}
-    otherwise
-      error ("legend: unrecognized legend orientation");
-  endswitch
-
-  ## Validate the position type is valid
-  outside = false;
-  inout = findstr (position, "outside");
-  if (! isempty (inout))
-    outside = true;
-    position = position(1:inout-1);
-  else
-    outside = false;
   endif
 
-  switch (position)
-    case {"north", "south", "east", "west", "northeast", "northwest", ...
-          "southeast", "southwest"}
-    case "best"
-      warning ("legend: 'Best' not yet implemented for location specifier\n");
-      position = "northeast";
-    otherwise
-      error ("legend: unrecognized legend position");
-  endswitch
-
-  show = "create";
-  textpos = "default";
-  reverse = false;
-  box = "default";
-
-  hlegend = [];
-  fkids = get (fig, "children");
-  for i = 1 : numel(fkids)
-    if (ishandle (fkids (i)) && strcmp (get (fkids (i), "type"), "axes") 
-        && (strcmp (get (fkids (i), "tag"), "legend")))
-      udata = get (fkids (i), "userdata");
-      if (! isempty (intersect (udata.handle, ca)))
-        hlegend = fkids (i);
-        break;
-      endif
-    endif
-  endfor
+  k = 1;
+  turn_on_legend = false;
 
   if (nargs == 1)
     arg = varargin{1};
@@ -218,31 +139,30 @@
         str = tolower (deblank (arg));
         switch (str)
           case {"off", "hide"}
-            show = "off";
+            set (ca, "key", "off");
             nargs--;
           case "show"
-            show = "on";
+            set (ca, "key", "on");
             nargs--;
           case "toggle"
-            if (isempty (hlegend) || strcmp (get (hlegend, "visible"), "off"))
-              show = "on";
+            val = get (ca, "key");
+            if (strcmpi (val, "on"))
+              set (ca, "key", "off");
             else
-              show = "off";
+              set (ca, "key", "on");
             endif
             nargs--;
           case "boxon"
-            box = "on";
+            set (ca, "key", "on", "keybox", "on");
             nargs--;
           case "boxoff"
-            box = "off";
+            set (ca, "keybox", "off");
             nargs--;
           case "left"
-            textpos = "left";
-            reverse = false;
+            set (ca, "keyreverse", "off")
             nargs--;
           case "right"
-            textpos = "right";
-            reverse = true;
+            set (ca, "keyreverse", "on")
             nargs--;
           otherwise
         endswitch
@@ -258,507 +178,62 @@
     endif
   endif
 
-  if (strcmp (show, "off"))
-    if (! isempty (hlegend))
-      set (hlegend, "visible", "off");
-      set (get (hlegend, "children"), "visible", "off");
-      hlegend = [];
-    endif
-    hobjects = [];
-    hplots  = [];
-    text_strings = {};
-  elseif (strcmp (show, "on"))
-    if (! isempty (hlegend))
-      set (hlegend, "visible", "on");
-      set (get (hlegend, "children"), "visible", "on");
-    else
-      hobjects = [];
-      hplots  = [];
-      text_strings = {};
-    endif
-  elseif (strcmp (box, "on"))
-    if (! isempty (hlegend))
-      set (hlegend, "visible", "on", "box", "on");
-    endif
-  elseif (strcmp (box, "off"))
-    if (! isempty (hlegend))
-      set (hlegend, "box", "off", "visible", "off");
-    endif
-  else
-    hobjects = [];
-    hplots  = [];
-    text_strings = {};
-
-    if (nargs > 0)
-      have_data = false;
-      for k = 1:nkids
-        typ = get (kids(k), "type");
-        if (strcmp (typ, "line") || strcmp (typ, "surface")
-            || strcmp (typ, "patch") || strcmp (typ, "hggroup"))
-          have_data = true;
-          break;
-        endif
-      endfor
-
-      if (! have_data)
-        warning ("legend: plot data is empty; setting key labels has no effect");
-      endif
-    endif
-
-    if (strcmp (textpos, "default"))
-      warned = false;
-      k = nkids;
-      for i = 1 : nargs
-        arg = varargin{i};
-        if (ischar (arg))
-          typ = get (kids(k), "type");
-          while (k > 0
-                 && ! (strcmp (typ, "line") || strcmp (typ, "surface")
-                       || strcmp (typ, "patch") || strcmp (typ, "hggroup")))
-            typ = get (kids(--k), "type");
-          endwhile
-          if (k > 0)
-            if (strcmp (get (kids(k), "type"), "hggroup"))
-              hgkids = get (kids(k), "children");
-              for j = 1 : length (hgkids)
-                hgobj = get (hgkids (j));
-                if (isfield (hgobj, "displayname"))
-                  set (hgkids(j), "displayname", arg);
-                  hplots = [hplots, hgkids(j)];
-                  text_strings = {text_strings{:}, arg};
-                  break;
-                endif
-              endfor
-            else
-              set (kids(k), "displayname", arg);
-              hplots = [hplots, kids(k)];
-              text_strings = {text_strings{:}, arg};
-            endif
-
-            if (--k == 0)
-              break;
-            endif
-          elseif (! warned)
-            warned = true;
-            warning ("legend: ignoring extra labels");
-          endif
-        else
-          error ("legend: expecting argument to be a character string");
-        endif
-      endfor
-    else
-      k = nkids;
-      while (k > 0)
-        typ = get (kids(k), "type");
-        while (k > 0
-               && ! (strcmp (typ, "line") || strcmp (typ, "surface")
-                     || strcmp (typ, "patch") || strcmp (typ, "hggroup")))
-          typ = get (kids(--k), "type");
-        endwhile
-        if (k > 0)
-          if (strcmp (get (kids(k), "type"), "hggroup"))
-            hgkids = get (kids(k), "children");
-            for j = 1 : length (hgkids)
-              hgobj = get (hgkids (j));
-              if (isfield (hgobj, "displayname") 
-                  && ! isempty (hgobj.displayname))
-                hplots = [hplots, hgkids(j)];
-                text_strings = {text_strings{:}, hbobj.displayname};
-                break;
-              endif
-            endfor
-          else
-            if (! isempty (get (kids (k), "displayname")))
-              hplots = [hplots, kids(k)];
-              text_strings = {text_strings{:}, get(kids (k), "displayname")};
-            endif
-          endif
-          if (--k == 0)
-            break;
-          endif
-        endif
-      endwhile
-    endif
-
-    if (isempty (hplots))
-      if (! isempty (hlegend))
-        fkids = get (fig, "children");
-        delete (fkids (fkids == hlegend));
-        hlegend = [];
-        hobjects = [];
-        hplots  = [];
-        text_strings = {};
-      endif
-    else
-      ## Delete the old legend if it exists
-      if (! isempty (hlegend))
-        fkids = get (fig, "children");
-        delete (fkids (fkids == hlegend));
+  if (nargs > 0)
+    have_data = false;
+    for k = 1:nkids
+      typ = get (kids(k), "type");
+      if (strcmp (typ, "line") || strcmp (typ, "surface")
+          || strcmp (typ, "patch") || strcmp (typ, "hggroup"))
+        have_data = true;
+        break;
       endif
-      
-      ## Force the figure to be drawn here, so that the figure position
-      ## is updated correctly before reading it
-      drawnow ();
-
-      ## Get axis size and fontsize in points.  
-      ## Rely on listener to handle coversion.
-      units = get (ca(1), "units");
-      fontunits = get (ca(1), "fontunits");
-      unwind_protect
-        set (ca(1), "units", "points");
-        set (ca(1), "fontunits", "points");
-        ca_pos = get (ca(1), "position");
-        ca_outpos = get (ca(1), "outerposition");
-        ca_fontsize = get (ca(1), "fontsize");
-      unwind_protect_cleanup
-        set (ca(1), "units", units);
-        set (ca(1), "fontunits", fontunits);
-      end_unwind_protect
-
-      ## Padding between legend entries horizontally and vertically
-      xpad = 2;
-      ypad = 2;
-
-      ## Length of line segments in the legend in points
-      linelength = 15;
-
-      ## Create the axis first
-      ## FIXME hlegend should inherit properties from "ca"
-      curaxes = get (fig, "currentaxes");
-      unwind_protect
-        hlegend = axes ("tag", "legend", "userdata", struct ("handle", ca),
-                        "box", "off", "outerposition", [0, 0, 0, 0],
-                        "xtick", [], "ytick", [], "xticklabel", "",
-                        "yticklabel", "", "zticklabel", "", 
-                        "xlim", [0, 1], "ylim", [0, 1], "visible", "off",
-                        "activepositionproperty", "position");
-
-        ## Add text label to the axis first, checking their extents
-        nentries = numel (hplots);
-        texthandle = [];
-        maxwidth = 0;
-        maxheight = 0;
-        for k = 1 : nentries
-          if (reverse)
-            texthandle = [texthandle, text(0, 0, text_strings {k}, 
-                                           "horizontalalignment", "left")];
-          else
-            texthandle = [texthandle, text(0, 0, text_strings {k},
-                                           "horizontalalignment", "right")];
-          endif
-          units = get (texthandle (end), "units");
-          unwind_protect
-            set (texthandle (end), "units", "points");
-            extents = get (texthandle (end), "extent");
-            ## FIXME fudge for gnuplot as the text extents are calculated from
-            ## the FreeType text render rather than from gnuplot itself. Your
-            ## luck will vary depending on the terminals that are used.
-            if (strcmp (get (fig, "__backend__"), "gnuplot"))
-              extents = [0,0,1,0] + [1,1,1.22,1] .* extents;
-              linelength = 20;
-            endif
-            maxwidth = max (maxwidth, extents (3));
-            maxheight = max (maxheight, extents (4));
-          unwind_protect_cleanup
-            set (texthandle (end), "units", units);
-          end_unwind_protect
-        endfor
-
-        num1 = nentries;
-        if (strcmp (orientation, "vertical"))
-          height = nentries * (ypad + maxheight);
-          if (outside)
-            if (height > ca_pos (4))
-              ## Avoid shrinking the height of the axis to zero if outside
-              num1 = ca_pos(4) / (maxheight + ypad) / 2;
-            endif
-          else
-            if (height > 0.9 * ca_pos (4))
-              num1 = 0.9 * ca_pos(4) / (maxheight + ypad);
-            endif
-          endif
-        else
-          width = nentries * (ypad + maxwidth);
-          if (outside)
-            if (width > ca_pos (3))
-              ## Avoid shrinking the width of the axis to zero if outside
-              num1 = ca_pos(3) / (maxwidth + ypad) / 2;
-            endif
-          else
-            if (width > 0.9 * ca_pos (3))
-              num1 = 0.9 * ca_pos(3) / (maxwidth + ypad);
-            endif
-          endif
-        endif
-        num2 = ceil (nentries / num1);
-
-        xstep = 3 * xpad + (maxwidth + linelength);
-        if (reverse)
-          xoffset = xpad;
-          txoffset = 2 * xpad + linelength;
-        else
-          xoffset = 2 * xpad + maxwidth;
-          txoffset = xpad + maxwidth;
-        endif
-        ystep = (ypad + maxheight);
-        yoffset = ystep / 2;
-
-        ## Place the legend in the desired position
-        if (strcmp (orientation, "vertical"))
-          lpos = [0, 0, num2 * xstep, num1 * ystep];
-        else
-          lpos = [0, 0, num1 * xstep, num2 * ystep];
-        endif
-        switch(position)
-          case "north"
-            if (outside)
-              lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ...
-                      ca_outpos(2) + ca_outpos(4) - lpos(4), lpos(3), 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
-              ca_pos
-              lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ...
-                      ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)];
-            endif
-          case "south"
-            if (outside)
-              lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ca_outpos(2), ...
-                      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)];
-            endif
-          case "east"
-            if (outside)
-              lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3), ...
-                      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)];
-            endif
-          case "west"
-            if (outside)
-              lpos = [ca_outpos(1), ca_pos(2) + (ca_pos(4) - lpos(4)) / 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) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)];
-            endif
-          case "northeast"
-            if (outside)
-              lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3), ...
-                      ca_outpos(2) + ca_outpos(4) - lpos(4), lpos(3), lpos(4)];
-              new_pos = [ca_pos(1), ca_pos(2), ca_pos(3) - lpos(3), ...
-                         ca_pos(4) - lpos(4)];
-              new_outpos = [ca_outpos(1), ca_outpos(2), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4) - lpos(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)];
-            endif
-          case "northwest"
-            if (outside)
-              lpos = [ca_outpos(1), ca_outpos(2) + ca_outpos(4) - lpos(4), ...
-                      lpos(3), lpos(4)];
-              new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ...
-                         ca_pos(3) - lpos(3), ca_pos(4) - lpos(4)];
-              new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4) - lpos(4)];
-            else
-              lpos = [ca_pos(1) + ypad, ...
-                      ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)];
-            endif
-          case "southeast"
-            if (outside)
-              lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3), ca_outpos(2), 
-                      lpos(3), lpos(4)];
-              new_pos = [ca_pos(1), ca_pos(2) + lpos(4), ...
-                         ca_pos(3) - lpos(3), ca_pos(4) - lpos(4)];
-              new_outpos = [ca_outpos(1), ca_outpos(2) + lpos(4), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4) - lpos(4)];
-            else
-              lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ...
-                      ca_pos(2) + ypad, lpos(3), lpos(4)];
-            endif
-          case "southwest"
-            if (outside)
-              lpos = [ca_outpos(1), ca_outpos(2), 0, lpos(3), lpos(4)];
-              new_pos = [ca_pos(1) +lpos(3), ca_pos(2) + lpos(4), ...
-                         ca_pos(3) - lpos(3), ca_pos(4) - lpos(4)];
-              new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2) + lpos(4), ...
-                            ca_outpos(3) - lpos(3), ca_outpos(4) - lpos(4)];
-            else
-              lpos = [ca_pos(1) + ypad, ca_pos(2) + ypad, lpos(3), lpos(4)];
-            endif
-        endswitch
-
-        units = get (hlegend, "units");
-        unwind_protect
-          set (hlegend, "units", "points");
-          set (hlegend, "position", lpos, "outerposition", lpos);
-        unwind_protect_cleanup
-          set (hlegend, "units", units);
-        end_unwind_protect
-
-        ## Now write the line segments and place the text objects correctly
-        xk = 0;
-        yk = 0;
-        for k = 1 : numel (hplots)
-          hobjects = [hobjects, texthandle (k)];
-          color = get (hplots (k), "color");
-          style = get (hplots (k), "linestyle");
-          if (! strcmp (style, "none"))
-            l1 = line ("xdata", ([xoffset, xoffset + linelength] + xk * xstep) / lpos(3),
-                       "ydata", [1, 1] .* (lpos(4) - yoffset - yk * ystep) / lpos(4), 
-                       "color", color, "linestyle", style);
-            hobjects = [hobjects, l1];
-          endif
-          marker = get (hplots (k), "marker");
-          if (! strcmp (marker, "none"))
-            l1 = line ("xdata", (xoffset + 0.5 * linelength  + xk * xstep) / lpos(3),
-                       "ydata", (lpos(4) - yoffset - yk * ystep) / lpos(4), 
-                       "color", color, "marker", marker,
-	               "markeredgecolor", get (hplots (k), "markeredgecolor"),
-	               "markerfacecolor", get (hplots (k), "markerfacecolor"),
-	               "markersize", get (hplots (k), "markersize"));
-            hobjects = [hobjects, l1];
-          endif
-          set (texthandle (k), "position", [(txoffset + xk * xstep) / lpos(3), ...
-                                            (lpos(4) - yoffset - yk * ystep) / lpos(4)]);
-
-          if (strcmp (orientation, "vertical"))
-            yk++;
-            if (yk > num1)
-              yk = 0;
-              xk++;
-            endif
-          else
-            xk++;
-            if (xk > num1)
-              xk = 0;
-              yk++;
-            endif
-          endif
-        endfor
-
-        ## Add an invisible text object to original axis
-        ## that when it is destroyed will remove the legend
-        t1 = text (0, 0, "", "parent", ca(1), "tag", "legend", 
-                   "handlevisibility", "off", "visible", "off",
-                   "xliminclude", "off", "yliminclude", "off");
-        set (t1, "deletefcn", {@deletelegend1, hlegend});
-
-        ## Resize the axis the legend is attached to if the
-        ## legend is "outside" the plot and create listener to 
-        ## resize axis to original size if the legend is deleted, 
-        ## hidden or shown
-        if (outside)
-          for i = 1 : numel (ca)
-            units = get (ca(i), "units");
-            unwind_protect
-              set (ca(i), "units", "points");
-              set (ca (i), "position", new_pos, "outerposition", new_outpos);
-            unwind_protect_cleanup
-              set (ca(i), "units", units);
-            end_unwind_protect
-          endfor
-
-          set (hlegend, "deletefcn", {@deletelegend2, ca, ...
-                                      ca_pos, ca_outpos, t1});
-          addlistener (hlegend, "visible", {@hideshowlegend, ca, ...
-                                            ca_pos, new_pos, ...
-                                            ca_outpos, new_outpos});
-        else
-          set (hlegend, "deletefcn", {@deletelegend2, ca, [], [], t1});
-        endif
-      unwind_protect_cleanup
-        set (fig, "currentaxes", curaxes);
-      end_unwind_protect
+    endfor
+    if (! have_data)
+      warning ("legend: plot data is empty; setting key labels has no effect");
     endif
   endif
 
-  if (nargout > 0)
-    hlegend2 = hlegend2;
-    hobjects2 = hobjects;
-    hplot2 = hplots;
-    text_strings2 = text_strings;
-  endif
-
-endfunction
+  warned = false;
+  k = nkids;
+  for i = 1:nargs
+    arg = varargin{i};
+    if (ischar (arg))
+      typ = get (kids(k), "type");
+      while (k > 1
+             && ! (strcmp (typ, "line") || strcmp (typ, "surface")
+                   || strcmp (typ, "patch") || strcmp (typ, "hggroup")))
+        typ = get (kids(--k), "type");
+      endwhile
+      if (k > 0)
+        if (strcmp (get (kids(k), "type"), "hggroup"))
+          hgkids = get (kids(k), "children");
+          for j = 1 : length (hgkids)
+            hgobj = get (hgkids (j));
+            if (isfield (hgobj, "keylabel"))
+              set (hgkids(j), "keylabel", arg);
+              break;
+            endif
+          endfor
+        else
+          set (kids(k), "keylabel", arg);
+        endif
+        turn_on_legend = true;
+        if (--k == 0)
+          break;
+        endif
+      elseif (! warned)
+        warned = true;
+        warning ("legend: ignoring extra labels");
+      endif
+    else
+      error ("legend: expecting argument to be a character string");
+    endif
+  endfor
 
-function hideshowlegend (h, d, ca, pos1, pos2, outpos1, outpos2)
-  isvisible = strcmp (get (h, "visible"), "off");
-  if (! isvisible)
-    kids = get (h, "children");
-    for i = 1 : numel (kids)
-      if (! strcmp (get (kids(i), "visible"), "off"))
-        isvisible = true;
-        break;
-      endif
-    endfor
+  if (turn_on_legend)
+    set (ca, "key", "on");
   endif
 
-  for i = 1 : numel (ca)
-    if (ishandle (ca(i)) && strcmp (get (ca(i), "type"), "axes") && 
-      (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off")) &&
-        strcmp (get (ca(i), "beingdeleted"), "off"))
-      units = get (ca(i), "units");
-      unwind_protect
-        set (ca(i), "units", "points");
-        if (isvisible)
-          set (ca(i), "position", pos2, "outerposition", outpos2);
-        else
-          set (ca(i), "position", pos1, "outerposition", outpos1);
-        endif
-      unwind_protect_cleanup
-        set (ca(i), "units", units);
-      end_unwind_protect
-    endif
-  endfor
-endfunction
-
-function deletelegend1 (h, d, ca)
-  if (ishandle (ca) && strcmp (get (ca, "type"), "axes") && 
-      (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off")) &&
-      strcmp (get (ca, "beingdeleted"), "off"))
-    delete (ca);
-  endif
-endfunction
-
-function deletelegend2 (h, d, ca, pos, outpos, t1)
-  for i = 1 : numel (ca)
-    if (ishandle (ca(i)) && strcmp (get (ca(i), "type"), "axes") && 
-      (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off")) &&
-        strcmp (get (ca(i), "beingdeleted"), "off"))
-      if (!isempty (pos) && !isempty(outpos))
-        units = get (ca(i), "units");
-        unwind_protect
-          set (ca(i), "units", "points");
-          set (ca(i), "position", pos, "outerposition", outpos, "deletefcn", "");
-        unwind_protect_cleanup
-          set (ca(i), "units", units);
-        end_unwind_protect
-      endif
-      if (i == 1)
-        set (t1, "deletefcn", "");
-        delete (t1);
-      endif
-    endif
-  endfor
 endfunction
 
 %!demo
--- a/src/ChangeLog	Thu Sep 16 23:13:22 2010 +0200
+++ b/src/ChangeLog	Thu Sep 16 23:25:18 2010 +0200
@@ -1,27 +1,3 @@
-2010-09-16  David Bateman  <dbateman@free.fr>
-
-	* graphics.cc (static Matrix screen_size_pixels (void), static Matrix
-	papersize_from_type (const caseless_str, const caseless_str))): New
-	functions.
-	(void figure::properties::set_paperunits (const octave_value&),
-	void figure::properties::set_papertype (const octave_value&),
-	void figure::properties::update_paperunits (const caseless_str&))
-	void figure::properties::update_papertype (void),
-	void figure::properties::update_papersize (void),
-	void figure::properties::update_units (const caseless_str&)): New
-	methods of the figure class.
-	(void axes::properties::set_units (const octave_value&),
-	void axes::properties::update_units (const caseless_str&),
-	void axes::properties::set_fontunits (const octave_value&),
-	void axes::properties::update_fontunits (const caseless_str&)):
-	New methods of the axes class.
-	* graphics.h.in (void figure::properties::update_paperunits
-	(const caseless_str&), void figure::properties::update_units
-	(const caseless_str&)): Declaration of new figure methods.
-	(void figure::properties::update_paperunits (const caseless_str&),
-	void figure::properties::update_units (const caseless_str&)):
-	Declaration of new axes methods.
-
 2010-09-16  John P. Swensen  <jpswensen@gmail.com>
 
 	* DLD-FUNCTIONS/))magick_read__.cc (write_image): Remove
--- a/src/graphics.cc	Thu Sep 16 23:13:22 2010 +0200
+++ b/src/graphics.cc	Thu Sep 16 23:25:18 2010 +0200
@@ -532,15 +532,6 @@
   return retval;
 }
 
-// This function always returns the screensize in pixels
-static Matrix
-screen_size_pixels (void)
-{
-  graphics_object obj = gh_manager::get_object (0);
-  Matrix sz = obj.get ("screensize").matrix_value ();
-  return convert_position (sz, obj.get ("units").string_value (), "pixels", sz.extract_n (0, 2, 1, 2)).extract_n (0, 2, 1, 2);
-}
-
 static graphics_object
 xget_ancestor (const graphics_object& go_arg, const std::string& type)
 {
@@ -2609,9 +2600,6 @@
     gripe_set_invalid ("callbackobject");
 }
 
-// FIXME This should update monitorpositions and pointerlocation, but
-// as these properties are yet used, and so it doesn't matter that they
-// aren't set yet.
 void
 root_figure::properties::update_units (void)
 {
@@ -2759,7 +2747,7 @@
 Matrix
 figure::properties::get_boundingbox (bool) const
 {
-  Matrix screen_size = screen_size_pixels ();
+  Matrix screen_size = xget (0, "screensize").matrix_value ().extract_n (0, 2, 1, 2);
   Matrix pos;
 
   pos = convert_position (get_position ().matrix_value (), get_units (),
@@ -2775,7 +2763,7 @@
 void
 figure::properties::set_boundingbox (const Matrix& bb)
 {
-  Matrix screen_size = screen_size_pixels ();
+  Matrix screen_size = xget (0, "screensize").matrix_value ().extract_n (0, 2, 1, 2);
   Matrix pos = bb;
 
   pos(1) = screen_size(1) - pos(1) - pos(3);
@@ -2810,297 +2798,6 @@
     }
 }
 
-void
-figure::properties::set_paperunits (const octave_value& v)
-{
-  if (! error_state)
-    {
-      caseless_str typ = get_papertype ();
-      caseless_str punits = v.string_value ();
-      if (! error_state)
-        {
-          if (punits.compare ("normalized") && typ.compare ("custom"))
-            error ("set: can't set the paperunits to normalized when the papertype is custom");
-          else
-            {
-              caseless_str old_paperunits = get_paperunits ();
-              if (paperunits.set (v, true))
-                {
-                  update_paperunits (old_paperunits);
-                  mark_modified ();
-                }
-            }
-        }
-    }
-}
-
-void
-figure::properties::set_papertype (const octave_value& v)
-{
-  if (! error_state)
-    {
-      caseless_str typ = v.string_value ();
-      caseless_str punits = get_paperunits ();
-      if (! error_state)
-        {
-          if (punits.compare ("normalized") && typ.compare ("custom"))
-            error ("set: can't set the paperunits to normalized when the papertype is custom");
-          else
-            {
-              if (papertype.set (v, true))
-                {
-                  update_papertype ();
-                  mark_modified ();
-                }
-            }
-        }
-    }
-}
-
-static Matrix
-papersize_from_type (const caseless_str punits, const caseless_str typ)
-{ 
-  Matrix ret (1, 2, 1.0);
-
-  if (! punits.compare ("normalized"))
-    {
-      double in2units;
-      double mm2units;
-      
-      if (punits.compare ("inches"))
-        {
-          in2units = 1.0;
-          mm2units = 1 / 25.4 ;
-        }
-      else if (punits.compare ("centimeters"))
-        {
-          in2units = 2.54;
-          mm2units = 1 / 10.0;
-        }
-      else // points
-        {
-          in2units = 72.0;
-          mm2units = 72.0 / 25.4;
-        }
-
-      if (typ.compare ("usletter"))
-        {
-          ret (0) = 8.5 * in2units;
-          ret (1) = 11.0 * in2units;
-        }
-      else if (typ.compare ("uslegal"))
-        {
-          ret (0) = 8.5 * in2units;
-          ret (1) = 14.0 * in2units;
-        }
-      else if (typ.compare ("tabloid"))
-        {
-          ret (0) = 11.0 * in2units;
-          ret (1) = 17.0 * in2units;
-        }
-      else if (typ.compare ("a0"))
-        {
-          ret (0) = 841.0 * mm2units;
-          ret (1) = 1189.0 * mm2units;
-        }
-      else if (typ.compare ("a1"))
-        {
-          ret (0) = 594.0 * mm2units;
-          ret (1) = 841.0 * mm2units;
-        }
-      else if (typ.compare ("a2"))
-        {
-          ret (0) = 420.0 * mm2units;
-          ret (1) = 594.0 * mm2units;
-        }
-      else if (typ.compare ("a3"))
-        {
-          ret (0) = 297.0 * mm2units;
-          ret (1) = 420.0 * mm2units;
-        }
-      else if (typ.compare ("a4"))
-        {
-          ret (0) = 210.0 * mm2units;
-          ret (1) = 297.0 * mm2units;
-        }
-      else if (typ.compare ("a5"))
-        {
-          ret (0) = 148.0 * mm2units;
-          ret (1) = 210.0 * mm2units;
-        }
-      else if (typ.compare ("b0"))
-        {
-          ret (0) = 1029.0 * mm2units;
-          ret (1) = 1456.0 * mm2units;
-        }
-      else if (typ.compare ("b1"))
-        {
-          ret (0) = 728.0 * mm2units;
-          ret (1) = 1028.0 * mm2units;
-        }
-      else if (typ.compare ("b2"))
-        {
-          ret (0) = 514.0 * mm2units;
-          ret (1) = 728.0 * mm2units;
-        }
-      else if (typ.compare ("b3"))
-        {
-          ret (0) = 364.0 * mm2units;
-          ret (1) = 514.0 * mm2units;
-        }
-      else if (typ.compare ("b4"))
-        {
-          ret (0) = 257.0 * mm2units;
-          ret (1) = 364.0 * mm2units;
-        }
-      else if (typ.compare ("b5"))
-        {
-          ret (0) = 182.0 * mm2units;
-          ret (1) = 257.0 * mm2units;
-        }
-      else if (typ.compare ("arch-a"))
-        {
-          ret (0) = 9.0 * in2units;
-          ret (1) = 12.0 * in2units;
-        }
-      else if (typ.compare ("arch-b"))
-        {
-          ret (0) = 12.0 * in2units;
-          ret (1) = 18.0 * in2units;
-        }
-      else if (typ.compare ("arch-c"))
-        {
-          ret (0) = 18.0 * in2units;
-          ret (1) = 24.0 * in2units;
-        }
-      else if (typ.compare ("arch-d"))
-        {
-          ret (0) = 24.0 * in2units;
-          ret (1) = 36.0 * in2units;
-        }
-      else if (typ.compare ("arch-e"))
-        {
-          ret (0) = 36.0 * in2units;
-          ret (1) = 48.0 * in2units;
-        }
-      else if (typ.compare ("a"))
-        {
-          ret (0) = 8.5 * in2units;
-          ret (1) = 11.0 * in2units;
-        }
-      else if (typ.compare ("b"))
-        {
-          ret (0) = 11.0 * in2units;
-          ret (1) = 17.0 * in2units;
-        }
-      else if (typ.compare ("c"))
-        {
-          ret (0) = 17.0 * in2units;
-          ret (1) = 22.0 * in2units;
-        }
-      else if (typ.compare ("d"))
-        {
-          ret (0) = 22.0 * in2units;
-          ret (1) = 34.0 * in2units;
-        }
-      else if (typ.compare ("e"))
-        {
-          ret (0) = 34.0 * in2units;
-          ret (1) = 43.0 * in2units;
-        }
-    }
- 
-  return ret;
-}
-
-void
-figure::properties::update_paperunits (const caseless_str& old_paperunits)
-{
-  Matrix pos = get_paperposition ().matrix_value ();
-  Matrix sz = get_papersize ().matrix_value ();
-  
-  pos (0) = pos (0) / sz(0);
-  pos (1) = pos (1) / sz(1);
-  pos (2) = pos (2) / sz(0);
-  pos (3) = pos (3) / sz(1);
-
-  caseless_str punits = get_paperunits ();
-  caseless_str typ = get_papertype ();
-
-  if (typ.compare ("custom"))
-    {
-      if (old_paperunits.compare ("centimeters"))
-        {
-          sz (0) = sz (0) / 2.54;
-          sz (1) = sz (1) / 2.54;
-        }
-      else if (old_paperunits.compare ("points"))
-        {
-          sz (0) = sz (0) / 72.0;
-          sz (1) = sz (1) / 72.0;
-        }
-
-      if (punits.compare ("centimeters"))
-        {
-          sz(0) = sz(0) * 2.54;
-          sz(1) = sz(1) * 2.54;
-        }
-      else if (old_paperunits.compare ("points"))
-        {
-          sz (0) = sz (0) * 72.0;
-          sz (1) = sz (1) * 72.0;
-        }
-    }
-  else
-    sz = papersize_from_type (punits, typ);
-
-  pos (0) = pos (0) * sz(0);
-  pos (1) = pos (1) * sz(1);
-  pos (2) = pos (2) * sz(0);
-  pos (3) = pos (3) * sz(1);
-
-  papersize.set (octave_value (sz));
-  paperposition.set (octave_value (pos));
-}
-
-void
-figure::properties::update_papertype (void)
-{
-  caseless_str typ = get_papertype ();
-
-  if (! typ.compare ("custom"))
-    // Call papersize.set rather than set_papersize to avoid loops between 
-    // update_papersize and update_papertype
-    papersize.set (octave_value (papersize_from_type (get_paperunits (), typ)));
-}
-
-void
-figure::properties::update_papersize (void)
-{
-  papertype.set ("custom");
-}
-
-void
-figure::properties::set_units (const octave_value& v)
-{
-  if (! error_state)
-    {
-      caseless_str old_units = get_units ();
-      if (units.set (v, true))
-        {
-          update_units (old_units);
-          mark_modified ();
-        }
-    }
-}
-
-void
-figure::properties::update_units (const caseless_str& old_units)
-{
-  set_position (convert_position (get_position ().matrix_value (), old_units,
-                                  get_units (), screen_size_pixels ()));
-}
-
 std::string
 figure::properties::get_title (void) const
 {
@@ -3976,74 +3673,6 @@
   return pos;
 }
 
-void
-axes::properties::set_units (const octave_value& v)
-{
-  if (! error_state)
-    {
-      caseless_str old_units = get_units ();
-      if (units.set (v, true))
-        {
-          update_units (old_units);
-          mark_modified ();
-        }
-    }
-}
-
-void
-axes::properties::update_units (const caseless_str& old_units)
-{
-  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)));
-}
-
-void
-axes::properties::set_fontunits (const octave_value& v)
-{
-  if (! error_state)
-    {
-      caseless_str old_fontunits = get_fontunits ();
-      if (fontunits.set (v, true))
-        {
-          update_fontunits (old_fontunits);
-          mark_modified ();
-        }
-    }
-}
-
-void
-axes::properties::update_fontunits (const caseless_str& old_units)
-{
-  caseless_str new_units = get_fontunits ();
-  double fsz = get_fontsize ();
-  double pixelsperinch = xget (0, "screenpixelsperinch").double_value();
-  double parent_height = get_boundingbox (true).elem (3);
-
-  if (old_units.compare ("normalized"))
-    fsz = fsz * parent_height * 72 / pixelsperinch;
-  else if (old_units.compare ("pixels"))
-    fsz = fsz * 72 / pixelsperinch;
-  else if (old_units.compare ("inches"))
-    fsz = fsz * 72;
-  else if (old_units.compare ("centimeters"))
-    fsz = fsz * 72 / 2.54;
-
-  if (new_units.compare ("normalized"))
-    fsz = fsz * pixelsperinch / parent_height / 72;
-  else if (new_units.compare ("pixels"))
-    fsz = fsz * pixelsperinch / 72;
-  else if (new_units.compare ("inches"))
-    fsz = fsz / 72;
-  else if (new_units.compare ("centimeters"))
-    fsz = fsz * 2.54 / 72;
-
-  set_fontsize (octave_value (fsz));
-}
-
 ColumnVector
 graphics_xform::xform_vector (double x, double y, double z)
 {
--- a/src/graphics.h.in	Thu Sep 16 23:13:22 2010 +0200
+++ b/src/graphics.h.in	Thu Sep 16 23:25:18 2010 +0200
@@ -2639,10 +2639,6 @@
 
     void set_boundingbox (const Matrix& bb);
 
-    void update_units (const caseless_str& old_units);
-
-    void update_paperunits (const caseless_str& old_paperunits);
-
     std::string get_title (void) const;
 
     // See the genprops.awk script for an explanation of the
@@ -2672,11 +2668,11 @@
       double_property mincolormap , 64
       string_property name , ""
       bool_property numbertitle , "on"
-      radio_property paperunits Su , "{inches}|centimeters|normalized|points"
+      radio_property paperunits , "{inches}|centimeters|normalized|points"
       array_property paperposition , default_figure_paperposition ()
       radio_property paperpositionmode , "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>"
+      array_property papersize , default_figure_papersize ()
+      radio_property papertype , "{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 pointer , "crosshair|fullcrosshair|{arrow}|ibeam|watch|topl|topr|botl|botr|left|top|right|bottom|circle|cross|fleur|custom|hand"
       array_property pointershapecdata , Matrix (16, 16, 0)
       array_property pointershapehotspot , Matrix (1, 2, 0)
@@ -2687,7 +2683,7 @@
       callback_property resizefcn , Matrix ()
       radio_property selectiontype , "{normal}|open|alt|extend"
       radio_property toolbar , "none|{auto}|figure"
-      radio_property units Su , "inches|centimeters|normalized|points|{pixels}|characters"
+      radio_property units , "inches|centimeters|normalized|points|{pixels}|characters"
       callback_property windowbuttondownfcn , Matrix ()
       callback_property windowbuttonmotionfcn , Matrix ()
       callback_property windowbuttonupfcn , Matrix ()
@@ -2926,10 +2922,6 @@
     void unzoom (void);
     void clear_zoom_stack (void);
 
-    void update_units (const caseless_str& old_units);
-
-    void update_fontunits (const caseless_str& old_fontunits);
-
   private:
     scaler sx, sy, sz;
     Matrix x_render, x_render_inv;
@@ -3026,7 +3018,7 @@
       radio_property fontangle , "{normal}|italic|oblique"
       string_property fontname , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize , 12
-      radio_property fontunits SU , "{points}|normalized|inches|centimeters|pixels"
+      radio_property fontunits , "{points}|normalized|inches|centimeters|pixels"
       radio_property fontweight , "{normal}|light|demi|bold"
       radio_property gridlinestyle , "-|--|{:}|-.|none"
       string_array_property linestyleorder , "-"
@@ -3040,7 +3032,7 @@
       array_property ticklength , default_axes_ticklength ()
       array_property tightinset r , Matrix (1, 4, 0.0)
       // FIXME -- uicontextmenu should be moved here.
-      radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters"
+      radio_property units , "{normalized}|inches|centimeters|points|pixels|characters"
       // hidden properties for transformation computation
       array_property x_viewtransform h , Matrix (4, 4, 0.0)
       array_property x_projectiontransform h , Matrix (4, 4, 0.0)