help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: findobj.m


From: David Bateman
Subject: Re: findobj.m
Date: Thu, 27 Sep 2007 14:37:32 +0200
User-agent: Thunderbird 1.5.0.7 (X11/20060921)

I believe the attached version addresses the issues I mentioned with the
previous version of findobj.m. John do you want it?

D.
## Copyright (C) 2007   Ben Abbott  <address@hidden>
##
## 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} address@hidden =} findobj ()
## @deftypefnx {Function File} address@hidden =} findobj (@var{propName}, 
@var{propValue})
## @deftypefnx {Function File} address@hidden =} findobj ('-property', 
@var{propName})
## @deftypefnx {Function File} address@hidden =} findobj ('-regexp', 
@var{propName},, @var{pattern})
## @deftypefnx {Function File} address@hidden =} findobj ('flat', @dots{})
## @deftypefnx {Function File} address@hidden =} findobj (@var{h}, @dots{})
## @deftypefnx {Function File} address@hidden =} 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'))
        regularexpression(np) = 1;
        na = na + 1;
      elseif (strcmpi(args{na}, '-property'))
        na = na + 1;
        property(np) = 1;
        pname{np} = args{na};
        na = na + 1;
        pvalue{np} = [];
        np = np + 1;
      elseif (! strcmp (args{na}(1), '-')) # parameter/value pairs
        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
        ## 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});
            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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]