* Bugs 16120 16121 16128 fixed: tree_show() with cells & void + improved
[scilab.git] / scilab / modules / data_structures / macros / list2tree.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2019 - Samuel GOUGEON
3 //
4 // This file is hereby licensed under the terms of the GNU GPL v2.0,
5 // pursuant to article 5.3.4 of the CeCILL v.2.1.
6 // This file was originally licensed under the terms of the CeCILL v2.1,
7 // and continues to be available under such terms.
8 // For more information, see the COPYING file which you should have received
9 // along with this program.
10
11 // Internal function (for the time being..)
12
13 function tree = list2tree(x, titleRoot, styles, arrayByFields)
14     // x : list, cells or structs array, tlist, mlist, Xcos block
15     // titleRoot: single string: label of the tree root, for instance
16     //     the name of x in the calling environment
17     // styles: single string = HTML.4 tag embedding the address
18     //   of each data (fields names, lists indices..).
19     //   Example: "<b>$</b>"  where $ will be replaced with the address.
20     // arrayByFields: single boolean (when x is an array of structs).
21     //   %T => For each field: the array of its values is displayed.
22     //   %F => For each array component, all its fields are displayed.
23
24     // CHECKING INPUT ARGUMENTS
25     // ------------------------
26     if argn(2) < 1 then
27         msg = _("%s: Wrong number of input argument(s): %d to %d expected.\n")
28         error(msprintf(msg, "list2tree", 1, 4));
29     end
30
31     if and(type(x)<>[15 16 17 128]) then
32         msg = _("%s: Argument #%d: Container or Xcos object expected.\n")
33         error(msprintf(msg, "list2tree", 1))
34     end
35
36     if ~isdef("titleRoot","l")
37         titleRoot = "";
38     end
39
40     if ~isdef("arrayByFields","l") then
41         arrayByFields = %f
42     elseif type(arrayByFields) <> 4
43         msg = _("%s: Argument #%d: Boolean(s) expected.\n")
44         error(msprintf(msg, "tree_show", 3))
45     else
46         arrayByFields = arrayByFields(1)
47     end
48
49     if ~isdef("styles","l") then
50         styles = ""
51     elseif type(styles) <> 10
52         msg = _("%s: Argument #%d: Text(s) expected.\n")
53         error(msprintf(msg, "tree_show", 4))
54     else
55         styles = styles(1)
56     end
57
58     // BUILDING THE TREE
59     // -----------------
60     tree = uiCreateNode(titleRoot);
61     tree = list2tree_inc(x, "root", tree, styles, arrayByFields);
62 endfunction
63
64 // ===========================================================================
65
66 function tree = list2tree_inc(x, Path, tree, styles, arrayByFields)
67
68     if type(x) <> 15 then
69         list_field_content = %f
70     end
71     if type(x)==15 then
72         if length(x)==0 then
73             tree($).label = tree($).label + " list()"
74             return
75         end
76         II = 1:size(x);
77         if isdef("list_field_content") & list_field_content
78             if sum(list_field_content>1)>1
79                 // Generating all "(i,j,..)" headers
80                 v = container_get_ijk_labels(list_field_content)
81             else
82                 v = msprintf("%d\n",II')';
83                 if prod(list_field_content)==1  // parent struct is scalar
84                     tree($).label = tree($).label + " [list]"
85                 end
86             end
87         else
88             tree($).label = tree($).label + " [list]"
89             v = msprintf("%d\n",II')';
90         end
91
92     elseif typeof(x)=="ce"
93         nb = length(x)
94         if nb==0
95             tree($).label = tree($).label + " { }"
96             return
97         else
98             if nb==1 then
99                 tmp = " [cell]"
100             else
101                 tmp = msprintf(" [%s cell]", ..
102                         strcat(msprintf("%d\n",size(x)'),"x"));
103             end
104             tree($).label = tree($).label + tmp
105             II = 1:nb
106             // Generating all "(i,j,..)" headers
107             v = container_get_ijk_labels(size(x))
108         end
109
110     elseif type(x)==17 & typeof(x)=="st" then
111         // Structures are displayed first by k indices, then
112         // for each x(k), by field. In this way, each x(k) is
113         // displayed as a whole object/record, instead of being split.
114         if length(x)==0 then
115             tree($).label = tree($).label + " struct()"
116             return
117         else
118             if arrayByFields | length(x)==1 then
119                 if length(x)==1 then
120                     if isdef("struct_array") & struct_array then
121                         tmp = "↴"
122                     else
123                         tmp = " [struct]"
124                     end
125                 else
126                     tmp = msprintf(" [%s struct]", ..
127                             strcat(msprintf("%d\n",size(x)'),"x"));
128                 end
129                 struct_array = %f
130                 v = ["" ; fieldnames(x)]
131                 II = 2:size(v,"*")  // fields indices
132                 list_field_content = size(x)
133             else
134                 tmp = msprintf(" [%s struct]", ..
135                         strcat(msprintf("%d\n",size(x)'),"x"));
136                 II = 1:size(x,"*")
137                 v = container_get_ijk_labels(size(x))
138                 struct_array = %t
139             end
140             tree($).label = tree($).label + tmp
141         end
142         
143     elseif typeof(x)=="rational"
144         v = getfield(1,x);
145         II = 2:4
146         if x.dt == []
147             II = 2:3 // dt field skipped
148         end
149         if size(x,"*")<=1 then
150             tmp = " [rational]"
151         else
152             tmp = msprintf(" [%s rational]", ..
153                     strcat(msprintf("%d\n",size(x)'),"x"));
154         end
155         tree($).label = tree($).label + tmp
156
157     else // or(type(x)==[16 17])
158         v = getfield(1,x);
159         II = 2:size(v,"*")
160         if II==[] // No field
161             tree($).label = tree($).label + " " + sci2exp(x)
162             return
163         end
164         // Header:
165         tpof = typeof(x)
166         sz = []
167         if or(tpof==["st" "ce"]) | isdef("%"+tpof+"_size") then
168             sz = size(x)
169         end
170         tmp = "tlist"
171         if type(x)==17
172             tmp = "mlist"
173         end
174         if sz == [] | prod(sz)<2
175             tmp = "[" + tpof + " " + tmp + "]"
176         else
177             tmp = msprintf(" [%s %s %s]", ..
178                     strcat(msprintf("%d\n",size(x)'),"x"), tpof, tmp);
179         end
180         tree($).label = tree($).label + tmp
181     end
182
183     // Loop over container components or fields
184     // ----------------------------------------
185     for i = II
186         path = Path+"," + msprintf("%d",i)
187         titre = v(i) + ": ";
188         if styles <> ""
189             titre = strsubst("<html>"+styles, "$", titre)
190         end
191     
192         // Reads the object
193         clear o
194         if typeof(x)=="st" then
195             if ~struct_array
196                 o = x(v(i))
197             else
198                 o = x(i)
199             end
200         elseif typeof(x)=="ce"
201             o = x{i}
202         elseif or(type(x)==[15 16 17])
203             try // there may be more field names than data
204                 o = getfield(i,x);
205             catch
206                 o = list(,2)(1)
207             end
208         else
209             o = x
210         end
211         //
212         if ~isdef("o","l")  // void element in lists
213             currentNode = uiCreateNode(titre);
214             tree = uiConcatTree(tree, currentNode);
215
216         elseif or(type(o)==[15 16 17 128])
217             // Recursive call:
218             currentNode = uiCreateNode(titre);
219             currentNode = list2tree_inc(o, path, currentNode, styles, arrayByFields)
220             tree = uiConcatTree(tree, currentNode);
221
222         elseif typeof(o)=="implicitlist"
223             tree = uiConcatTree(tree, uiCreateNode(titre + sci2exp(o)));
224             
225         elseif type(o)== 13    // function
226             p = macr2tree(o)
227             tmp = msprintf(_("%s() (%d lines)"), p.name, p.nblines) 
228             tree = uiConcatTree(tree, uiCreateNode(titre + tmp));
229             
230         elseif type(o)== 14    // library
231             tmp = string(o)
232             p = strsubst(tmp(1), "\", "/"); // not escaped chars for mprintf()
233             libname = xmlGetValues("/scilablib","name",p + "lib")
234             tmp = msprintf("%s library of %d functions @ %s", ..
235                            libname, size(tmp,1)-1, p)
236             tree = uiConcatTree(tree, uiCreateNode(titre + tmp));
237
238         else
239             tp = typeof(o)
240             try
241                 if size(o, "*") > 40 then
242                     tts = tp + " of size " + sci2exp(size(o))
243                 else
244                     tts = sci2exp(o)
245                     if or(type(o)==(1:8))
246                         tts = strsubst(tts, ",", ", ");
247                         tts = strsubst(tts, ";", " ; ");
248                     elseif type(o)==10
249                         tts = strsubst(tts, """,""", """, """);
250                         tts = strsubst(tts, """;""", """ ; """);
251                     end
252                     if type(o)==2 | typeof(o)=="rational"
253                         vn = varn(o)
254                         if or(vn==["s" "z"])
255                             tts = strsubst(tts, "%"+vn, vn)
256                             tts = strsubst(tts, "*", "")
257                         end
258                     end
259                     if (or(type(o)==[1 2 5]) | typeof(o)=="rational")
260                         tts = strsubst(tts, "%inf","Inf")
261                         tts = strsubst(tts, "%nan","Nan")
262                         tts = strsubst(tts, "%i","i")
263                     end
264                     if or(type(o)==[4 6])
265                         tts = strsubst(tts, "%t", "T")
266                         tts = strsubst(tts, "%f", "F")
267                         tts = strsubst(tts, "],", "]]")
268                         tts = strsubst(tts, ",", "")
269                         tts = strsubst(tts, "]]", "],")
270                     end
271                 end
272             catch
273                 tts = tp;
274             end
275             titre2 = titre + tts  ;
276             tree = uiConcatTree(tree, uiCreateNode(titre2));
277         end
278     end
279
280 endfunction
281
282 // -------------------------------------------------------------------
283
284 function v = container_get_ijk_labels(sz)
285     if sum(sz>1) < 2 then
286         // if it's a vector, we display linearized indices
287         v = msprintf("%d\n", (1:prod(sz))')
288     else
289         // Otherwise we display (i,j,.) indices
290         L = list()
291         nd = length(sz);
292         in = "=ndgrid(" + strcat(msprintf("1:%d\n",sz'),",") + ")";
293         out = "[" + strcat(msprintf("L(%d)\n",(1:nd)'),",") + "]";
294         execstr(out + in);
295         v = []
296         for i = 1:nd
297             v = [v, msprintf("%d\n",L(i)(:))];
298         end
299         v = "(" + strcat(v,",","c") + ") ";
300     end
301 endfunction