# HG changeset patch # User Pantxo Diribarne # Date 1342485421 14400 # Node ID 97ce18b62d0f14ec2cc9444557bf021a726d75f9 # Parent 2309812f428edf18222a66376a743fc35bf46c67 New Functions; copyobj.m, hdl2struct.m, struct2hdl.m * copyobj.m: New File. * hdl2struct.m: New File. * struct2hdl.m: New File. * scripts/plot/module.mk: Add new files. * scripts/help/unimplmented.m: Remove copyobj.m from list. diff -r 2309812f428e -r 97ce18b62d0f scripts/help/unimplemented.m --- a/scripts/help/unimplemented.m Mon Jul 16 17:32:27 2012 -0400 +++ b/scripts/help/unimplemented.m Mon Jul 16 20:37:01 2012 -0400 @@ -143,7 +143,6 @@ "condeig", "coneplot", "contourslice", - "copyobj", "createClassFromWsdl", "createSoapMessage", "customverctrl", diff -r 2309812f428e -r 97ce18b62d0f scripts/plot/copyobj.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/copyobj.m Mon Jul 16 20:37:01 2012 -0400 @@ -0,0 +1,127 @@ +## Copyright (C) 2012 pdiribarne +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{hnew} =} copyobj (@var{horig}) +## @deftypefnx {Function File} {@var{hnew} =} copyobj (@var{horig}, @var{hparent}) +## Constructs a copy of the object associated with handle @var{horig} +## and returns a handle, @var{hnew}, to the new object. +## If a parent handle @var{hparent} (root, figure, axes or hggroup) is specified, +## the copied object will be created as a child to @var{hparent}. +## @seealso{findobj, get, set, struct2hdl, hdl2struct} +## @end deftypefn + +## Author: pdiribarne +## Created: 2012-04-01 + +function hout = copyobj (hin, hpar = 0) + + partypes = {"root", "figure", "axes", "hggroup"}; + othertypes = {"line", "patch", "surface", "image", "text"}; + alltypes = [partypes othertypes]; + + if (! ishandle (hin) || nargin > 2) + print_usage (); + elseif (! ishandle (hpar)) + hpar = figure (floor (hpar)); + elseif (! any (strcmpi (get (hpar).type, partypes))) + print_usage (); + endif + + ## compatibility of input handles + kididx = find (strcmp (alltypes, get (hin).type)); + paridx = find (strcmp (alltypes, get (hpar).type)); + + if (kididx <= paridx) + error ("copyobj: %s object can't be children to %s.", + alltypes{kididx}, alltypes{paridx}) + elseif nargin == 1 + str = hdl2struct (hin); + hout = struct2hdl (str); + else + str = hdl2struct (hin); + hout = struct2hdl (str, hpar); + endif +endfunction + +%!test +%! h1 = figure (); +%! set (h1, "visible", "off") +%! x = 0:0.1:2*pi; +%! y1 = sin (x); +%! y2 = exp (x - 1); +%! ax = plotyy (x,y1, x-1,y2, @plot, @semilogy); +%! xlabel ("X"); +%! ylabel (ax(1), "Axis 1"); +%! ylabel (ax(2), "Axis 2"); +%! axes (ax(1)); +%! text (0.5, 0.5, "Left Axis", ... +%! "color", [0 0 1], "horizontalalignment", "center"); +%! axes (ax(2)); +%! text (4.5, 80, "Right Axis", ... +%! "color", [0 0.5 0], "horizontalalignment", "center"); +%! s1 = hdl2struct (h1); +%! h2 = struct2hdl (s1); +%! s2 = hdl2struct (h2); +%! png1 = strcat (tmpnam (), ".png"); +%! png2 = strcat (tmpnam (), ".png"); +%! unwind_protect +%! print (h1, png1) +%! [img1, map1, alpha1] = imread (png1); +%! print (h2, png2) +%! [img2, map2, alpha2] = imread (png2); +%! unwind_protect_cleanup +%! unlink (png1); +%! unlink (png2); +%! end_unwind_protect +%! assert (img1, img2) +%! assert (map1, map2) +%! assert (alpha1, alpha2) + +%!demo +%! hdl = figure (1234); +%! clf () +%! hold on +%! x = 1:10; +%! y = x.^2; +%! dy = 2 * (.2 * x); +%! y2 = (x - 3).^2; +%! hg = errorbar (x, y, dy,'#~'); +%! set (hg, 'marker', '^', 'markerfacecolor', rand(1,3)) +%! plot (x, y2, 'ok-') +%! legend ('errorbar', 'line') +%! hout = copyobj (1234); + +%!demo +%! hdl = figure (1234); +%! clf () +%! subplot (2, 2, 1); +%! hold on +%! [C, H] = contourf (rand(10, 10)); +%! colorbar +%! subplot (2, 2, 2); +%! hold on +%! quiver (rand(10, 10), rand(10, 10)) +%! subplot (2, 2, 3); +%! colormap (jet (64)) +%! sombrero; +%! colorbar('peer', gca, 'NorthOutside') +%! subplot (2, 2, 4); +%! imagesc (rand (30, 30)); +%! text (15, 15, 'Rotated text', ... +%! 'HorizontAlalignment', 'Center', 'Rotation', 30); +%! hout = copyobj (1234); + diff -r 2309812f428e -r 97ce18b62d0f scripts/plot/hdl2struct.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/hdl2struct.m Mon Jul 16 20:37:01 2012 -0400 @@ -0,0 +1,166 @@ +## Copyright (C) 2012 pdiribarne +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{s} =} hdl2struct (@var{h}) +## Returns a structure, @var{s}, whose fields describe the properties +## of the object, and its children, associated with the handle, @var{h}. +## The fields of the structure, @var{s}, are "type", "handle", "properties", +## "children" and "special". +## @seealso{findobj, get, set, struct2hdl} +## @end deftypefn + +## Author: pdiribarne +## Created: 2012-03-04 + +function hgS = hdl2struct (h) + if (nargin != 1 || !ishandle (h)) + print_usage (); + endif + + hiddenh = get (0, "showhiddenhandles"); + if strcmp (hiddenh, "on") + set (0, "showhiddenhandles", "off"); + endif + + ## main object + main = get (h); + hgS.handle = h; + hgS.type = main.type; + hgS.properties = getprops (h); + hgS.children = []; + hgS.special = []; + + ## sweep all children but legends, colorbars, uimenu and hggroup children + ## in reverse order + kids = main.children; + lg = findobj (h, "-depth", 1, "tag", "legend"); + cb = findobj (h, "-depth", 1, "tag", "colorbar"); + ui = findobj (h, "-depth", 1, "type", "uimenu"); + nkids = length (kids); + ii = 0; + while nkids + if (! any (kids (nkids) == lg) && !any (kids (nkids) == cb) + && ! any (kids (nkids) == ui) && !strcmpi (main.type, "hggroup")) + ii++; + hgS.children(ii) = hdl2struct(kids(nkids)); + endif + nkids--; + endwhile + + ## add non "children" children objects (title, xlabel, ...) and + ## hggroup children and tag theim in "special" + special = []; + if (strcmpi (main.type, "hggroup")) + special = main.children; + endif + special = [special getspecial(h)]; + nsp = length (special); + while nsp + ii++; + hgS.children(ii) = hdl2struct (special(nsp)); + hgS.special(nsp) = ii; + nsp--; + endwhile + + ## look for legends and colorbars among "main"'s brothers and add them + ## to the children list + if (strcmpi (main.type, "axes")) + par = main.parent; + lg = findobj (par, "-depth", 1, "tag", "legend"); + if !isempty (lg) + idx = arrayfun (@(x) get(x).userdata.handle(end) == h, lg); + lg = lg(find(idx)); + endif + nlg = length (lg); + if nlg == 1 + ii++; + hgS.children(ii) = hdl2struct (lg); + elseif (nlg > 1) + error ("hdl2struct: more than one legend found") + endif + + cb = findobj (par, "-depth", 1, "tag", "colorbar"); + if (! isempty (cb)) + idx = arrayfun (@(x) get(x).axes == h, cb); + cb = cb(find(idx)); + endif + + ncb = length (cb); + if (ncb == 1) + ii++; + hgS.children(ii) = hdl2struct(cb); + elseif (nlg > 1) + error ("hdl2struct: more than one colorbar found") + endif + endif + + set (0, "showhiddenhandles", hiddenh); + +endfunction + +function hdlist = getspecial (h) + obj = get (h); + ## return handles to special children + fields = fieldnames (obj); + hdlist = []; + + regkids = get ( h, "children"); + set (0, "showhiddenhandles", "on") + allkids = get ( h, "children"); + set (0, "showhiddenhandles", "off") + speckids = arrayfun (@(x) ! any (x == regkids), allkids); + hdlist = allkids (find (speckids)); + hdlist = reshape (hdlist, 1, numel (hdlist)); + +endfunction + +function prpstr = getprops (h) + obj = get (h); + ## get usefull properties rejecting readonly, children, handles ... + fields = fieldnames (obj); + hdlist = []; + + forbid = {"beingdeleted", "busyaction", "buttondownfcn", ... + "children", "clipping", "createfcn", ... + "deletefcn", "handlevisibility", "hittest", ... + "interruptible", "parent", "selected" ,... + "selectionhighlight", "type", "__modified__", ... + "uicontextmenu", "__graphics_toolkit__", "currentaxes", ... + "currentcharacter", "currentobject","tightinset", ... + "currentpoint", "extent"}; + + nflds = length (fields); + ii = 0; + while nflds + prop = fields{nflds}; + val = obj.(fields{nflds}); + ii++; + if !any (strcmp (prop, forbid)) + prpstr.(prop) = val; + endif + nflds--; + endwhile + + ## hidden properties + hidden = {"autopos_tag", "looseinset"}; + for ii = 1:numel (hidden) + if (isprop (h, hidden{ii})) + prpstr.(hidden{ii}) = get (h, hidden{ii}); + endif + endfor +endfunction + diff -r 2309812f428e -r 97ce18b62d0f scripts/plot/module.mk --- a/scripts/plot/module.mk Mon Jul 16 17:32:27 2012 -0400 +++ b/scripts/plot/module.mk Mon Jul 16 20:37:01 2012 -0400 @@ -80,6 +80,7 @@ plot/contour3.m \ plot/contourc.m \ plot/contourf.m \ + plot/copyobj.m \ plot/cylinder.m \ plot/daspect.m \ plot/diffuse.m \ @@ -112,6 +113,7 @@ plot/gtext.m \ plot/guidata.m \ plot/guihandles.m \ + plot/hdl2struct.m \ plot/hggroup.m \ plot/hidden.m \ plot/hist.m \ @@ -172,6 +174,7 @@ plot/stairs.m \ plot/stem.m \ plot/stem3.m \ + plot/struct2hdl.m \ plot/subplot.m \ plot/surf.m \ plot/surface.m \ diff -r 2309812f428e -r 97ce18b62d0f scripts/plot/struct2hdl.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/struct2hdl.m Mon Jul 16 20:37:01 2012 -0400 @@ -0,0 +1,615 @@ +## Copyright (C) 2012 pdiribarne +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{h} =} struct2hdl (@var{s}) +## @deftypefnx {Function File} {@var{h} =} struct2hdl (@var{s}, @var{p}) +## @deftypefnx {Function File} {@var{h} =} struct2hdl (@var{s}, @var{p}, @var{hilev}) +## Constructs an object from the structure @var{s}. The structure must +## contain the fields "handle", "type", "children", "properties", and +## "special". If the handle of an existing figure or axes is specified, +## @var{p}, the new object will be created as a child to that object. +## If no object handle is provided, then a new figure and the necessary +## children will be constructed using the default object values from +## the root figure. +## +## A third boolean argument @var{hilev} can be passed to specify wether +## the function should try to preserve listeners/calbacks e.g for +## legends or hggroups. Default is false. +## @seealso{findobj, get, hdl2struct, set} +## @end deftypefn + +## Author: pdiribarne +## Created: 2012-03-04 + +function [ h, matchout ] = struct2hdl (hgS, matchin=[], hilev = false) + + fields = { "handle", "type", "children", "properties", "special"}; + partypes = {"root", "figure", "axes", "hggroup"}; + othertypes = {"line", "patch", "surface", "image", "text"}; + alltypes = [partypes othertypes]; + + if (nargin > 3 || ! isstruct (hgS)) + print_usage (); + elseif (! all (isfield (hgS, fields))) + print_usage (); + elseif (isscalar (matchin)) + if (! ishandle (matchin)) + error ("struct2hdl: argument #2 is not a handle to graphic object") + endif + if (any (strcmp (get (matchin).type, partypes))) + paridx = find (strcmp (get (matchin).type, alltypes)); + kididx = find (strcmp (hgS.type, alltypes)); + if (kididx <= paridx) + error ("struct2hdl: incompatible input handles") + endif + else + error ("struct2hdl: %s object can't be parent object", get (matchin).type) + endif + hpar = matchin; + matchin = [NaN; hpar]; + ## create appropriate parent if needed + if (any (strcmp (hgS.type, othertypes))) + for ii = (paridx+1) : (numel (partypes)-1) + eval (["hpar = " partypes{ii} "(\"parent\", hpar);"]); + matchin = [matchin [NaN; hpar]]; + endfor + elseif (any (strcmp (hgS.type, {"hggroup", "axes"}))) + for ii = (paridx+1) : (kididx-1) + eval (["hpar = " partypes{ii} "(\"parent\", hpar);"]); + matchin = [matchin [NaN; hpar]]; + endfor + else + par = NaN; + endif + elseif (isempty (matchin)) + if (any (strcmp (hgS.type, othertypes))) + par = axes (); + elseif (any (strcmp (hgS.type, {"hggroup", "axes"}))) + par = figure (); + else + par = NaN; + endif + matchin = [NaN; par]; + endif + ## read parent (last column) in matchin and remove it if duplicate + par = matchin (2,end); + tst = find (matchin (2,:) == par); + if (numel (tst) > 1) + matchin = matchin (1:2, 1:(tst(end)-1)); + endif + + ## create object + if (strcmpi (hgS.type, "root")) + h = 0; + hgS.properties = rmfield (hgS.properties, ... + {"callbackobject", "commandwindowsize", ... + "screendepth", "screenpixelsperinch", ... + "screensize"}); + elseif (strcmpi (hgS.type, "figure")) + h = figure (); + elseif (strcmpi (hgS.type, "axes")) + ## legends and colorbars are "transformed" in normal axes + ## if hilev is not requested + if (! hilev) + if (strcmp (hgS.properties.tag, "legend")) + hgS.properties.tag = ""; + hgS.properties.userdata = []; + par = gcf; + elseif (strcmp (hgS.properties.tag, "colorbar")) + hgS.properties.tag = ""; + hgS.properties.userdata = []; + par = gcf; + endif + endif + + [h, hgS] = createaxes (hgS, matchin, par); + elseif (strcmpi (hgS.type, "line")) + h = createline (hgS, par); + elseif (strcmpi (hgS.type, "patch")) + [h, hgS] = createpatch (hgS, par); + elseif (strcmpi (hgS.type, "text")) + h = createtext (hgS, par); + elseif (strcmpi (hgS.type, "image")) + h = createimage (hgS, par); + elseif (strcmpi (hgS.type, "surface")) + h = createsurface (hgS, par); + elseif (strcmpi (hgS.type, "hggroup")) + [h, hgS, matchin] = createhg (hgS, matchin, par, hilev); + endif + + ## children + matchin = [matchin [hgS.handle; h]]; # [original; new] + kids = hgS.children; + nkids = length (kids); + ii = 0; + while nkids + ii++; + if (! any (ii == hgS.special)) + [h2, matchin] = struct2hdl (hgS.children(ii), + [matchin [hgS.handle; h]], hilev); + endif + nkids--; + endwhile + + ## paste properties + setprops (hgS, h, matchin, hilev); + + matchout = matchin; + +endfunction + +function [h, hgSout] = createaxes (hgS, matchin, par); + ## regular axes + if (strcmpi (hgS.properties.tag, "")) + propval = {"position", hgS.properties.position}; + hid = {"autopos_tag", "looseinset"}; + for ii = 1:numel (hid) + prop = hid{ii}; + if (isfield (hgS.properties, prop)) + val = hgS.properties.(prop); + propval = [propval, prop, val]; + endif + endfor + h = axes (propval{:}, "parent", par); + + if isfield (hgS.properties, "__plotyy_axes__") + plty = hgS.properties.__plotyy_axes__; + addproperty ("__plotyy_axes__", h, "any") + tmp = [matchin [hgS.handle; h]]; + tst = arrayfun (@(x) any (plty == x), tmp (1:2:end)); + if sum (tst) == numel (plty) + for ii = 1:numel (plty) + plty(ii) = tmp (find (tmp == plty(ii)) + 1); + endfor + for ii = 1:numel (plty) + set (plty(ii), "__plotyy_axes__", plty); + endfor + endif + hgS.properties = rmfield (hgS.properties, "__plotyy_axes__"); + endif + + ## delete non-default and already set properties + fields = fieldnames (hgS.properties); + tst = cellfun (@(x) isprop (h, x), fields); + hgS.properties = rmfield (hgS.properties, fields(find (tst == 0))); + + elseif (strcmpi (hgS.properties.tag, "legend")) + ## legends + oldax = hgS.properties.userdata.handle; + idx = find (matchin == oldax); + newax = matchin(idx+1); + strings = {}; + kids = hgS.children; + kids(hgS.special) = []; + oldh = unique (arrayfun (@(x) x.properties.userdata(end), kids)); + for ii = 1:length (oldh) + idx = find (matchin(1:2:end) == oldh(ii)) * 2; + if (! isempty (idx)) + newh(ii) = matchin (idx); + if (! strcmp (get (newh(ii), "type"), "hggroup")) + str = get (newh(ii), "displayname"); + strings = [strings str]; + else + str = get (get (newh(ii), "children")(1), "displayname"); + strings = [strings str]; + endif + else + error ("struct2hdl: didn't find a legend item") + endif + endfor + location = hgS.properties.location; + orientation = hgS.properties.orientation; + textpos = hgS.properties.textposition; + box = hgS.properties.box; + + h = legend (newax, newh, strings, "location", location, ... + "orientation", orientation); + set (h, "textposition", textpos); # bug makes "textposition" + # redefine the legend + h = legend (newax, newh, strings, "location", location, ... + "orientation", orientation); + ## box + if (strcmp (box, "on")) + legend boxon + endif + + ## visibility + tst = arrayfun (@(x) strcmp (x.properties.visible, "on"), kids); + if !any (tst) + legend ("hide"); + endif + + ## remove all properties such as "textposition" that redefines + ## the entire legend. Also remove chidren + hgS.properties = rmfield (hgS.properties, ... + {"userdata", "xlabel",... + "ylabel", "zlabel", "location", ... + "title", "string","orientation", ... + "visible", "textposition"}); + + hgS.children = []; + + elseif (strcmpi (hgS.properties.tag, "colorbar")) + ## colorbar + oldax = hgS.properties.axes; + if (! isempty (idx = find (oldax == matchin))) + ax = matchin(idx+1); + location = hgS.properties.location; + h = colorbar ("peer", ax, location); + hgS.properties = rmfield (hgS.properties, ... + {"userdata", "xlabel" ... + "ylabel", "zlabel", ... + "title", "axes"}); + hgS.children= []; + else + error ("hdl2struct: didn't find an object") + endif + endif + hgSout = hgS; +endfunction + +function [h] = createline (hgS, par); + h = line ("parent", par); + addmissingprops (h, hgS.properties); +endfunction + +function [h, hgSout] = createpatch (hgS, par); + prp.faces = hgS.properties.faces; + prp.vertices = hgS.properties.vertices; + prp.facevertexcdata = hgS.properties.facevertexcdata; + h = patch (prp); + set (h, "parent", par); + hgS.properties = rmfield (hgS.properties, + {"faces", "vertices", "facevertexcdata"}); + addmissingprops (h, hgS.properties); + hgSout = hgS; +endfunction + +function [h] = createtext (hgS, par); + h = text ("parent", par); + addmissingprops (h, hgS.properties) +endfunction + +function [h] = createimage (hgS, par); + h = image ("parent", par); + addmissingprops (h, hgS.properties) +endfunction + +function [h] = createsurface (hgS, par); + h = surface ("parent", par); + addmissingprops (h, hgS.properties) +endfunction + +function [h, hgSout, matchout] = createhg (hgS, matchin, par, hilev) + ## Here we infer from properties the type of hggroup we should build + ## an call corresponding high level functions + ## We manually set "hold on" to avoid next hggroup be deleted + ## the proper value of axes "nextplot" will finally be recovered + + hold on; + if (hilev) + [h, hgS, matchin] = createhg_hilev (hgS, matchin, par); + if (numel (hgS.children) != numel (get (h).children)) + warning (["struct2hdl: couldn't infer the hggroup type. ", ... + "Will build objects but listener/callback functions ", ... + "will be lost"]); + if isfield (h, "bargroup") + delete (get (h).bargroup); + else + delete (h); + endif + h = hggroup ("parent", par); + addmissingprops (h, hgS.properties); + hgS.special = []; + else + oldkids = hgS.children; + newkids = get (h).children; + nkids = numel (oldkids); + ii = 1; + while nkids + matchin = [matchin [oldkids(ii++).handle; newkids(nkids--)]]; + endwhile + endif + else + h = hggroup ("parent", par); + addmissingprops (h, hgS.properties); + hgS.special = []; + endif + hgSout = hgS; + matchout = matchin; +endfunction + +function [h, hgSout, matchout] = createhg_hilev (hgS, matchin, par) + fields = hgS.properties; + if (isfield (fields, "contourmatrix")) + ## contours + xdata = hgS.properties.xdata; + ydata = hgS.properties.ydata; + zdata = hgS.properties.zdata; + levellist = hgS.properties.levellist; + textlist = hgS.properties.textlist; + + ## contour creation + if (isempty (hgS.children(1).properties.zdata)) + if (strcmpi (hgS.properties.fill, "on")) + [cm2, h] = contourf (xdata, ydata, zdata, levellist); + else + [cm2, h] = contour (xdata, ydata, zdata, levellist); + endif + + ## labels + if (strcmpi (hgS.properties.showtext, "on")) + clabel (cm2, h, textlist); + endif + else + [cm2, h] = contour3 (xdata, ydata, zdata, levellist); + endif + + ## delete already set properties and children + hgS.properties = rmfield (hgS.properties, ... + {"xdata", "ydata", "zdata", ... + "contourmatrix", "levellist", ... + "fill", "labelspacing", ... + "levellistmode", "levelstep", ... + "levelstepmode", "textlist"... + "textlistmode" , "textstep", ... + "textstepmode", "zlevel", ... + "zlevelmode"}); + + elseif (isfield (fields, "udata") && isfield (fields, "vdata")) + ## quiver + xdata = hgS.properties.xdata; + ydata = hgS.properties.ydata; + + udata = hgS.properties.udata; + vdata = hgS.properties.vdata; + + h = quiver (xdata, ydata, udata, vdata); + + ## delete already set properties and children + hgS.properties = rmfield (hgS.properties, ... + {"xdata", "ydata", "zdata", ... + "xdatasource", "ydatasource", "zdatasource", ... + "udata", "vdata", "wdata", ... + "udatasource", "vdatasource", "wdatasource"}); + + elseif (isfield (fields, "format")) + ##errorbar + form = hgS.properties.format; + xdata = hgS.properties.xdata; + ydata = hgS.properties.ydata; + xldata = hgS.properties.xldata; + ldata = hgS.properties.ldata; + xudata = hgS.properties.xudata; + udata = hgS.properties.udata; + + switch form + case "xerr" + h = errorbar (xdata, ydata, xldata, xudata, ">"); + case "yerr" + h = errorbar (xdata, ydata, ldata, udata, "~"); + case "xyerr" + h = errorbar (xdata, ydata, xldata, xudata, ldata, udata, "~>"); + case "box" + h = errorbar (xdata, ydata, xldata, xudata, "#"); + case "boxy" + h = errorbar (xdata, ydata, ldata, udata, "#~"); + case "boxxy" + h = errorbar (xdata, ydata, xldata, xudata, ldata, udata, "#~>"); + otherwise + error ("struct2hdl: couldn't guess the errorbar format") + endswitch + ## delete already set properties + hgS.properties = rmfield (hgS.properties, ... + {"xdata", "ydata", ... + "xldata", "ldata", ... + "xudata", "udata", ... + "xldatasource", "ldatasource", ... + "xudatasource", "udatasource", ... + "format"}); + + elseif (isfield (fields, "bargroup")) + ## bar plot + ## FIXME - here we don't have access to brothers so we first create all + ## the barseries of the bargroup (but the last), then retrieve information, + ## and rebuild the whole bargroup. + ## The duplicate are deleted after calling "setprops" + + bargroup = hgS.properties.bargroup; + oldh = hgS.handle; + + temp = arrayfun (@(x) any(x == bargroup), [matchin(1:2:end) oldh]); + tst = sum (temp) == length (bargroup); + + if (isscalar (bargroup) || !tst) + xdata = hgS.properties.xdata; + ydata = hgS.properties.ydata; + + h = bar (xdata, ydata); + + ## delete already set properties, + hgS.properties = rmfield (hgS.properties, ... + {"xdata", "ydata", ... + "xdatasource", "ydatasource", ... + "bargroup", ... + "barwidth", "baseline"}); + else + xdata = []; + ydata = []; + + ##build x/y matrix + nbar = length (bargroup); + tmp = struct ("handle", NaN,"type", "", "children", [], "special", []); + for ii = 1:(nbar - 1) + idx = find (matchin(1:2:end) == bargroup(ii)) * 2; + hdl = matchin (idx); + xdata = [xdata get(hdl).xdata]; + ydata = [ydata get(hdl).ydata]; + tmp.children(ii) = hdl2struct (hdl); + endfor + + xdata = [xdata hgS.properties.xdata]; + ydata = [ydata hgS.properties.ydata]; + width = hgS.properties.barwidth; + h = bar (ydata, width); + + ## replace previous handles in "match", copy props and delete redundant + for ii = 1:(nbar - 1) + props = tmp.children(ii).properties; + bl = props.baseline; + tmp.children(ii).properties = rmfield (props, {"baseline", "bargroup"}); + setprops (tmp.children(ii), h(ii), matchin, 1); + delete (tmp.children(ii).handle); + delete (bl); + idxpar = find (matchin == tmp.children(ii).handle); + matchin (idxpar) = h(ii); + idxkid = idxpar - 2; + matchin (idxkid) = get (h(ii), "children"); + endfor + matchin (2,((end-nbar+2):end)) = h (1:(end-1)); + h = h (end); + + ## delete already set properties , + hgS.properties = rmfield (hgS.properties, ... + {"xdata", "ydata", "bargroup"... + "barwidth", "baseline"}); + endif + elseif (isfield (fields, "baseline")) + ## stem plot + xdata = hgS.properties.xdata; + ydata = hgS.properties.ydata; + + h = stem (xdata, ydata); + + ## delete already set properties, + hgS.properties = rmfield (hgS.properties, ... + {"xdata", "ydata", ... + "xdatasource", "ydatasource", ... + "baseline"}); + elseif (isfield (fields, "basevalue")) + ## area plot + xdata = hgS.properties.xdata; + ydata = hgS.properties.ydata; + level = hgS.properties.basevalue; + + h = area (xdata, ydata, level); + + ## delete already set properties, + hgS.properties = rmfield (hgS.properties, ... + {"xdata", "ydata", ... + "xdatasource", "ydatasource"}); + else + warning ("struct2hdl: couldn't infer the hggroup type. Will build objects but listener/callback functions will be lost"); + h = hggroup ("parent", par); + addmissingprops (h, hgS.properties); + hgS.special = []; # children will be treated as normal children + endif + hgSout = hgS; + matchout = matchin; +endfunction + +function setprops (hgS, h, matchin, hilev) + more off + if (strcmpi (hgS.properties.tag, "")) + specs = hgS.children(hgS.special); + hdls = arrayfun (@(x) x.handle, specs); + nh = length(hdls); + msg = ""; + if (! nh) + set (h, hgS.properties); + else + ## Specials are objects that where automatically constructed with + ## current object. Among them are "x(yz)labels", "title", high + ## level hggroup children + fields = fieldnames (hgS.properties); + vals = struct2cell (hgS.properties); + idx = find (cellfun (@(x) valcomp(x, hdls) , vals)); + hgS.properties = rmfield (hgS.properties, fields(idx)); + + ## set all properties but special handles + set (h, hgS.properties); + + ## find props with val == (one of special handles) + nf = length (idx); + fields = fields(idx); + vals = vals(idx); + while nf + field = fields{nf}; + idx = find (hdls == vals{nf}); + spec = specs(idx); + if (isprop (h, field)) + h2 = get (h , field); + set (h2, spec.properties); + endif + nf--; + endwhile + + ## If hggroup children were created by high level functions, + ## copy only usefull properties. + if (hilev) + if (strcmpi (hgS.type, "hggroup")) + nold = numel (hgS.children); + nnew = numel (get(h).children); + + if (nold == nnew) + hnew = get(h).children; + ii = 1; + while ii <= nnew + try + set (hnew (ii), "displayname", ... + hgS.children(ii).properties.displayname); + catch + sprintf ("struct2hdl: couldn't set hggroup children #%d props.", ii) + end_try_catch + ii ++; + endwhile + + else + error ("struct2hdl: non-conformant number of children in hgggroup") + endif + endif + endif + endif + + elseif (strcmpi (hgS.properties.tag, "legend") + || strcmpi (hgS.properties.tag, "colorbar")) + set (h, hgS.properties); + endif + +endfunction + +function out = valcomp (x, hdls) + if (isfloat(x) && isscalar(x)) + out = any (x == hdls); + else + out = 0; + endif +endfunction + +function addmissingprops (h, props) + hid = {"autopos_tag", "looseinset"}; + oldfields = fieldnames (props); + curfields = fieldnames (get (h)); + missing = cellfun (@(x) !any (strcmp (x, curfields)), oldfields); + idx = find (missing); + for ii = 1:length(idx) + prop = oldfields{idx(ii)}; + if (! any (strcmp (prop, hid))) + addproperty (prop, h, "any"); + endif + endfor +endfunction