changeset 6935:5cd272497aae

[project @ 2007-09-30 19:16:49 by dbateman]
author dbateman
date Sun, 30 Sep 2007 19:16:49 +0000
parents 37676450044a
children e92bc778c634
files scripts/ChangeLog scripts/plot/Makefile.in scripts/plot/findobj.m
diffstat 3 files changed, 240 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Fri Sep 28 15:41:01 2007 +0000
+++ b/scripts/ChangeLog	Sun Sep 30 19:16:49 2007 +0000
@@ -1,3 +1,8 @@
+2007-09-30  Ben Abbott  <bpabbott@mac.com>
+
+	* plot/findobj.m: New function.
+	* plot/Makefile.m (SOURCES): Add it to SOURCES.
+
 2007-09-26  David Bateman  <dbateman@free.fr>
 
 	* pkg/pkg.m: Add second argument to setting for prefix for
--- a/scripts/plot/Makefile.in	Fri Sep 28 15:41:01 2007 +0000
+++ b/scripts/plot/Makefile.in	Sun Sep 30 19:16:49 2007 +0000
@@ -60,6 +60,7 @@
   drawnow.m \
   errorbar.m \
   figure.m \
+  findobj.m \
   fplot.m \
   gca.m \
   gcf.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/findobj.m	Sun Sep 30 19:16:49 2007 +0000
