changeset 24403:b9462090773a

legend.m: Setting DisplayName to "" should delete legend (bug #52641). * legend.m: Add new field "nocallbacks" to legend "userdata" struct. Set "nocallbacks" to true when constructing legend, and set to false at end of function to restore callback functionality. * legend.m (updateline): Check "nocallbacks" property before executing callback function. If DisplayName has changed to null string and there are no labels to display then delete legend, otherwise re-build legend with new strings. * isprop.m: Fix BIST test that changed with new behavior.
author Rik <rik@octave.org>
date Tue, 12 Dec 2017 13:02:19 -0800
parents 5cc1e8b16ab1
children 9213b8166af9
files scripts/plot/appearance/legend.m scripts/plot/util/isprop.m
diffstat 2 files changed, 24 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/plot/appearance/legend.m	Mon Dec 11 15:07:43 2017 -0800
+++ b/scripts/plot/appearance/legend.m	Tue Dec 12 13:02:19 2017 -0800
@@ -357,11 +357,18 @@
       endif
     endif
   else
-    ## Create new legend
+    ## Create or modify legend object
     hobjects = [];
     hplots = [];
     text_strings = {};
 
+    if (! isempty (hlegend))
+      ## Disable callbacks while modifying an existing legend
+      legdata = get (hlegend, "userdata");
+      legdata.nocallbacks = true;
+      set (hlegend, "userdata", legdata);
+    endif
+
     if (have_labels)
       ## Check for valid data that can be labeled.
       have_data = false;
@@ -412,10 +419,6 @@
         endwhile
         if (k > 0)
           if (have_labels)
-            ## FIXME: This is inefficient on an existing legend object because
-            ##        it triggers the updateline() callback which then calls
-            ##        legend() itself.  Possibly better to delete the callback
-            ##        on displayname and then re-attach it.  See bug #52641.
             set (kids(k), "displayname", arg);
           endif
           hplots(end+1) = kids(k);
@@ -1047,6 +1050,11 @@
     endif
   endif
 
+  ## Restore operation of callbacks
+  legdata = get (hlegend, "userdata");
+  legdata.nocallbacks = false;
+  set (hlegend, "userdata", legdata);
+
   if (nargout > 0)
     hleg = hlegend;
     hleg_obj = hobjects;
@@ -1183,13 +1191,19 @@
 
 function updateline (h, ~, hlegend, linelength, update_name)
 
+  ## Don't execute callbacks when legend is under construction
+  legdata = get (hlegend, "userdata");
+  if (legdata.nocallbacks)
+    return;
+  endif
+
   if (update_name)
     ## When string changes, have to rebuild legend completely
     [hplots, text_strings] = __getlegenddata__ (hlegend);
-    ## FIXME: See bug #52641.  Changing an existing legend string to a blank
-    ##        can trigger this.
-    if (! isempty (hplots))
-      legend (get (hplots(1), "parent"), hplots, text_strings);
+    if (isempty (hplots))
+      delete (hlegend);
+    else
+      legend (legdata.handle, hplots, text_strings);
     endif
   else
     kids = get (hlegend, "children");
--- a/scripts/plot/util/isprop.m	Mon Dec 11 15:07:43 2017 -0800
+++ b/scripts/plot/util/isprop.m	Tue Dec 12 13:02:19 2017 -0800
@@ -54,7 +54,7 @@
 %!assert (isprop (0, "foobar"), false)
 %!assert (isprop (0, "screenpixelsperinch"), true)
 %!assert (isprop (zeros (2, 3), "visible"), true (2, 3))
-%!assert (isprop (0:2, "visible"), [true false false])
+%!assert (isprop ([-2, -1, 0], "visible"), [false, false, true])
 
 %!error isprop ()
 %!error isprop (1)