function fout = cwaitbar(x,name,col)
%CWAITBAR Display compound wait bar.
%   H = CWAITBAR(X,TITLE) creates and displays wait bars of 
%   fractional lengths X and with one title string TITLE.
%   The handle to the compound waitbar figure is returned in H.
%   X values should be between 0 and 1.
%   Each subsequent call to cwaitbar, CWAITBAR([BAR X]),
%   extends the length of the bar BAR to the new position X.
%   The first bar is the topmost bar and is BAR = 1 which
%   corresponds to the outermost loop.
%   H = CWAITBAR(X,TITLE) where TITLE is a cellstring with same
%   number of titles as there are fractional lengths in X.
%   Suitable for showing the bars' corresponding loop indices.
%   H = CWAITBAR(X,TITLE,COLOR) where COLOR is the color of the
%   bars. COLOR is either a color code character (see PLOT) or
%   an RGB vector. The default color is red. COLOR can also be 
%   a cell array with same number of elements as there are bars
%   in the cwaitbar figure.
%
%   The order of the elements in vector X and cell arrays TITLE
%   and COLOR which is consistent with the bar number BAR is:
%   The first element corresponds to the first bar at the top
%   of the figure which in turn corresponds to the outermost loop.
%
%   CWAITBAR is typically used inside nested FOR loops that
%   performs lengthy computations.
%
%      Examples:
%         cwaitbar([.3 .2 .7],'Please wait...');     %single title
%
%         h = cwaitbar([0 0 0],{'i','j','k'},{[.8 .2 .8],'b','r'});
%         for i=1:5,
%            % computations %
%            for j=1:10
%               % computations %
%               for k=1:100
%                  % computations %
%                  cwaitbar([3 k/100])
%               end
%               cwaitbar([2 j/10])
%            end
%            cwaitbar([1 i/5])
%         end
%         close(h)
%
%   See also WAITBAR.

% Based on matlab's WAITBAR. See help for WAITBAR.
% Copyright (c) 2003-11-02, B. Rasmus Anthin.
% Revision 2003-11-03 - 2003-11-06.
% GPL license.

xline = [100 0 0 100 100];
yline = [0 0 1 1 0];


switch nargin
case 1   % waitbar(x)    update
   bar=x(1);
   x=max(0,min(100*x(2),100));
   f = findobj(allchild(0),'flat','Tag','CWaitbar');
   if ~isempty(f), f=f(1);end
   a=sort(get(f,'child'));                         %axes objects
   if isempty(f) | isempty(a), 
      error('Couldn''t find waitbar handles.'); 
   end
   bar=length(a)+1-bar;        %first bar is the topmost bar instead
   if length(a)<bar
      error('Bar number exceeds number of available bars.')
   end
   for i=1:length(a)
      p(i)=findobj(a(i),'type','patch');
      l(i)=findobj(a(i),'type','line');      
   end
   %rewind upper bars when they are full
%   if bar==1
%      for i=2:length(a)
%         xpatchold=get(p(i),'xdata');
%         xold=xpatchold(2);
%         if xold==100
%            set(p,'erase','normal')
%            xpatch=[0 0 0 0];
%            set(p(i),'xdata',xpatch,'erase','none')
%            set(l(i),'xdata',xline)
%         end
%      end
%   end
   
   a=a(bar);
   p=p(bar);
   l=l(bar);
   xpatchold=get(p,'xdata');
   xold=xpatchold(2);
   if xold>x                      %erase old patches (if bar is shorter than before)
      set(p,'erase','normal')
      %xold=0;
   end
   xold=0;
        %previously: (continue on old patch)
   xpatch=[xold x x xold];
   set(p,'xdata',xpatch,'erase','none')
   set(l,'xdata',xline)

case 2   % waitbar(x,name)  initialize
   x=fliplr(max(0,min(100*x,100)));

   oldRootUnits = get(0,'Units');
   set(0, 'Units', 'points');
   pos = get(0,'ScreenSize');
   pointsPerPixel = 72/get(0,'ScreenPixelsPerInch');
   
   L=length(x)*.6+.4;
   width = 360 * pointsPerPixel;
   height = 75 * pointsPerPixel * L;
   pos = [pos(3)/2-width/2 pos(4)/2-height/2 width height];

   f = figure(...
      'Units', 'points', ...
      'Position', pos, ...
      'Resize','off', ...
      'CreateFcn','', ...
      'NumberTitle','off', ...
      'IntegerHandle','off', ...
      'MenuBar', 'none', ...
      'Tag','CWaitbar');
   colormap([]);
   
   for i=1:length(x)
      h = axes('XLim',[0 100],'YLim',[0 1]);
      if ~iscell(name)
         if i==length(x), title(name);end
      else
         if length(name)~=length(x)
            error('There must be equally many titles as waitbars, or only one title.')
         end
         title(name{end+1-i})
      end
      set(h, ...
         'Box','on', ...
         'Position',[.05 .3/L*(2*i-1) .9 .2/L],...
         'XTickMode','manual',...
         'YTickMode','manual',...
         'XTick',[],...
         'YTick',[],...
         'XTickLabelMode','manual',...
         'XTickLabel',[],...
         'YTickLabelMode','manual',...
         'YTickLabel',[]);
      
      xpatch = [0 x(i) x(i) 0];
      ypatch = [0 0 1 1];
      
      patch(xpatch,ypatch,'r','edgec','r','erase','none')
      line(xline,yline,'color','k','erase','none');
      
   end
   set(f,'HandleVisibility','callback');
   set(0, 'Units', oldRootUnits);
   
case 3
   if iscell(col) & length(col)~=length(x)
      error('There must be equally many colors as waitbars, or only one color.')
   end
   f=cwaitbar(x,name);
   a=get(f,'child');
   p=findobj(a,'type','patch');
   l=findobj(a,'type','line');
   if ~iscell(col)
      set(p,'facec',col,'edgec',col)
   else
      for i=1:length(col)
         set(p(i),'facec',col{i},'edgec',col{i})
      end
   end
   set(l,'xdata',xline')
end  % case
drawnow
figure(f)

if nargout==1,
  fout = f;
end