@@ -0,0 +1,234 @@
+## Copyright (C) 2007   Ben Abbott  <bpabbott@mac.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+## 02110-1301  USA
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{h} =} findobj ()
+## @deftypefnx {Function File} {@var{h} =} findobj (@var{propName}, @var{propValue})
+## @deftypefnx {Function File} {@var{h} =} findobj ('-property', @var{propName})
+## @deftypefnx {Function File} {@var{h} =} findobj ('-regexp', @var{propName},, @var{pattern})
+## @deftypefnx {Function File} {@var{h} =} findobj ('flat', @dots{})
+## @deftypefnx {Function File} {@var{h} =} findobj (@var{h}, @dots{})
+## @deftypefnx {Function File} {@var{h} =} findobj (@var{h}, '-depth', @var{d}, @dots{})
+## Find object with specified property values. The simpliest form is
+##
+## @example
+## findobj (@var{propName}, @var{propValue})
+## @end example
+##
+## @noindent
+## which returns all of the handles to the objects with the name 
+## @var{propName} and the name @var{propValue}. The search can be limited
+## to a particular object or set of objects and their descendants by 
+## passing a handle or set of handles @var{h} as the first argument to 
+## @code{findobj}.
+##
+## The depth of hierarchy of objects to which to search to can be limited
+## with the '-depth' argument. To limit the number depth of the hierarchy
+## to search to @var{d} generations of children, and example is
+##
+## @example
+## findobj (@var{h}, '-depth', @var{d}, @var{propName}, @var{propValue})
+## @end example
+##
+## Specifying a depth @var{d} of 0, limits the search to the set of object
+## passed in @var{h}. A depth @var{d} of 0 is equivalent to the '-flat'
+## argument. 
+##
+## A specified logical operator may be applied to the pairs of @var{propName}
+## and @var{propValue}. The supported logical operators are '-and', '-or', 
+## '-xor', '-not'.
+##
+## The objects may also be matched by comparing a regular expression to the 
+## property values, where property values that match @code{regexp 
+## (@var{propValue}, @var{pattern})} are returned.  Finally, objects may be 
+## matched by property name only, using the '-property' option.
+## @seealso{get, set}
+## @end deftypefn
+
+function h = findobj (varargin)
+
+  depth = NaN;
+  if (nargin == 0)
+    handles = 0;
+    n1 = 0;
+  else
+    if (ishandle (varargin{1}(1)))
+      handles = varargin{1};
+      n1 = 2;
+    else
+      handles = 0;
+      n1 = 1;
+    end
+    if (n1 <= nargin)
+      if (ischar (varargin{n1}))
+	if (strcmpi (varargin{n1}, 'flat'))
+	  depth = 0;
+	  n1 = n1 + 1;
+	elseif (strcmpi(varargin{n1}, '-depth'))
+	  depth = varargin{n1+1};
+	  n1 = n1 + 2;
+	endif
+      else
+	error ("findobj: properties and options must be strings");
+      endif
+    endif
+  endif
+
+  if (n1 <= nargin && nargin > 0)
+    args = varargin(n1 : nargin);
+  else
+    args = {};
+  endif
+
+  regularexpression = [];
+  property          = [];
+  logicaloperator   = {};
+  pname             = {};
+  pvalue            = {};
+  np = 1;
+  na = 1;
+
+  while (na <= numel (args))
+    regularexpression(np) = 0;
+    property(np) = 0;
+    logicaloperator{np} = 'and';
+    if (ischar (args {na}))
+      if (strcmpi(args{na}, '-regexp'))
+	if (na + 2 <= numel (args))
+	  regularexpression(np) = 1;
+	  na = na + 1;
+	  pname{np} = args{na};
+	  na = na + 1;
+	  pvalue{np} = args{na};
+	  na = na + 1;
+	  np = np + 1;
+	else
+	  error ("findobj: inconsistent number of arguments");
+	endif
+      elseif (strcmpi(args{na}, '-property'))
+	if (na + 1 <= numel (args))
+	  na = na + 1;
+	  property(np) = 1;
+	  pname{np} = args{na};
+	  na = na + 1;
+	  pvalue{np} = [];
+	  np = np + 1;
+	else
+	  error ("findobj: inconsistent number of arguments");
+	endif
+      elseif (! strcmp (args{na}(1), '-')) # parameter/value pairs
+	if (na + 1 <= numel (args))
+	  pname{np} = args{na};
+	  na = na + 1;
+	  pvalue{np} = args{na};
+	  na = na + 1;
+	  if (na <= numel(args))
+	    if (ischar (args{na}))
+	      if strcmpi(args{na}, '-and')
+		logicaloperator{np} = 'and';
+		na = na+1;
+	      elseif strcmpi(args{na}, '-or')
+		logicaloperator{np} = 'or';
+		na = na+1;
+	      elseif strcmpi(args{na}, '-xor')
+		logicaloperator{np} = 'xor';
+		na = na+1;
+	      elseif strcmpi(args{na}, '-not')
+		logicaloperator{np} = 'not';
+		na = na+1;
+	      endif
+	    else
+	      error ("findobj: properties and options must be strings");
+	    endif
+	  else
+	    logicaloperator{np} = 'and';
+	  endif
+	  np = np + 1;
+	else
+	  error ("findobj: inconsistent number of arguments");
+	endif
+      else
+	## this is sloppy ... but works like matlab
+	if strcmpi(args{na}, '-not')
+	  h = [];
+	  return
+	endif
+	na = na + 1;
+      endif
+    else
+      error ("findobj: properties and options must be strings");
+    endif
+  endwhile
+
+  numpairs = np - 1;
+  
+  ## load all objects which qualify for being searched
+  idepth = 0;
+  h = handles;
+  while (numel (handles) && ! (idepth >= depth))
+    children = [];
+    for n = 1 : numel (handles)
+      children = union (children, get(handles(n), 'children'));
+    endfor 
+    handles = children;
+    h = union (h, children);
+    idepth = idepth + 1;
+  endwhile
+
+  keepers = ones (size (h));
+  if (numpairs > 0)
+    for nh = 1 : numel(h)
+      p = get (h (nh));
+      for np = 1 : numpairs
+	fields = fieldnames (p);
+	fieldindex = find (strcmpi (fields, pname{np}), 1);
+	if (numel (fieldindex))
+          pname{np} = fields{fieldindex};
+          if (property(np))
+            match = 1;
+          else
+            if (regularexpression(np))
+	      match = regexp (p.(pname{np}), pvalue{np});
+              if isempty (match)
+                match = 0;
+              end
+            elseif (numel (p.(pname{np})) == numel (pvalue{np}))
+	      if (ischar (pvalue{np}))
+		match = strcmpi (pvalue{np}, p.(pname{np}));
+	      else
+		match = (pvalue{np} == p.(pname{np}));
+	      endif
+            else
+	      match = 0;
+            endif
+            match = all (match);
+          endif
+          if (strcmpi (logicaloperator{np}, 'not'))
+            keepers(nh) = ! keepers(nh) & ! match;
+          else
+            keepers(nh) = feval (logicaloperator{np}, keepers(nh), match);
+          endif
+	else
+	  keepers(nh) = 0;
+	endif
+      endfor
+    endfor
+  endif
+
+  h = h (keepers != 0);
+  h = reshape (h, [numel(h), 1]);
+endfunction