changeset 22069:9121d6584f6a

Overhaul graphics implementation of hold() (bug #43559). * NEWS: Announce possible color changes in plots relying on "hold on". * hold.m: Deprecate "hold all" in docstring. Eliminate use of __hold_all__ graphics property. Update %!demo to use "hold on" only. * ishold.m: Put input validation first. Use switch statement rather than if/else tree for clarity. * graphics.in.h: Remove hidden __hold_all__ graphics property of axes. * graphics.cc (axes::properties::set_defaults): Remove use of __hold_all__. * newplot.m: Delete kluge use of __next_line_color__ and __next_line_style__. Set colororderindex and linestyleorderindex to 1 on new plots. * __next_line_color__.m: Completely rewrite to use the axes graphic property "colororderindex" to keep track of which color should be used next. Also increment "linestyleorderindex" when number of colors used rolls over so that colors will repeat with the next linestyle in the series. Update BIST test. * __next_line_style__.m: Completely rewrite to use the axes graphic property "linestyleorderindex" to keep track of which linestyle should be used next. * imagesc.m, axis.m, legend.m: Replace "hold all" with "hold on" in all demos.
author Rik <rik@octave.org>
date Thu, 07 Jul 2016 13:07:03 -0700
parents 88b3c6932236
children 3008798dc5ba
files NEWS libinterp/corefcn/graphics.cc libinterp/corefcn/graphics.in.h scripts/image/imagesc.m scripts/plot/appearance/axis.m scripts/plot/appearance/legend.m scripts/plot/util/__next_line_color__.m scripts/plot/util/__next_line_style__.m scripts/plot/util/hold.m scripts/plot/util/ishold.m scripts/plot/util/newplot.m
diffstat 11 files changed, 87 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Thu Jul 07 12:15:46 2016 -0700
+++ b/NEWS	Thu Jul 07 13:07:03 2016 -0700
@@ -22,6 +22,14 @@
     "luminance profile" and is also more similar to Matlab's new default
     colormap "parula".
 
+ ** The graphics command "hold on" now ensures that each new plot added to
+    an existing plot has a different color or linestyle according to the
+    "ColorOrder" and/or "LineStyleOrder" properties.  This is equivalent
+    to the old command "hold all" and was made for Matlab compatibility.
+    Existing code *may* produce differently colored plots if it did not
+    specify the color for a plot and relied on each new plot having the
+    the default first color in the "ColorOrder" property.
+
  ** When starting, Octave now looks in the function path for a file
     startup.m and executes any commands found there.  This change was
     made to accommodate Matlab users.  Octave has it's own configuration
--- a/libinterp/corefcn/graphics.cc	Thu Jul 07 12:15:46 2016 -0700
+++ b/libinterp/corefcn/graphics.cc	Thu Jul 07 13:07:03 2016 -0700
@@ -4836,7 +4836,6 @@
   tview(1) = 90;
   view = tview;
 
-  __hold_all__ = "off";
   nextplot = "replace";
 
   ambientlightcolor = Matrix (1, 3, 1.0);
--- a/libinterp/corefcn/graphics.in.h	Thu Jul 07 12:15:46 2016 -0700
+++ b/libinterp/corefcn/graphics.in.h	Thu Jul 07 13:07:03 2016 -0700
@@ -3922,7 +3922,6 @@
       radio_property ztickmode u , "{auto}|manual"
       // Octave-specific properties
       double_property mousewheelzoom , 0.5
-      bool_property __hold_all__ h , "off"
       // hidden properties for alignment of subplots
       radio_property autopos_tag h , "{none}|subplot"
       // hidden properties for inset
--- a/scripts/image/imagesc.m	Thu Jul 07 12:15:46 2016 -0700
+++ b/scripts/image/imagesc.m	Thu Jul 07 13:07:03 2016 -0700
@@ -159,7 +159,7 @@
 %! g = 0.1:0.1:10;
 %! h = g'*g;
 %! imagesc (g, g, sin (h));
-%! hold all;
+%! hold on;
 %! plot (g, 11.0 * ones (size (g)));
 %! imagesc (g, g+12, cos (h/2));
 %! axis ([0 10 0 22]);
@@ -172,7 +172,7 @@
 %! g = 0.1:0.1:10;
 %! h = g'*g;
 %! plot (g, 10.5 * ones (size (g)));
-%! hold all;
+%! hold on;
 %! imagesc (g, g, sin (h));
 %! plot (g, 11.0 * ones (size (g)));
 %! imagesc (g, g+12, cos (h/2));
--- a/scripts/plot/appearance/axis.m	Thu Jul 07 12:15:46 2016 -0700
+++ b/scripts/plot/appearance/axis.m	Thu Jul 07 13:07:03 2016 -0700
@@ -605,7 +605,7 @@
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   plot (11:20, [21:24, NaN, -Inf, 27:30]);
-%!   hold all;
+%!   hold on;
 %!   plot (11:20, 25.5 + rand (10));
 %!   axis tight;
 %!   assert (axis (), [11 20 21 30]);
--- a/scripts/plot/appearance/legend.m	Thu Jul 07 12:15:46 2016 -0700
+++ b/scripts/plot/appearance/legend.m	Thu Jul 07 13:07:03 2016 -0700
@@ -1399,7 +1399,7 @@
 %! clf;
 %! x = 0:0.1:10;
 %! plot (x, sin (x), ';sin (x);');
-%! hold all;
+%! hold on;
 %! plot (x, cos (x), ';cos (x);');
 %! hold off;
 %! title ('legend constructed from multiple plot calls');
@@ -1408,7 +1408,7 @@
 %! clf;
 %! x = 0:0.1:10;
 %! plot (x, sin (x), ';sin (x);');
-%! hold all;
+%! hold on;
 %! plot (x, cos (x), ';cos (x);');
 %! hold off;
 %! title ('Specified label text overrides previous labels');
--- a/scripts/plot/util/__next_line_color__.m	Thu Jul 07 12:15:46 2016 -0700
+++ b/scripts/plot/util/__next_line_color__.m	Thu Jul 07 13:07:03 2016 -0700
@@ -27,29 +27,35 @@
 ## Author: Carl Osterwisch
 ## Author: jwe
 
-function rgb = __next_line_color__ (reset)
+function rgb = __next_line_color__ ()
+
+  ca = gca ();
 
-  persistent reset_colors = true;
+  colororder = get (ca, "colororder");
+  if (isempty (colororder))
+    rgb = [0 0 0];   # black
+    return;
+  endif
 
-  if (nargin == 1)
-    ## Indicates whether the next call will increment or not
-    reset_colors = reset;
-  else
-    ## Find and return the next line color
-    ca = gca ();
-    colororder = get (ca, "colororder");
-    if (reset_colors)
-      color_index = 1;
-      reset_colors = false;
-    else
-      ## Executed when "hold all" is active
-      n_kids = length (get (ca, "children"));
-      n_colors = rows (colororder);
-      color_index = mod (n_kids, n_colors) + 1;
-    endif
-    rgb = colororder(color_index,:);
+  color_idx = fix (get (ca, "colororderindex"));
+  num_colors = rows (colororder);
+  if (color_idx > num_colors)
+    color_idx = mod (color_idx, num_colors);
+  endif
+  if (color_idx < 1)
+    color_idx = 1;
   endif
 
+  rgb = colororder(color_idx, :);
+
+  if (++color_idx > num_colors)
+    color_idx = mod (color_idx, num_colors);
+    ## Rollover of all colors switches to next linestyle.
+    style_idx = fix (get (ca, "linestyleorderindex"));
+    set (ca, "linestyleorderindex", ++style_idx);
+  endif
+  set (ca, "colororderindex", color_idx);
+
 endfunction
 
 
@@ -59,11 +65,11 @@
 %!   hax = axes ();
 %!   set (hax, "colororder", [1 0 0; 0 1 0; 0 0 1]);
 %!   hold on;
-%!   h = plot (1:5,1:5,'o', 1:4,1:4, "x", 1:3,1:3, "d");
+%!   h = plot (1:5,1:5,'o', 1:4,1:4,"x", 1:3,1:3,"d");
 %!   assert (get (h, "color"), {[1 0 0]; [0 1 0]; [0 0 1]});
 %!   cla (hax);
-%!   hold all;
-%!   h1 = plot (1:5,1:5,'o');
+%!   hold on;
+%!   h1 = plot (1:5,1:5, 'o');
 %!   h2 = plot (1:4,1:4, "x");
 %!   h3 = plot (1:3,1:3, "d");
 %!   assert (get ([h1;h2;h3], "color"), {[1 0 0]; [0 1 0]; [0 0 1]});
--- a/scripts/plot/util/__next_line_style__.m	Thu Jul 07 12:15:46 2016 -0700
+++ b/scripts/plot/util/__next_line_style__.m	Thu Jul 07 13:07:03 2016 -0700
@@ -24,36 +24,34 @@
 ## Return the next line style in the rotation.
 
 
-function [linestyle, marker] = __next_line_style__ (reset)
+function [linestyle, marker] = __next_line_style__ ()
+
+  ca = gca ();
 
-  persistent reset_style = true;
+  styleorder = get (ca, "linestyleorder");
+  if (isempty (styleorder))
+    linestyle = "-";   # basic line
+    marker = "none";   # no marker
+    return;
+  endif
 
-  if (nargin == 1)
-    ## Indicates whether the next call will increment or not
-    reset_style = reset;
-  else
-    ## Find and return the next line style
-    ca = gca ();
-    style_rotation = get (ca, "linestyleorder");
-    if (ischar (style_rotation))
-      style_rotation = strsplit (style_rotation, "|");
-    endif
-    nStyles = length (style_rotation);
-    if (reset_style || (nStyles < 2))
-      style_index = 1;
-      reset_style = false;
-    else
-      ## Executed when "hold all" is active
-      nChildren = length (get (ca, "Children"));
-      nColors = rows (get (ca, "ColorOrder"));
-      style_index = mod (floor (nChildren/nColors), nStyles) + 1;
-    endif
-    options = __pltopt__ ("__next_line_style__",
-                          style_rotation(style_index));
-    linestyle = options.linestyle;
-    marker = options.marker;
+  if (ischar (styleorder))
+    styleorder = cellstr (styleorder);
   endif
 
+  style_idx = fix (get (ca, "linestyleorderindex"));
+  num_styles = rows (styleorder);
+  if (style_idx > num_styles)
+    style_idx = mod (style_idx, num_styles);
+  endif
+  if (style_idx < 1)
+    style_idx = 1;
+  endif
+
+  options = __pltopt__ ("__next_line_style__", styleorder{style_idx});
+  linestyle = options.linestyle;
+  marker = options.marker;
+
 endfunction
 
 
@@ -67,7 +65,7 @@
 %!   h = plot (1:5,1:5, 1:4,1:4, 1:3,1:3);
 %!   assert (get (h, "linestyle"), {"-"; ":"; "--"});
 %!   cla (hax);
-%!   hold all;
+%!   hold on;
 %!   h1 = plot (1:5,1:5);
 %!   h2 = plot (1:4,1:4);
 %!   h3 = plot (1:3,1:3);
--- a/scripts/plot/util/hold.m	Thu Jul 07 12:15:46 2016 -0700
+++ b/scripts/plot/util/hold.m	Thu Jul 07 13:07:03 2016 -0700
@@ -20,7 +20,6 @@
 ## @deftypefn  {} {} hold
 ## @deftypefnx {} {} hold on
 ## @deftypefnx {} {} hold off
-## @deftypefnx {} {} hold all
 ## @deftypefnx {} {} hold (@var{hax}, @dots{})
 ## Toggle or set the @qcode{"hold"} state of the plotting engine which
 ## determines whether new graphic objects are added to the plot or replace
@@ -29,12 +28,11 @@
 ## @table @code
 ## @item hold on
 ## Retain plot data and settings so that subsequent plot commands are displayed
-## on a single graph.
+## on a single graph.  Line color and line style are advanced for each new plot
+## added.
 ##
-## @item hold all
-## Retain plot line color, line style, data, and settings so that subsequent
-## plot commands are displayed on a single graph with the next line color and
-## style.
+## @item hold all (deprecated)
+## Equivalent to @code{hold on}.
 ##
 ## @item hold off
 ## Restore default graphics settings which clear the graph and reset axis
@@ -92,7 +90,6 @@
     set (hax, "nextplot", "add");
     set (hfig, "nextplot", "add");
   endif
-  set (hax, "__hold_all__", hold_all);
 
 endfunction
 
@@ -108,15 +105,6 @@
 
 %!demo
 %! clf;
-%! t = linspace (0, 2*pi, 100);
-%! plot (t, sin (t));
-%! hold all;
-%! plot (t, cos (t));
-%! title ({'hold all', '2 plots shown on same graph with linestyle also preserved'});
-%! hold off;
-
-%!demo
-%! clf;
 %! A = rand (100);
 %! [X, Y] = find (A > 0.95);
 %! imshow (A);
--- a/scripts/plot/util/ishold.m	Thu Jul 07 12:15:46 2016 -0700
+++ b/scripts/plot/util/ishold.m	Thu Jul 07 13:07:03 2016 -0700
@@ -38,19 +38,23 @@
     fig = gcf ();
     ax = get (fig, "currentaxes");
   else
-    if (ishandle (h))
-      if (strcmp (get (h, "type"), "figure"))
+    if (! ishandle (h))
+      error ("ishold: H must be an axes or figure graphics handle");
+    endif
+
+    switch (get (h, "type"))
+      case "figure"
         fig = h;
         ax = get (fig, "currentaxes");
-      elseif (strcmp (get (h, "type"), "axes"))
+
+      case "axes"
         ax = h;
         fig = ancestor (ax, "figure");
-      else
+
+      otherwise
         error ("ishold: H must be an axes or figure graphics handle");
-      endif
-    else
-      error ("ishold: H must be an axes or figure graphics handle");
-    endif
+
+    endswitch
   endif
 
   retval = (strcmp (get (fig, "nextplot"), "add")
--- a/scripts/plot/util/newplot.m	Thu Jul 07 12:15:46 2016 -0700
+++ b/scripts/plot/util/newplot.m	Thu Jul 07 13:07:03 2016 -0700
@@ -152,16 +152,6 @@
     deleteall = false;
   endif
 
-  ## FIXME: Is this necessary anymore?
-  ##        It seems like a kluge that belongs somewhere else.
-  if (strcmp (get (ca, "__hold_all__"), "off"))
-    __next_line_color__ (true);
-    __next_line_style__ (true);
-  else
-    __next_line_color__ (false);
-    __next_line_style__ (false);
-  endif
-
   anp = get (ca, "nextplot");
   switch (anp)
     case "add"
@@ -213,6 +203,11 @@
       ## the above code is is required.
   endswitch
 
+  ## Reset line and color styles when hold is not on 
+  if (! strcmp (anp, "add"))
+    set (ca, "colororderindex", 1, "linestyleorderindex", 1);
+  endif
+
   if (nargout > 0)
     hax = ca;
   endif