* Bug 7117 fixed: now findobj() can search within given object 11/21511/9
Stéphane MOTTELET [Wed, 15 May 2019 16:13:19 +0000 (18:13 +0200)]
http://bugzilla.scilab.org/show_bug.cgi?id=7117

help page: http://bugzilla.scilab.org/attachment.cgi?id=5153

Change-Id: I1c8c1e4b95b6b36686bdf1de7de5920ec3f2b0c6

SEP/SEP_135_findobj.odt [new file with mode: 0644]
scilab/CHANGES.md
scilab/modules/gui/help/en_US/findobj.xml
scilab/modules/gui/help/ja_JP/findobj.xml [deleted file]
scilab/modules/gui/macros/findobj.sci

diff --git a/SEP/SEP_135_findobj.odt b/SEP/SEP_135_findobj.odt
new file mode 100644 (file)
index 0000000..7a0ca35
Binary files /dev/null and b/SEP/SEP_135_findobj.odt differ
index c62a8d8..e94a97e 100644 (file)
@@ -275,6 +275,7 @@ Bug Fixes
 
 ### Bugs fixed in 6.1.1:
 * [#3188](https://bugzilla.scilab.org/3188): `part()` was slower than in Scilab 4.1.2.
+* [#7117](https://bugzilla.scilab.org/7117): `findobj()` could not search within given object.
 * [#8059](https://bugzilla.scilab.org/8059): A local `.wgetrc` config file could make troubles in `atomsDownload`.
 * [#8378](https://bugzilla.scilab.org/8378): Datatip `ContextMenu => Delete last datatip` was useless.
 * [#9909](https://bugzilla.scilab.org/9909): In the help browser, add a way to open the online version of the current page.
index 6c730df..be954ec 100644 (file)
@@ -7,7 +7,13 @@
     <refsynopsisdiv>
         <title>Syntax</title>
         <synopsis>
-            h =  findobj(propertyName, propertyValue)
+            h = findobj()
+            h = findobj(propertyName, propertyValue)
+            h = findobj(propertyName, propertyValue, operator, propertyName, propertyValue, ...)
+            h = findobj("-property", propertyName, ...)
+            h = findobj(searchHandles, ...)
+            h = findobj(..., '-depth', d, ...)
+            h = findobj(..., '-flat', ...)
         </synopsis>
     </refsynopsisdiv>
     <refsection>
             <varlistentry>
                 <term>propertyValue</term>
                 <listitem>
-                    <para>string character specify the value the tested property should be equal to (case sensitive).</para>
+                    <para>character string specify the value the tested property should be equal to (case sensitive).</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>operator</term>
+                <listitem>
+                    <para>character string belonging to the set {"-and", "-or", "-not"}.</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>searchHandles</term>
+                <listitem>
+                    <para>Vector of graphic handles where the search is restricted to.</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>d</term>
+                <listitem>
+                    <para>positive integer, the depth of the search.</para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                 <term>h</term>
                 <listitem>
-                    <para>handle of the found object.</para>
+                    <para>handles of the found objects.</para>
                 </listitem>
             </varlistentry>
         </variablelist>
     <refsection>
         <title>Description</title>
         <para>
-            This routine is currently used to find objects knowing their 'tag'
-            property.  It returns handle of the first found object which property
-            <emphasis role="italic">propertyName</emphasis> is equal to <emphasis role="italic">propertyValue</emphasis>. If such an object does not exist, the
+            Without arguments <literal>findobj</literal> returns handles of all graphic objects and their descendants. If such an object does not exist, the
             function returns an empty matrix.
         </para>
+        <para>
+            <literal>findobj(propertyName, propertyValue, ...)</literal> returns the handles of objects having the property <literal>propertyName</literal> set to <literal>propertyValue</literal>. 
+            If successive property/vaue pairs are given the handles of objects verifing all conditions are returned, i.e. there is an implicit <literal>"-and"</literal> operator between pairs. 
+            Another operator can be explicitely given with <literal>findobj(propertyName, propertyValue, operator, propertyName, propertyValue, ...)</literal>.
+        </para>
+        <para>The priority of evaluations in a composite condition using operators can be controlled by using a cell argument, e.g. <literal>findobj({propertyName, propertyValue, ...}, operator, ...)</literal>
+        </para>
+        <para>
+            <literal>findobj("-property", propertyName, ...)</literal> returns the handles of objects having the property <literal>propertyName</literal>. Other conditions can be added.
+        </para>
+        <para>
+            By default the search is done within all figures and <literal>findobj(searchHandles, ...)</literal> restricts the search to the given handles. The depth of the search is by default infinite and can be restricted by <literal>findobj(searchHandles, '-depth', d, ...)</literal>. A value of 0 restricts the search to objects given in <literal>searchHandles</literal> and does not search within descendants, this is equivalent to the <literal>"flat"</literal> optional string.
+        </para>
     </refsection>
     <refsection>
         <title>Examples</title>
         <programlisting role="example"><![CDATA[
 // Create a figure
-h=figure();
+h=scf();
 // Put a text in the figure
 uicontrol(h, "style","text", ...
              "string","This is a figure", ...
@@ -56,8 +91,26 @@ uicontrol(h, "style","text", ...
 // Find the object which "tag" value is "Alabel"
 lab=findobj("tag","Alabel");
 disp("The text of the label is """+lab.string+"""");
-// Close the figure
-close();
+ ]]></programlisting>
+        <programlisting role="example"><![CDATA[
+// Create a figure
+h=scf();
+// plot something
+plot()
+xlabel abscissae
+ylabel ordinate
+title "a plot"
+legend "c1" "c2" "c3"
+
+// Find the objects having a "font_size" property
+h1 = findobj("-property","font_size")
+// Change the font size of all text objects
+h1.font_size = 3
+
+// Find the objects having a "thickness" property
+h2 = findobj("-property","thickness")
+// Change the thickness of such objects
+h2.thickness = 2
  ]]></programlisting>
     </refsection>
     <refsection role="see also">
diff --git a/scilab/modules/gui/help/ja_JP/findobj.xml b/scilab/modules/gui/help/ja_JP/findobj.xml
deleted file mode 100644 (file)
index d990830..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:lang="ja" xml:id="findobj">
-    <refnamediv>
-        <refname>findobj</refname>
-        <refpurpose>指定したプロパティを有するオブジェクトを探す</refpurpose>
-    </refnamediv>
-    <refsynopsisdiv>
-        <title>呼び出し手順</title>
-        <synopsis>
-            h =  findobj(propertyName, propertyValue)
-        </synopsis>
-    </refsynopsisdiv>
-    <refsection>
-        <title>引数</title>
-        <variablelist>
-            <varlistentry>
-                <term>propertyName</term>
-                <listitem>
-                    <para>文字列,探すプロパティ名 (大文字小文字を区別しない).</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>propertyValue</term>
-                <listitem>
-                    <para>
-                        探すプロパティが一致する値を指定する文字列
-                        (大文字小文字を区別する).
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>h</term>
-                <listitem>
-                    <para>見つかったオブジェクトのハンドル.</para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </refsection>
-    <refsection>
-        <title>説明</title>
-        <para>
-            このルーチンは,現在,
-            'tag'プロパティが既知のオブジェクトを探す際に使用されています.
-            このルーチンは,
-            <emphasis role="italic">propertyName</emphasis>が
-            <emphasis role="italic">propertyValue</emphasis>に等しい
-            最初に見つかったオブジェクトのハンドルを返します.
-            そのようなオブジェクトが存在しない場合,
-            この関数は空の行列を返します.
-        </para>
-    </refsection>
-    <refsection>
-        <title>例</title>
-        <programlisting role="example"><![CDATA[
-// 図を作成
-h=figure();
-// 図にテキストを表示
-uicontrol(h, "style","text", ...
-             "string","This is a figure", ...
-             "position",[50 70 100 100], ...
-             "fontsize",15, ...
-             "tag","Alabel");
-// "tag" の値が"Alabel"であるオブジェクトを探す
-lab=findobj("tag","Alabel");
-disp("The text of the label is """+lab.string+"""");
-// 図を閉じる
-close();
- ]]></programlisting>
-    </refsection>
-    <refsection role="see also">
-        <title>参照</title>
-        <simplelist type="inline">
-            <member>
-                <link linkend="uicontrol">uicontrol</link>
-            </member>
-            <member>
-                <link linkend="uimenu">uimenu</link>
-            </member>
-            <member>
-                <link linkend="set">set</link>
-            </member>
-            <member>
-                <link linkend="get">get</link>
-            </member>
-        </simplelist>
-    </refsection>
-</refentry>
index 66b6043..0f45b42 100644 (file)
@@ -1,8 +1,8 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) 2008 - INRIA - Vincent COUVERT
 // Copyright (C) 2008 - DIGITEO - Vincent COUVERT
-//
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2020 - Stéphane MOTTELET
 //
 // This file is hereby licensed under the terms of the GNU GPL v2.0,
 // pursuant to article 5.3.4 of the CeCILL v.2.1.
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
-function h =  findobj(propertyName, propertyValue)
+function h =  findobj(varargin)
 
     rhs = argn(2);
-    if rhs<> [1 2] then
-        msg = gettext("%s: Wrong number of input arguments: %d or %d expected.\n");
-        error(msprintf(msg, "findobj", 1, 2));
-        return;
-    end
-
-    if rhs == 1 then
-        h = get(propertyName);
-        return
-    end
-    if strcmp(propertyName, "tag", "i") == 0 then
-        h = get(propertyValue);
-        return
-    end
-
-    // Return value
-    h = []
-
-    // Get all opened figures
-    figureIds = winsid();
-    if isempty(figureIds) then
-        return
-    end
 
-    currentFig = gcf();
-
-    propertyName = convstr(propertyName,"l");
-
-    // Special fast case: finding a figure
-    if propertyName=="figure_id" then
-        if type(propertyValue)==1 & or(figureIds==propertyValue)
-            h = scf(propertyValue);
-            scf(currentFig);
+    searchHandles= [];
+    iPos = 1;
+    if rhs >= 1
+        if typeof(varargin(1)) == "handle"
+            if and(is_handle_valid(varargin(1)))
+                searchHandles = varargin(1);
+            else
+                msg = gettext("%s: Input argument #%d must be a valid handle.\n");
+                error(msprintf(msg, "findobj", 1));
+            end
+            iPos = 2;
+        elseif typeof(varargin(1) <> "string")
+             msg = gettext("%s: Wrong type for argument #%d: A string expected.\n");
+             error(msprintf(msg, "findobj", 1));
         end
-        return
     end
 
-    // Otherwise:
-    // Iterate over all figures
-    for figureindex = 1:size(figureIds,2)
-        // Does the figure match the propertyName/propertyValue set ?
-        f=scf(figureIds(figureindex));
-
-        %ierr = execstr("%bool = isequal(get(f, propertyName), propertyValue);", "errcatch");
-        if %ierr==0 & %bool then
-            h = f;
-            break
+    if isempty(searchHandles)
+        // Get all opened figures
+        figureIds = winsid();
+        if isempty(figureIds) then
+            return
         end
-
-        answ = findMatchingChild(f.children, propertyName, propertyValue);
-        if ~isempty(answ) then
-            h = answ;
-            break
+        // Iterate over all figures
+        for figureindex = 1:size(figureIds,2)
+            searchHandles(figureindex) = scf(figureIds(figureindex));
         end
     end
 
-    scf(currentFig);
+    try
+        [testString,depth] = parse(varargin(iPos:$));
+    catch
+        error(lasterror())
+    end
+
+    h = findMatchingChild(searchHandles, testString, depth);
 
 endfunction
-//-----------------------------------------------------------------------------
-function hFound = findMatchingChild(children, propertyName, propertyValue)
-    // Copyright DIGITEO 2008
-    // Vincent COUVERT
 
+function hFound = findMatchingChild(handles, testString, depth)
     hFound = []
-
-    for childIndex = 1:size(children,1)
-
-        %ierr = execstr("%bool = isequal(get(children(childIndex), propertyName), propertyValue);", "errcatch");
-        if %ierr==0 & %bool then
-            hFound = children(childIndex);
-            return
+    for index = 1:size(handles,1)
+        h = handles(index);
+        [bResult, ierr] = evstr(testString);
+        if ierr==0 & bResult then
+            hFound = [hFound; handles(index)];
+        end
+        if depth > 0
+            [children,ierr] = evstr("get(handles(index), ""children"");"); // Does the child have a children property
+            if get(handles(index),"type") == "Axes" // Title and Label entities of Axes are children
+                children = [children
+                            get(handles(index),"Title")
+                            get(handles(index),"x_label")
+                            get(handles(index),"y_label")
+                            get(handles(index),"z_label")];
+            end
+            if ~isempty(children) // Yes the child can have children
+                answ = findMatchingChild(children, testString, depth-1);
+                if ~isempty(answ) then
+                    hFound = [hFound; answ];
+                end
+            end
         end
+    end
+endfunction
 
-        %ierr = execstr("get(children(childIndex), ""children"");", "errcatch"); // Does the child have a children property
 
-        if %ierr==0 then // Yes the child can have children
-            answ = findMatchingChild(children(childIndex).children, propertyName, propertyValue);
-            if ~isempty(answ) then
-                hFound = answ;
-                return
+function [out,depth] = parse(varargin)
+    operators = ["&&","||","~" ]
+    depth = %inf;
+    out = "";
+    currentOp = "";
+    i = 1;
+    while i <= length(varargin)
+        op = operators(varargin(i) == ["-and","-or","-not"]);
+        if ~isempty(op)
+            // token is an operator
+            if ~isempty(currentOp) && op <> "~"
+               msg = gettext("%s: Argument #%d cannot be a binary operator.");
+                error(msprintf(msg, "findobj", i));
+            end
+            currentOp = currentOp + op;
+            if op <> "~" && isempty(out)
+               msg = gettext("%s: Argument #%d cannot be a binary operator.");
+                error(msprintf(msg, "findobj", i));
+            end
+            if i == length(varargin)
+                msg = gettext("%s: Wrong number of input argument(s): At least %d expected.");
+                error(msprintf(msg, "findobj", i+1));
+            end
+            i = i+1;
+            continue
+        end
+        if ~isempty(out) && (isempty(currentOp) || currentOp == "~")
+            // by default all successive conditions are connected with &&
+            currentOp = "&&"+currentOp;
+        end
+        if typeof(varargin(i)) == "ce"
+            // recursively parse content of cell
+            cellArg = varargin(i);
+            out = out + msprintf("%s(%s)",currentOp,parse(cellArg{:}(:)));
+            currentOp = "";
+            i = i+1;
+        elseif varargin(i) == "-depth"
+            // set depth
+            if i < length(varargin)
+                n = varargin(i+1);
+                if type(n) == 1 && isscalar(n) && n >= 0 && floor(n) == n
+                    depth = varargin(i+1);
+                    i = i+2;
+                else
+                    msg = gettext("%s: Wrong type for input argument #%d: A positive integer value expected.\n");
+                    error(msprintf(msg, "findobj", i+1));
+                end
+            else
+                msg = gettext("%s: Wrong number of input argument(s): At least %d expected.");
+                error(msprintf(msg, "findobj", i+1));
+            end
+        elseif varargin(i) == "-flat"
+            // set depth at 0
+            depth = 0;
+            i = i+1;
+        elseif varargin(i) == "-property"
+            // search handles having a given property
+            if i < length(varargin)
+                if type(varargin(i+1)) == 10
+                    out = out+msprintf("%s~execstr(""h.%s"",""errcatch"")",currentOp,varargin(i+1))
+                    currentOp = "";
+                    i = i+2;
+                 else
+                    msg = gettext("%s: Wrong type for argument #%d: A string expected.\n");
+                    error(msprintf(msg, "findobj", i+1));
+                 end
+            else
+                msg = gettext("%s: Wrong number of input argument(s): At least %d expected.");
+                error(msprintf(msg, "findobj", i+1));
+            end
+        else // property, value sequence, likely
+            if i < length(varargin)
+                out = out+msprintf("%s(h.%s==%s)",currentOp,varargin(i),sci2exp(varargin(i+1)));
+                currentOp = "";
+                i = i+2;
+            else
+                msg = gettext("%s: Wrong number of input argument(s): At least %d expected.");
+                error(msprintf(msg, "findobj", i+1));
             end
         end
     end
-
 endfunction
-//-----------------------------------------------------------------------------