6935
|
1 ## Copyright (C) 2007 Ben Abbott <bpabbott@mac.com> |
|
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 |
|
63 function h = findobj (varargin) |
|
64 |
|
65 depth = NaN; |
|
66 if (nargin == 0) |
|
67 handles = 0; |
|
68 n1 = 0; |
|
69 else |
|
70 if (ishandle (varargin{1}(1))) |
|
71 handles = varargin{1}; |
|
72 n1 = 2; |
|
73 else |
|
74 handles = 0; |
|
75 n1 = 1; |
|
76 end |
|
77 if (n1 <= nargin) |
|
78 if (ischar (varargin{n1})) |
|
79 if (strcmpi (varargin{n1}, 'flat')) |
|
80 depth = 0; |
|
81 n1 = n1 + 1; |
|
82 elseif (strcmpi(varargin{n1}, '-depth')) |
|
83 depth = varargin{n1+1}; |
|
84 n1 = n1 + 2; |
|
85 endif |
|
86 else |
|
87 error ("findobj: properties and options must be strings"); |
|
88 endif |
|
89 endif |
|
90 endif |
|
91 |
|
92 if (n1 <= nargin && nargin > 0) |
|
93 args = varargin(n1 : nargin); |
|
94 else |
|
95 args = {}; |
|
96 endif |
|
97 |
|
98 regularexpression = []; |
|
99 property = []; |
|
100 logicaloperator = {}; |
|
101 pname = {}; |
|
102 pvalue = {}; |
|
103 np = 1; |
|
104 na = 1; |
|
105 |
|
106 while (na <= numel (args)) |
|
107 regularexpression(np) = 0; |
|
108 property(np) = 0; |
|
109 logicaloperator{np} = 'and'; |
|
110 if (ischar (args {na})) |
|
111 if (strcmpi(args{na}, '-regexp')) |
|
112 if (na + 2 <= numel (args)) |
|
113 regularexpression(np) = 1; |
|
114 na = na + 1; |
|
115 pname{np} = args{na}; |
|
116 na = na + 1; |
|
117 pvalue{np} = args{na}; |
|
118 na = na + 1; |
|
119 np = np + 1; |
|
120 else |
|
121 error ("findobj: inconsistent number of arguments"); |
|
122 endif |
|
123 elseif (strcmpi(args{na}, '-property')) |
|
124 if (na + 1 <= numel (args)) |
|
125 na = na + 1; |
|
126 property(np) = 1; |
|
127 pname{np} = args{na}; |
|
128 na = na + 1; |
|
129 pvalue{np} = []; |
|
130 np = np + 1; |
|
131 else |
|
132 error ("findobj: inconsistent number of arguments"); |
|
133 endif |
|
134 elseif (! strcmp (args{na}(1), '-')) # parameter/value pairs |
|
135 if (na + 1 <= numel (args)) |
|
136 pname{np} = args{na}; |
|
137 na = na + 1; |
|
138 pvalue{np} = args{na}; |
|
139 na = na + 1; |
|
140 if (na <= numel(args)) |
|
141 if (ischar (args{na})) |
|
142 if strcmpi(args{na}, '-and') |
|
143 logicaloperator{np} = 'and'; |
|
144 na = na+1; |
|
145 elseif strcmpi(args{na}, '-or') |
|
146 logicaloperator{np} = 'or'; |
|
147 na = na+1; |
|
148 elseif strcmpi(args{na}, '-xor') |
|
149 logicaloperator{np} = 'xor'; |
|
150 na = na+1; |
|
151 elseif strcmpi(args{na}, '-not') |
|
152 logicaloperator{np} = 'not'; |
|
153 na = na+1; |
|
154 endif |
|
155 else |
|
156 error ("findobj: properties and options must be strings"); |
|
157 endif |
|
158 else |
|
159 logicaloperator{np} = 'and'; |
|
160 endif |
|
161 np = np + 1; |
|
162 else |
|
163 error ("findobj: inconsistent number of arguments"); |
|
164 endif |
|
165 else |
|
166 ## this is sloppy ... but works like matlab |
|
167 if strcmpi(args{na}, '-not') |
|
168 h = []; |
|
169 return |
|
170 endif |
|
171 na = na + 1; |
|
172 endif |
|
173 else |
|
174 error ("findobj: properties and options must be strings"); |
|
175 endif |
|
176 endwhile |
|
177 |
|
178 numpairs = np - 1; |
|
179 |
|
180 ## load all objects which qualify for being searched |
|
181 idepth = 0; |
|
182 h = handles; |
|
183 while (numel (handles) && ! (idepth >= depth)) |
|
184 children = []; |
|
185 for n = 1 : numel (handles) |
|
186 children = union (children, get(handles(n), 'children')); |
|
187 endfor |
|
188 handles = children; |
|
189 h = union (h, children); |
|
190 idepth = idepth + 1; |
|
191 endwhile |
|
192 |
|
193 keepers = ones (size (h)); |
|
194 if (numpairs > 0) |
|
195 for nh = 1 : numel(h) |
|
196 p = get (h (nh)); |
|
197 for np = 1 : numpairs |
|
198 fields = fieldnames (p); |
|
199 fieldindex = find (strcmpi (fields, pname{np}), 1); |
|
200 if (numel (fieldindex)) |
|
201 pname{np} = fields{fieldindex}; |
|
202 if (property(np)) |
|
203 match = 1; |
|
204 else |
|
205 if (regularexpression(np)) |
|
206 match = regexp (p.(pname{np}), pvalue{np}); |
|
207 if isempty (match) |
|
208 match = 0; |
|
209 end |
|
210 elseif (numel (p.(pname{np})) == numel (pvalue{np})) |
|
211 if (ischar (pvalue{np})) |
|
212 match = strcmpi (pvalue{np}, p.(pname{np})); |
|
213 else |
|
214 match = (pvalue{np} == p.(pname{np})); |
|
215 endif |
|
216 else |
|
217 match = 0; |
|
218 endif |
|
219 match = all (match); |
|
220 endif |
|
221 if (strcmpi (logicaloperator{np}, 'not')) |
|
222 keepers(nh) = ! keepers(nh) & ! match; |
|
223 else |
|
224 keepers(nh) = feval (logicaloperator{np}, keepers(nh), match); |
|
225 endif |
|
226 else |
|
227 keepers(nh) = 0; |
|
228 endif |
|
229 endfor |
|
230 endfor |
|
231 endif |
|
232 |
|
233 h = h (keepers != 0); |
|
234 h = reshape (h, [numel(h), 1]); |
|
235 endfunction |