% TREEGUI for exploring objects in memory
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DESCRIPTION: TREEGUI builds a tree visual structure to explore objects in
%              memory; this is an optimized version of the ltpda_explorer
%              tree object to explore inside structs, and it's meant to be
%              implemented into the repoGUI.
%
% CALL:    treegui;
%
% VERSION: $Id: cb_treegui.m,v 1.3 2009/07/29 16:19:38 nicola Exp $
%
% HISTORY: 15-02-09 N Tateo
%             Creation
%
% NOTE:      The idea and the core source code are taken from:
%            Hassan Lahdili (hassan.lahdili@crc.ca)
%            Communications Research Centre (CRC) | Advanced Audio Systems (AAS)
%            www.crc.ca | www.crc.ca/aas
%            Ottawa. Canada
%            CRC Advanced Audio Systems - Ottawa 16/02/2005 2004-2005
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function tree = cb_treegui(varargin)
   
  prefs = getappdata(0, 'LTPDApreferences');
  fontsize = prefs.repository.fontsize;

  tree_name = 'Workspace';
  obj_value = {};
  obj_name  = {};
  
% %   if nargin==0
%      % Define figure
%      fig_name = 'Variables in workspace';
%      fig_position = [150 150 400 600];
%      fig = figure('NumberTitle','off', 'Toolbar','none', 'name',fig_name, 'Color','w', 'ToolBar','none',...
%         'NextPlot','new', 'MenuBar','none', 'Position',fig_position);
%      treeSize = [.01 .07 .98 .92];
% %   else   fig = gcf; treeSize = varargin{1};
% %   end

  fig = gcf;
  treeSize = [0.025   1-2*0.025-0.55   0.3   0.5];
  

  % Read the objects from the 'base' workspace

   ws_vars   = evalin('base','whos');
     
  % Only ltpda_user_classes and common structs are shown:
  accepted_classes = [utils.helper.ltpda_userclasses(), 'struct'];
  for ii=numel(ws_vars):-1:1
     if ~ismember(ws_vars(ii).class,accepted_classes)
        ws_vars(ii)=[];
     end
  end
  clear accepted_classes
  
  for ii=1:length(ws_vars)

      obj = evalin('base', ws_vars(ii).name);

      if numel(obj) == 1
        obj_value{end+1} = obj;
        obj_name{end+1}  = ws_vars(ii).name;

      else
      % the ao in the workspace is a vector
        [n,m] = size(obj);
        if n == 1 || m == 1
          for jj=1:length(obj)
            obj_value{end+1} = obj(jj);
            obj_name{end+1}  = [ws_vars(ii).name '(' num2str(jj) ')'];
          end
        elseif n > 1 && m > 1
        % the ao in the workspace is a matrix
          for gg = 1:n
            for hh = 1:m
              obj_value{end+1} = obj(gg,hh);
              obj_name{end+1}  = [ws_vars(ii).name '(' num2str(gg) ',' num2str(hh) ')'];
            end
          end

        else
          error ('### This should not happen: not scalar, nor vector, nor matrix?');
        end

      end
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %           Define the tree           %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  root = uitreenode('v0', tree_name, tree_name, [], false);
  tree = uitree('v0',fig,  'Root',root,  'ExpandFcn', @myExpfcn4);
  set(tree, 'Units', 'normalized')
  set(tree,'MultipleSelectionEnabled',1)
  drawnow;
  set(tree, 'position', treeSize);
  set(tree, 'NodeWillExpandCallback', @nodeWillExpand_cb4); %, ...
            %'NodeSelectedCallback',   @nodeSelected_cb4);
         
  % assignin('base','tree',tree)
  tmp = tree.FigureComponent;
  cell_Data = cell(3,1);
  

  cell_Data{1} = obj_value;
  cell_Data{2} = root.getRoot;
  cell_Data{3} = obj_name;
  set(tmp, 'UserData', cell_Data);
  
  nodeWillExpand_cb4(tree,[],root);
  myExpfcn4(tree);

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function nodes = myExpfcn4(tree,varargin)

  tmp = tree.FigureComponent;
  S = get(tmp, 'UserData');
  s = S{1};
  cNode = S{2};
  [val, cNode] = getcNodevalue(cNode, s);
  ltpda_user_classes = utils.helper.ltpda_userclasses();
  
  if numel(val)==1 && utils.helper.isobject(val)
     newVal = struct();
     allfields = fieldnames(val);
     for kk=numel(allfields):-1:1
        if ismember(allfields{kk},ltpda_user_classes),   newVal.(allfields{kk}) = val.(allfields{kk}); end
     end
     val = newVal;
     clear newVal
  end
  [n,m] = size(val);
  count = 0;

  %%% Vector or Matrix
  if m>1 || n>1
     
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%% Vector
    if m==1 || n==1
      L = length(val);

      for J = 1:L
        count = count + 1;
        cNode = S{2};
        
        iconpath = setIconPath(val{J});
        if ismember(class(val{J}),ltpda_user_classes), isLeaf = 1;
        else isLeaf = 0;
        end

