7017
|
1 ## Copyright (C) 2007 Ben Abbott |
6935
|
2 ## |
7016
|
3 ## This file is part of Octave. |
6935
|
4 ## |
7016
|
5 ## Octave is free software; you can redistribute it and/or modify it |
|
6 ## under the terms of the GNU General Public License as published by |
|
7 ## the Free Software Foundation; either version 3 of the License, or (at |
|
8 ## your option) any later version. |
|
9 ## |
|
10 ## Octave is distributed in the hope that it will be useful, but |
|
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 ## General Public License for more details. |
6935
|
14 ## |
|
15 ## You should have received a copy of the GNU General Public License |
7016
|
16 ## along with Octave; see the file COPYING. If not, see |
|
17 ## <http://www.gnu.org/licenses/>. |
6935
|
18 |
|
19 ## -*- texinfo -*- |
|
20 ## @deftypefn {Function File} {@var{h} =} findobj () |
|
21 ## @deftypefnx {Function File} {@var{h} =} findobj (@var{propName}, @var{propValue}) |
|
22 ## @deftypefnx {Function File} {@var{h} =} findobj ('-property', @var{propName}) |
|
23 ## @deftypefnx {Function File} {@var{h} =} findobj ('-regexp', @var{propName},, @var{pattern}) |
|
24 ## @deftypefnx {Function File} {@var{h} =} findobj ('flat', @dots{}) |
|
25 ## @deftypefnx {Function File} {@var{h} =} findobj (@var{h}, @dots{}) |
|
26 ## @deftypefnx {Function File} {@var{h} =} findobj (@var{h}, '-depth', @var{d}, @dots{}) |
7001
|
27 ## Find object with specified property values. The simplest form is |
6935
|
28 ## |
|
29 ## @example |
|
30 ## findobj (@var{propName}, @var{propValue}) |
|
31 ## @end example |
|
32 ## |
|
33 ## @noindent |
|
34 ## which returns all of the handles to the objects with the name |
|
35 ## @var{propName} and the name @var{propValue}. The search can be limited |
|
36 ## to a particular object or set of objects and their descendants by |
|
37 ## passing a handle or set of handles @var{h} as the first argument to |
|
38 ## @code{findobj}. |
|
39 ## |
|
40 ## The depth of hierarchy of objects to which to search to can be limited |
|
41 ## with the '-depth' argument. To limit the number depth of the hierarchy |
|
42 ## to search to @var{d} generations of children, and example is |
|
43 ## |
|
44 ## @example |
|
45 ## findobj (@var{h}, '-depth', @var{d}, @var{propName}, @var{propValue}) |
|
46 ## @end example |
|
47 ## |
|
48 ## Specifying a depth @var{d} of 0, limits the search to the set of object |
|
49 ## passed in @var{h}. A depth @var{d} of 0 is equivalent to the '-flat' |
|
50 ## argument. |
|
51 ## |
|
52 ## A specified logical operator may be applied to the pairs of @var{propName} |
|
53 ## and @var{propValue}. The supported logical operators are '-and', '-or', |
|
54 ## '-xor', '-not'. |
|
55 ## |
|
56 ## The objects may also be matched by comparing a regular expression to the |
|
57 ## property values, where property values that match @code{regexp |
|
58 ## (@var{propValue}, @var{pattern})} are returned. Finally, objects may be |
|
59 ## matched by property name only, using the '-property' option. |
|
60 ## @seealso{get, set} |
|
61 ## @end deftypefn |
|
62 |
7017
|
63 ## Author: Ben Abbott <bpabbott@mac.com> |
|
64 |
6935
|
65 function h = findobj (varargin) |
|
66 |
|
67 depth = NaN; |
|
68 if (nargin == 0) |
|
69 handles = 0; |
|
70 n1 = 0; |
|
71 else |
|
72 if (ishandle (varargin{1}(1))) |
|
73 handles = varargin{1}; |
|
74 n1 = 2; |
|
75 else |
|
76 handles = 0; |
|
77 n1 = 1; |
|
78 end |
|
79 if (n1 <= nargin) |
|
80 if (ischar (varargin{n1})) |
|
81 if (strcmpi (varargin{n1}, 'flat')) |
|
82 depth = 0; |
|
83 n1 = n1 + 1; |
|
84 elseif (strcmpi(varargin{n1}, '-depth')) |
|
85 depth = varargin{n1+1}; |
|
86 n1 = n1 + 2; |
|
87 endif |
|
88 else |
|
89 error ("findobj: properties and options must be strings"); |
|
90 endif |
|
91 endif |
|
92 endif |
|
93 |
|
94 if (n1 <= nargin && nargin > 0) |
|
95 args = varargin(n1 : nargin); |
|
96 else |
|
97 args = {}; |
|
98 endif |
|
99 |
|
100 regularexpression = []; |
|
101 property = []; |
|
102 logicaloperator = {}; |
|
103 pname = {}; |
|
104 pvalue = {}; |
|
105 np = 1; |
|
106 na = 1; |
|
107 |
|
108 while (na <= numel (args)) |
|
109 regularexpression(np) = 0; |
|
110 property(np) = 0; |
|
111 logicaloperator{np} = 'and'; |
|
112 if (ischar (args {na})) |
|
113 if (strcmpi(args{na}, '-regexp')) |
|
114 if (na + 2 <= numel (args)) |
|
115 regularexpression(np) = 1; |
|
116 na = na + 1; |
|
117 pname{np} = args{na}; |
|
118 na = na + 1; |
|
119 pvalue{np} = args{na}; |
|
120 na = na + 1; |
|
121 np = np + 1; |
|
122 else |
|
123 error ("findobj: inconsistent number of arguments"); |
|
124 endif |
|
125 elseif (strcmpi(args{na}, '-property')) |
|
126 if (na + 1 <= numel (args)) |
|
127 na = na + 1; |
|
128 property(np) = 1; |
|
129 pname{np} = args{na}; |
|
130 na = na + 1; |
|
131 pvalue{np} = []; |
|
132 np = np + 1; |
|
133 else |
|
134 error ("findobj: inconsistent number of arguments"); |
|
135 endif |
|
136 elseif (! strcmp (args{na}(1), '-')) # parameter/value pairs |
|
137 if (na + 1 <= numel (args)) |
|
138 pname{np} = args{na}; |
|
139 na = na + 1; |
|
140 pvalue{np} = args{na}; |
|
141 na = na + 1; |
|
142 if (na <= numel(args)) |
|
143 if (ischar (args{na})) |
|
144 if strcmpi(args{na}, '-and') |
|
145 logicaloperator{np} = 'and'; |
|
146 na = na+1; |
|
147 elseif strcmpi(args{na}, '-or') |
|
148 logicaloperator{np} = 'or'; |
|
149 na = na+1; |
|
150 elseif strcmpi(args{na}, '-xor') |
|
151 logicaloperator{np} = 'xor'; |
|
152 na = na+1; |
|
153 elseif strcmpi(args{na}, '-not') |
|
154 logicaloperator{np} = 'not'; |
|
155 na = na+1; |
|
156 endif |
|
157 else |
|
158 error ("findobj: properties and options must be strings"); |
|
159 endif |
|
160 else |
|
161 logicaloperator{np} = 'and'; |
|
162 endif |
|
163 np = np + 1; |
|
164 else |
|
165 error ("findobj: inconsistent number of arguments"); |
|
166 endif |
|
167 else |
|
168 ## this is sloppy ... but works like matlab |
|
169 if strcmpi(args{na}, '-not') |
|
170 h = []; |
|
171 return |
|
172 endif |
|
173 na = na + 1; |
|
174 endif |
|
175 else |
|
176 error ("findobj: properties and options must be strings"); |
|
177 endif |
|
178 endwhile |
|
179 |
|
180 numpairs = np - 1; |
|
181 |
|
182 ## load all objects which qualify for being searched |
|
183 idepth = 0; |
|
184 h = handles; |
|
185 while (numel (handles) && ! (idepth >= depth)) |
|
186 children = []; |
|
187 for n = 1 : numel (handles) |
|
188 children = union (children, get(handles(n), 'children')); |
|
189 endfor |
|
190 handles = children; |
|
191 h = union (h, children); |
|
192 idepth = idepth + 1; |
|
193 endwhile |
|
194 |
|
195 keepers = ones (size (h)); |
|
196 if (numpairs > 0) |
|
197 for nh = 1 : numel(h) |
|
198 p = get (h (nh)); |
|
199 for np = 1 : numpairs |
|
200 fields = fieldnames (p); |
|
201 fieldindex = find (strcmpi (fields, pname{np}), 1); |
|
202 if (numel (fieldindex)) |
|
203 pname{np} = fields{fieldindex}; |
|
204 if (property(np)) |
|
205 match = 1; |
|
206 else |
|
207 if (regularexpression(np)) |
|
208 match = regexp (p.(pname{np}), pvalue{np}); |
|
209 if isempty (match) |
|
210 match = 0; |
|
211 end |
|
212 elseif (numel (p.(pname{np})) == numel (pvalue{np})) |
|
213 if (ischar (pvalue{np})) |
|
214 match = strcmpi (pvalue{np}, p.(pname{np})); |
|
215 else |
|
216 match = (pvalue{np} == p.(pname{np})); |
|
217 endif |
|
218 else |
|
219 match = 0; |
|
220 endif |
|
221 match = all (match); |
|
222 endif |
|
223 if (strcmpi (logicaloperator{np}, 'not')) |
|
224 keepers(nh) = ! keepers(nh) & ! match; |
|
225 else |
|
226 keepers(nh) = feval (logicaloperator{np}, keepers(nh), match); |
|
227 endif |
|
228 else |
|
229 keepers(nh) = 0; |
|
230 endif |
|
231 endfor |
|
232 endfor |
|
233 endif |
|
234 |
|
235 h = h (keepers != 0); |
|
236 h = reshape (h, [numel(h), 1]); |
|
237 endfunction |