Mercurial > hg > octave-nkf
changeset 19456:f0dcb44826f6
Overhaul appdata family of functions (getappdata, isappdata, rmappdata, setappdata).
* getappdata.m: Redo docstring. Match function variable names to
documentation. Place input validation first and make error messages
more specific. Add BIST tests.
* isappdata.m: Redo docstring. Match function variable names to documentation.
Make input validation more precise. Use try/catch block for performance
improvement. Add BIST tests.
* rmappdata.m: Redo docstring. Improve input validation. Remove one for loop
through vectorization. Add BIST tests.
* setappdata.m: Redo docstring. Make input validation more precise.
Use try/catch block for 80% performance improvement. Add BIST tests.
author | Rik <rik@octave.org> |
---|---|
date | Sat, 18 Oct 2014 18:10:52 -0700 |
parents | 281a36ad4907 |
children | d0f02639f560 |
files | scripts/miscellaneous/getappdata.m scripts/miscellaneous/isappdata.m scripts/miscellaneous/rmappdata.m scripts/miscellaneous/setappdata.m |
diffstat | 4 files changed, 193 insertions(+), 84 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/miscellaneous/getappdata.m +++ b/scripts/miscellaneous/getappdata.m @@ -19,47 +19,84 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {@var{value} =} getappdata (@var{h}, @var{name}) ## @deftypefnx {Function File} {@var{appdata} =} getappdata (@var{h}) -## -## Return the @var{value} for named application data for the object(s) with -## handle(s) @var{h}. +## Return the @var{value} of the application data @var{name} for the graphics +## object with handle @var{h}. ## -## @code{getappdata(@var{h})} returns a structure, @var{appdata}, whose fields -## correspond to the appdata properties. +## @var{h} may also be a vector of graphics handles. If no second argument +## @var{name} is given then @code{getappdata} returns a structure, +## @var{appdata}, whose fields correspond to the appdata properties. ## -## @seealso{setappdata, guidata, get, set, getpref, setpref} +## @seealso{setappdata, isappdata, rmappdata, guidata, get, set, getpref, setpref} ## @end deftypefn ## Author: Ben Abbott <bpabbott@mac.com> ## Created: 2010-07-15 -function val = getappdata (h, name) +function value = getappdata (h, name) + + if (nargin < 1 || nargin > 2) + print_usage (); + endif - if (all (ishandle (h)) && nargin == 2 && ischar (name)) + if (! all (ishandle (h(:)))) + error ("getappdata: H must be a scalar or vector of graphic handles"); + endif + + if (nargin == 2) + if (! ischar (name)) + error ("getappdata: NAME must be a string"); + endif + ## FIXME: Is there a better way to handle non-existent appdata ## and missing fields? - val = cell (numel (h), 1); + value = cell (numel (h), 1); appdata = struct (); - for nh = 1:numel (h) + for i = 1:numel (h) try - appdata = get (h(nh), "__appdata__"); + appdata = get (h(i), "__appdata__"); end_try_catch - if (! isfield (appdata, name)) - appdata.(name) = []; + if (isfield (appdata, name)) + value(i) = {appdata.(name)}; + else + value(i) = {[]}; endif - val(nh) = {appdata.(name)}; endfor - if (nh == 1) - val = val{1}; + + if (i == 1) + value = value{1}; endif - elseif (ishandle (h) && numel (h) == 1 && nargin == 1) + + else # nargin == 1 + if (numel (h) != 1) + error ("getappdata: Only one handle H may be used when fetching appdata"); + endif try - val = get (h, "__appdata__"); + value = get (h, "__appdata__"); catch - val = struct (); + value = struct (); end_try_catch - else - error ("getappdata: invalid input"); endif endfunction + +%!test +%! unwind_protect +%! setappdata (0, "%data1%", ones (3), "%data2%", "hello world"); +%! assert (getappdata (0, "%data1%"), ones (3)); +%! assert (getappdata (0, "%data2%"), "hello world"); +%! appdata = getappdata (0); +%! name1 = "%data1%"; name2 = "%data2%"; +%! assert (appdata.(name1), ones (3)); +%! assert (appdata.(name2), "hello world"); +%! unwind_protect_cleanup +%! rmappdata (0, "%data1%", "%data2%"); +%! end_unwind_protect + +## Test input validation +%!error getappdata () +%!error getappdata (1,2,3) +%!error <H must be a scalar .* graphic handle> getappdata (-1, "hello") +%!error <NAME must be a string> getappdata (0, 1) +%!error <Only one handle H may be used when fetching appdata> getappdata ([0 0]) +
--- a/scripts/miscellaneous/isappdata.m +++ b/scripts/miscellaneous/isappdata.m @@ -17,35 +17,55 @@ ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {@var{V} =} isappdata (@var{h}, @var{name}) +## @deftypefn {Function File} {@var{valid} =} isappdata (@var{h}, @var{name}) ## Return true if the named application data, @var{name}, exists for the -## object with handle @var{h}. -## @seealso{getappdata, setappdata, rmappdata} +## graphics object with handle @var{h}. +## +## @var{h} may also be a vector of graphics handles. +## @seealso{getappdata, setappdata, rmappdata, guidata, get, set, getpref, setpref} ## @end deftypefn ## Author: Ben Abbott <bpabbott@mac.com> ## Created: 2010-07-15 -function res = isappdata (h, name) +function valid = isappdata (h, name) - if (! (all (ishandle (h)) && ischar (name))) - error ("isappdata: invalid input"); + if (nargin < 1 || nargin > 2) + print_usage (); endif - for nh = 1:numel (h) - data = get (h(nh)); - if (isfield (data, "__appdata__") && isfield (data.__appdata__, name)) - res(nh) = true; - else - res(nh) = false; - endif + if (! all (ishandle (h(:)))) + error ("isappdata: H must be a scalar or vector of graphic handles"); + elseif (! ischar (name)) + error ("isappdata: NAME must be a string"); + endif + + valid = false (size (h)); + for i = 1:numel (h) + try + appdata = get (h(i), "__appdata__"); + if (isfield (appdata, name)) + valid(i) = true; + endif + end_try_catch endfor endfunction %!test -%! setappdata (0, "hello", "world"); -%! assert (isappdata (0, "hello"), true); -%! assert (isappdata (0, "foobar"), false); +%! unwind_protect +%! setappdata (0, "%hello%", "world"); +%! assert (isappdata (0, "%hello%"), true); +%! assert (isappdata ([0 0], "%hello%"), [true, true]); +%! assert (isappdata (0, "%foobar%"), false); +%! unwind_protect_cleanup +%! rmappdata (0, "%hello%"); +%! end_unwind_protect +## Test input validation +%!error isappdata () +%!error isappdata (1,2,3) +%!error <H must be a scalar .* graphic handle> isappdata (-1, "hello") +%!error <NAME must be a string> isappdata (0, 1) +
--- a/scripts/miscellaneous/rmappdata.m +++ b/scripts/miscellaneous/rmappdata.m @@ -17,9 +17,15 @@ ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {} rmappdata (@var{h}, @var{name}) -## Delete the named application data for the object(s) with -## handle(s) @var{h}. +## @deftypefn {Function File} {} rmappdata (@var{h}, @var{name}) +## @deftypefnx {Function File} {} rmappdata (@var{h}, @var{name1}, @var{name2}, @dots{}) +## Delete the application data @var{name} from the graphics object with handle +## @var{h}. +## +## @var{h} may also be a vector of graphics handles. Multiple application data +## names may be supplied to delete several properties at once. +## +## @seealso{setappdata, getappdata, isappdata} ## @end deftypefn ## Author: Ben Abbott <bpabbott@mac.com> @@ -27,21 +33,28 @@ function rmappdata (h, varargin) - if (! (all (ishandle (h)) && iscellstr (varargin))) - error ("rmappdata: invalid input"); + if (nargin < 2) + print_usage (); + endif + + h = h(:).'; + if (! all (ishandle (h))) + error ("rmappdata: H must be a scalar or vector of graphic handles"); + elseif (! iscellstr (varargin)) + error ("rmappdata: NAME must be a string"); endif - for nh = 1:numel (h) - if (isprop (h(nh), "__appdata__")) - appdata = get (h(nh), "__appdata__"); - for v = 1:numel(varargin) - if (isfield (appdata, varargin{v})) - appdata = rmfield (appdata, varargin{v}); - else - error ("rmappdata: appdata '%s' is not present") - endif - endfor - set (h(nh), "__appdata__", appdata); + for hg = h + if (isprop (hg, "__appdata__")) + appdata = get (hg, "__appdata__"); + vld = isfield (appdata, varargin); + if (! all (vld)) + ## FIXME: Should we bother to error out? Or just silently continue? + missing = varargin{find (! vld, 1)}; + error ("rmappdata: appdata '%s' is not present", missing); + endif + appdata = rmfield (appdata, varargin); + set (hg, "__appdata__", appdata); endif endfor @@ -49,14 +62,21 @@ %!test -%! setappdata (0, "hello", "world"); -%! rmappdata (0, "hello"); -%! assert (isappdata (0, "hello"), false); +%! setappdata (0, "%hello%", "world"); +%! rmappdata (0, "%hello%"); +%! assert (isappdata (0, "%hello%"), false); %!test -%! setappdata (0, "data1", rand (3)); -%! setappdata (0, "data2", {"hello", "world"}); -%! rmappdata (0, "data1", "data2"); -%! assert (isappdata (0, "data1"), false); -%! assert (isappdata (0, "data2"), false); +%! setappdata (0, "%data1%", ones (3)); +%! setappdata (0, "%data2%", {"hello", "world"}); +%! rmappdata (0, "%data1%", "%data2%"); +%! assert (isappdata (0, "%data1%"), false); +%! assert (isappdata (0, "%data2%"), false); +## Test input validation +%!error rmappdata () +%!error rmappdata (1) +%!error <H must be a scalar .* graphic handle> rmappdata (-1, "hello") +%!error <NAME must be a string> rmappdata (0, 1) +%!error <appdata 'foobar' is not present> rmappdata (0, "foobar") +
--- a/scripts/miscellaneous/setappdata.m +++ b/scripts/miscellaneous/setappdata.m @@ -17,11 +17,16 @@ ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {} setappdata (@var{h}, @var{name}, @var{value}) -## Set the named application data to @var{value} for the object(s) with -## handle(s) @var{h}. If the application data with the specified name does -## not exist, it is created. -## @seealso{getappdata, guidata, get, set, getpref, setpref} +## @deftypefn {Function File} {} setappdata (@var{h}, @var{name}, @var{value}) +## @deftypefnx {Function File} {} setappdata (@var{h}, @var{name1}, @var{value1}, @var{name2}, @var{value3}, @dots{}) +## Set the application data @var{name} to @var{value} for the graphics object +## with handle @var{h}. +## +## @var{h} may also be a vector of graphics handles. If the application data +## with the specified @var{name} does not exist, it is created. Multiple +## @var{name}/@var{value} pairs can be specified at a time. +## +## @seealso{getappdata, isappdata, rmappdata, guidata, get, set, getpref, setpref} ## @end deftypefn ## Author: Ben Abbott <bpabbott@mac.com> @@ -29,35 +34,62 @@ function setappdata (h, varargin) - if (! (all (ishandle (h)) && mod (numel (varargin), 2) == 0)) - error ("setappdata: invalid input"); + h = h(:).'; + if (! all (ishandle (h))) + error ("setappdata: H must be a scalar or vector of graphic handles"); + elseif (mod (numel (varargin), 2) != 0) + error ("setappdata: NAME/VALUE arguments must occur in pairs"); endif - for nh = 1:numel (h) - if (! isfield (get (h(nh)), "__appdata__")) - addproperty ("__appdata__", h(nh), "any", struct ()); - endif - appdata = get (h(nh), "__appdata__"); + for hg = h + try + appdata = get (hg, "__appdata__"); + catch + appdata = struct (); + addproperty ("__appdata__", hg, "any", appdata); + end_try_catch + for narg = 1:2:numel (varargin) - if (iscellstr (varargin{narg})) + if (ischar (varargin{narg})) + appdata.(varargin{narg}) = varargin{narg+1}; + elseif (iscellstr (varargin{narg})) ## Handle cell arrays like set() does. - set (h(nh), "__appdata__", appdata); - setappdata (h(nh), vertcat (varargin{narg}', varargin{narg+1}'){:}); - appdata = get (h(nh), "__appdata__"); - elseif (ischar (varargin{narg})) - appdata.(varargin{narg}) = varargin{narg+1}; + set (hg, "__appdata__", appdata); + setappdata (hg, vertcat (varargin{narg}', varargin{narg+1}'){:}); + appdata = get (hg, "__appdata__"); else - error ("setappdata: invalid input"); + error ("setappdata: NAME must be a string or cellstr"); endif endfor - set (h(nh), "__appdata__", appdata); + + set (hg, "__appdata__", appdata); endfor endfunction %!test -%! setappdata (0, "hello", "world"); -%! assert (isappdata (0, "hello"), true); -%! assert (getappdata (0, "hello"), "world"); +%! unwind_protect +%! setappdata (0, "%hello%", "world"); +%! assert (isappdata (0, "%hello%"), true); +%! assert (getappdata (0, "%hello%"), "world"); +%! unwind_protect_cleanup +%! rmappdata (0, "%hello%"); +%! end_unwind_protect +%!test +%! unwind_protect +%! setappdata (0, "%data1%", ones (3), "%data2%", "hello world"); +%! assert (getappdata (0, "%data1%"), ones (3)); +%! assert (getappdata (0, "%data2%"), "hello world"); +%! setappdata (0, "%data1%", zeros (3)); +%! assert (getappdata (0, "%data1%"), zeros (3)); +%! unwind_protect_cleanup +%! rmappdata (0, "%data1%", "%data2%"); +%! end_unwind_protect + +## Test input validation +%!error <H must be a scalar .* graphic handle> rmappdata (-1, "hello") +%!error <NAME must be a string> setappdata (0, 1, 2) +%!error <NAME/VALUE arguments must occur in pairs> setappdata (0, "1") +