%         disp('--- Running vector')
        level = cNode.getLevel;
        fname = strcat(cNode.getValue, '(', num2str(J),')');
        if level==0 && ~isempty(S{3}) && numel(S{3}) == numel(S{1})
          node_str = S{3}(J);
        else
          node_str = fname;
        end
        nodes(count) =  uitreenode('v0',fname, node_str, iconpath, isLeaf);
      end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      %%% Matrix
    else
      for ii=1:n
        for jj=1:m
          count = count + 1;
          cNode = S{2};
%           disp('--- Running matrix')
          iconpath = setIconPath(val{ii,jj});
          if ismember(class(val{ii,jj}),ltpda_user_classes), isLeaf = 1;
          else isLeaf = 0;
          end
          fname = [cNode.getValue '(' num2str(ii) ',' num2str(jj) ')'];
          nodes(count) =  uitreenode('v0',fname, fname, iconpath, isLeaf);
        end
      end
    end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%% Struct, Object or single value
  else
    %%%
%     val = val;
    if ~isempty(val)
      fnames = fieldnames(val);
    else
      fnames = {};
    end

    for i=1:length(fnames)
      count = count + 1;
%       disp('--- Running else')
      x = val.(fnames{i});
      if iscell(x), x = x{1}; end

      if isstruct(x), isLeaf = 0;
      else isLeaf = 1;
      end
      iconpath = setIconPath(x);
      nodes(count) = uitreenode('v0',fnames{i}, fnames{i}, iconpath, isLeaf);

    end
  end
  
  if (count == 0)
    nodes = [];
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function cNode = nodeWillExpand_cb4(tree,ev,varargin)
  if isempty(ev) && nargin ==3
     cNode = varargin{1}.getRoot;
  else
     cNode = ev.getCurrentNode;
  end
  tmp = tree.FigureComponent;
  cell_Data = get(tmp, 'UserData');
  cell_Data{2} = cNode;
  set(tmp, 'UserData', cell_Data);

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [val, displayed, cNode] = getcNodevalue(cNode, s)
   
%    disp('------- Running getcNodevalue ')
  fields = {};
  while cNode.getLevel ~=0
    fields = [fields; cNode.getValue];
    c = findstr(cNode.getValue, '(');
    if ~isempty(c) && cNode.getLevel ~=0
      cNode = cNode.getParent;
    end

    if  cNode.getLevel ==0, break; end
    cNode = cNode.getParent;
  end
  val = s;

  if ~isempty(fields)
    L=length(fields);
    displayed = fields{L};
    % create the variable: displayed
    for j = L-1:-1:1
      displayed = strcat(displayed, '.', fields{j});
    end

    for i = L:-1:1
      field = fields{i};
      von = findstr(field,'(');
      bis = findstr(field,')');
      if ~isempty(von)

        idx = field(von+1:bis-1);
        field = field(1:von-1);
        if (strcmp(field, cNode.getValue))
          cmd = sprintf('val = val(%s);',idx);
          eval(cmd);
          if iscell(val) && numel(val) == 1
            val = val{1};
          else
            error('################');
          end
        else

          cmd = sprintf('val = getfield(val, field, {%s});',idx);
          eval(cmd);
          if iscell(val) && numel(val) == 1
            val = val{1};
          end

        end

      else
        if iscell(val) && numel(val) == 1
          val = val{1};
        elseif numel(val) ~= 1
          error('################ MAch mich neu');
        end
        val = val.(field);
      end
    end
  else
    displayed = cNode.getValue;
    if iscell(val) && numel(val) == 1
      val = val{1};
    else
    end
    return;
  end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function iconpath = setIconPath(val)
  % Set the path to the *.gif files
  % This is the current path of this function + 'exp_struct_icons'
        pth = '';
        eval (sprintf('pth = which(''%s'');',mfilename))
        index = find(pth==filesep, 1, 'last');
        pth = pth(1:index);
        pth = [pth 'exp_struct_icons' filesep];
   
        if isa(val, 'ao')
           iconpath =[pth,'analysis_object.gif'];
        elseif isa(val, 'tsdata')
           iconpath =[pth,'ts_data.gif'];
        elseif isa(val, 'fsdata')
           iconpath =[pth,'fs_data.gif'];
        elseif isa(val, 'xydata')
           iconpath =[pth,'xy_data.gif'];
        elseif isa(val, 'cdata')
           iconpath =[pth,'c_data.gif'];
        elseif isa(val, 'plist')
           iconpath =[pth,'plist.gif'];
        elseif isstruct(val)
           iconpath =[pth,'obj_icon.gif'];
        else
           iconpath =[pth,'unknown_icon.gif'];
        end

end


