## 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
## <http://www.gnu.org/licenses/>.

## h = struct2hdl (str) : builds a figure from the struct "str". The
## struct must contain at least fields : "handle", "type", "children",
## "properties", and "special".If the
## root element of str is not a figure (or root figure),
## builds all needed parents with root default properties   

## Author: pdiribarne <pdiribarne@new-host.home>
## Created: 2012-03-04

function [ h, matchout ] = struct2hdl (hgS, rec = 0, matchin=[])
  fields = { "handle", "type", "children", "properties", "special"};
  if nargin > 3 || ! isstruct(hgS)
    print_usage ();
  elseif ! all (isfield (hgS, fields))
    print_usage ();
  endif

  ## recursion incrementation
  rec ++;
  
  if strcmpi (hgS.type, "figure") || rec == 1
    h = figure ();
  endif
  
  ## main object
  if strcmpi (hgS.type, "axes")
    [h, hgS] = createaxes (hgS, matchin);
  elseif strcmpi (hgS.type, "line")
    h = createline (hgS);
  elseif strcmpi (hgS.type, "patch")
    h = createpatch (hgS);
  elseif strcmpi (hgS.type, "text")
    h = createtext (hgS); 
  elseif strcmpi (hgS.type, "image")
    h = createimage (hgS);
  elseif strcmpi (hgS.type, "surface")
    h = createsurface (hgS);
  elseif strcmpi (hgS.type, "hggroup")
    error ("struct2hdl : hggroup not implemented yet")
  endif
  
  ## children
   
  if ! isempty (h)
    matchout = [matchin [hgS.handle; h]]; # correspondance [original; new] handle identifier
    ## regular children
    temp = matchout;
    ch = hgS.children;
    nch = length (ch);
    ii = 0;
    while nch
      ii++;
      if !any (ii == hgS.special)
        [h2, matchout] = struct2hdl (hgS.children(ii), rec, matchout);
      endif
      nch--;
    endwhile
    
  else
    matchout = matchin;
  endif  
  
  ## paste properties
  setprops (hgS, h, matchout);

endfunction ##struct2hdl

################################################################

function [h, hgSout] = createaxes (hgS, match);
  
  if strcmpi (hgS.properties.tag, "")
    propval = {"position", hgS.properties.position};
    ##propval = {};
    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{:});
    hgS.properties = rmfield (hgS.properties, ["position", hid]);
    ##hgS.properties = rmfield (hgS.properties, hid);
    
  elseif strcmpi (hgS.properties.tag, "legend")
    oldax = hgS.properties.userdata.handle;
    if !isempty (idx = find (oldax == match))
      ax = match(idx+1);
      
      strings = {};
      ## check every legend item candidates created after current axes
      ittyp = {"line", "surface"};
      idx += 1;
      hdls = match (idx:2:end);
      for ii = 1:length (hdls);
        hdl = hdls(ii);
        if any (strcmpi (get(hdl).type, ittyp))
          str = get (hdl, "displayname");
          strings = [strings str];
        endif
      endfor
      
      location = hgS.properties.location;
      
      textpos = hgS.properties.textposition;
 
      show = "on";
      ## show = hgS.properties.visible;
      
      box = "boxoff";
      if strcmp (hgS.properties.box, "on");
        box = "boxon";
      endif
      h = legend (ax, strings, "location", location);
      ##h = legend (textpos);
      legend (box);
      %h = legend ("location", location)
      if !strcmp (show, "on");
        legend ("hide");
      endif
      
      hgS.properties = rmfield (hgS.properties, {"textposition", "visible"});

      hgS.children= [];
    else
      error ("hdl2struct: didn't find an object")
    endif
    
  elseif strcmpi (hgS.properties.tag, "colorbar")
    oldax = hgS.properties.axes;
    if !isempty (idx = find (oldax == match))
      ax = match(idx+1);
      ##posprop = get (ax, "activepositionproperty")
      ##set (ax, "activepositionproperty", "position");
      location = hgS.properties.location;
      h = colorbar ("peer", ax, location);
      ##set (ax, "activepositionproperty", posprop);
      hgS.children= [];
    else
      error ("hdl2struct: didn't find an object")
    endif
       
  endif
  hgSout = hgS;
endfunction ##createaxes

function [h] = createline (hgS);
  h = line ();
endfunction ##createline

function [h] = createpatch (hgS);
  h = patch ();
endfunction ##createpatch

function [h] = createtext (hgS);
  h = text ();
endfunction ##createtext

function [h] = createimage (hgS);
  h = image();
endfunction ##createimage

function [h] = createsurface (hgS);
  h = surface();
endfunction ##createsurface


function [h] = createhg (hgS)
  
endfunction

################################################################

function setprops (hgS, h, match)

  if strcmpi (hgS.properties.tag, "")
    specs = hgS.children(hgS.special);
    hdls = arrayfun (@(x) x.handle, specs);
    nh = length(hdls);
    
    if !nh
      set (h, hgS.properties);
    else
      ## find  props with val == one of special handles
      fields = fieldnames(hgS.properties);
      vals = struct2cell (hgS.properties);
      
      idx = find (cellfun (@(x) valcomp(x, hdls) , vals));

      hgS.properties = rmfield (hgS.properties, fields(idx));
      set (h, hgS.properties);
      
      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
    endif
    
  elseif strcmpi (hgS.properties.tag, "legend")
    oldax = hgS.properties.userdata.handle;
    if !isempty (idx = find (oldax == match))
      #remove all handles and properties such as "location" that redefines
      #the entire legend (and delete "h")
      hgS.properties = rmfield (hgS.properties, ...
                                {"userdata", "xlabel",...
                                 "ylabel", "zlabel", "location", ...
                                 "title", "string", "tag", "box"});
     ##set (h, hgS.properties);
    else
      error ("hdl2struct: didn't find an object")
    endif
    
  elseif strcmpi (hgS.properties.tag, "colorbar")
    oldax = hgS.properties.axes;
    if !isempty (idx = find (oldax == match))
      hgS.properties = rmfield (hgS.properties, ...
                                {"userdata", "xlabel", "position" ...
                                 "ylabel", "zlabel", "location", ...
                                 "title", "axes", "tag"});
      ##set (h, hgS.properties); 
    else
      error ("hdl2struct: didn't find an object")
    endif
    
  endif
  
endfunction
  
function out = valcomp (x, hdls)
  
  if isfloat(x) && isscalar(x)
    out = any (x == hdls);
  else
    out = 0;
  endif
endfunction


%!demo
%! hdl = figure(1234); clf
%! demo "text" 1
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "text" 2
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "text" 3
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "text" 4
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "plotyy" 1
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "plotyy" 3
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "pie" 1
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "pie" 2
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "pie" 3
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 1
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 2
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 3
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 4
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 5
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 7
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 8
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 9
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 10
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 12
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! demo "legend" 13
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);

%!demo
%! hdl = figure(1234); clf
%! subplot(2,2,1:2);hold on
%! plot(rand(1,30),"-db", "markerfacecolor", rand(1,3))
%! plot(rand(1,30)-1,"--*k")
%! plot(rand(1,30)-2,"-ok", "markerfacecolor", rand(1,3))
%! legend ("1st plot", "", "3rd plot", "location", "north")
%! legend ("boxon")
%! subplot(2,2,3);
%! sombrero;
%! colorbar("peer", gca, "NorthOutside")
%! subplot(2,2,4);
%! imagesc (rand (30, 30));
%! text (15,15,'Rotated text', ...
%!      'horizontalalignment','center', 'rotation', 30);
%! str = hdl2struct (1234);
%! hout = struct2hdl (str);
