function varargout=guide(varargin)
%GUIDE  Design GUI.
%   GUIDE initiates the GUI Design Environment tools that allow
%   Handle Graphics objects to be manipulated interactively.  Calling
%   GUIDE by itself will open the Control Panel if it is not open already
%   and update all other Guide tools that may already be open.  All tools
%   will be updated to use the current figure.  GUIDE(HandleList)
%   initializes all tools to the figure(s) containing all handles in the 
%   HandleList.  
%     
%   See also ALIGN, CBEDIT, CTLPANEL, MENUEDIT, PROPEDIT.

%   Loren Dean
%   Copyright (c) 1984-98 by The MathWorks, Inc.
%   $Revision: 1.43 $ $Date: 1998/05/22 18:20:30 $


Figures=allchild(0);    

ToolFig=findobj(Figures,'flat','Tag','Guide Control Panel');
PropFig=findobj(Figures,'flat','Tag','Guide Property Editor');
CBFig=findobj(Figures,'flat','Tag','Guide Callback Editor');
AlignFig=findobj(Figures,'flat','Tag','Guide Alignment Tool');
MenuFig=findobj(Figures,'flat','Tag','Guide Menu Editor');
HiddenFig=findobj(Figures,'flat','Tag','Guide Hidden Figure');

Figures=[ToolFig;PropFig;CBFig;AlignFig;MenuFig;HiddenFig];

OutputFlag=1;

switch nargin,
  %%%%%%%%%%%%%%%%%%%%%%%%
  %%% Peform an action %%%
  %%%%%%%%%%%%%%%%%%%%%%%%
  case 2,
    Action=varargin{1};
    Data=varargin{2};    
    if isstr(Action),
      
      switch Action,
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%% The Browsers need to be updated %%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        case 'BrowserUpdate',

          if ~isempty(Data.All.Browser.Handles),          
            Data=objbrwser('HandleUpdate',Data);
          end
          
          if ~isempty(Data.All.ObjTypeTag),          
            LocalUpdateTypeTag(Data); 
          end
          
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%% The Customization List has been modified %%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        case 'CustomizationUpdate',
        
          if ~isempty(Data.All.ObjTypeTag),          
            LocalUpdateTypeTag(Data); 
          end
          
          set(Data.All.DataHandle,'UserData',Data);         
          if ~isempty(PropFig),propedit CustomizationUpdate;end
          if ~isempty(CBFig),cbedit CustomizationUpdate;end
          Data=get(Data.All.DataHandle,'UserData');          
          
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%% A Handle has been added/removed %%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        case 'HandleUpdate',

          Data.All.HandleList= ...
            Data.All.HandleList(ishandle(Data.All.HandleList));
          Data.All.CurrentHandles= ...
            Data.All.CurrentHandles(ishandle(Data.All.CurrentHandles));       
          set(Data.All.DataHandle,'UserData',Data);
           
          if ~isempty(ToolFig),
            if Data.All.GuideFlag,              
              set(Data.All.HandleList,'Selected','off');
            end                
            Data=gnrlfun('TakeGeneralControl',Data);      
            set(Data.All.HandleList,'Selected','on');
            
          else,            
              Data=gnrlfun('TakeGeneralControl',Data);      
              
          end            
          
          if ~isempty(ToolFig),
            set(Data.All.DataHandle,'UserData',Data);         
            ctlpanel Update;
            Data=get(Data.All.DataHandle,'UserData');         
          end
          
          if ~isempty(Data.All.Browser.Handles),          
            Data=objbrwser('HandleUpdate',Data);
          end
          
          if ~isempty(Data.All.ObjTypeTag),          
            LocalUpdateTypeTag(Data); 
          end
          
          if ~isempty(MenuFig),
             Data=treemove('DetermineAvailMove',Data);
          end         

          set(Data.All.DataHandle,'UserData',Data);         
          if ~isempty(PropFig),propedit HandleUpdate;end
          if ~isempty(CBFig),cbedit HandleUpdate;end
          if ~isempty(AlignFig),align Update;end
          if ~isempty(MenuFig),menuedit Update;end

          Data=get(Data.All.DataHandle,'UserData');          
          Data.All.CurrentHandles=Data.All.HandleList;
          editfun('SetMenus',Data);
          
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%% A Property has been changed %%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        case 'PropertyUpdate',
          set(Data.All.DataHandle,'UserData',Data);         
          if ~isempty(PropFig),propedit PropertyUpdate;end
          if ~isempty(CBFig),cbedit PropertyUpdate;end
          if ~isempty(AlignFig),align Update;end
          if ~isempty(MenuFig),menuedit Update;end
          Data=get(Data.All.DataHandle,'UserData');         

          
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%% Update All Tools Completely %%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        case 'Update',
         
          Data=LocalUpdateTool(Figures,Data,[],'update');
          
          Data.All.HandleList= ...
            Data.All.HandleList(ishandle(Data.All.HandleList));
          Data.All.CurrentHandles= ...
            Data.All.CurrentHandles(ishandle(Data.All.CurrentHandles));       
        
          TempHandle=Data.All.CopyBuffer{1};          
          TempHandle=TempHandle(ishandle(TempHandle));
          Data.All.CopyBuffer{1}=TempHandle;          

          TempHandle=Data.All.CopyBuffer{2};          
          TempHandle=TempHandle(ishandle(TempHandle));
          Data.All.CopyBuffer{2}=TempHandle;          
                    
          set(Data.All.DataHandle,'UserData',Data);
          
          if ~isempty(ToolFig),
            if Data.All.GuideFlag,              
              set(Data.All.HandleList,'Selected','off');
            end                
            Data=gnrlfun('TakeGeneralControl',Data);
            set(Data.All.HandleList,'Selected','on');
            
          else,            
              Data=gnrlfun('TakeGeneralControl',Data);
              
          end            
          
          if ~isempty(ToolFig),
            set(Data.All.DataHandle,'UserData',Data);         
            ctlpanel Update;
            Data=get(Data.All.DataHandle,'UserData');         
          end
          
          if ~isempty(Data.All.Browser.Handles),          
            Data=objbrwser('Update',Data);
          end
          
          if ~isempty(Data.All.ObjTypeTag),          
            LocalUpdateTypeTag(Data); 
          end
          
          if ~isempty(MenuFig),
             Data=treemove('DetermineAvailMove',Data);
          end         

          set(Data.All.DataHandle,'UserData',Data);         
          if ~isempty(PropFig),propedit Update;end
          if ~isempty(CBFig),cbedit Update;end
          if ~isempty(AlignFig),align Update;end
          if ~isempty(MenuFig),menuedit Update;end
          
          Data=get(Data.All.DataHandle,'UserData');          
          Data.All.CurrentHandles=Data.All.HandleList;
          editfun('SetMenus',Data);
          
      end % switch Action
      

    else,
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      %%% Custom Initialization %%%
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      Data=LocalGuideInit(varargin{:});
      OutputFlag=0;
      
    end % if isstr

  case 3,    
    Action=varargin{1};
    Data=varargin{2};    
        
    switch Action,  
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %%% A Selection has been made %%%
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        case 'SelectionUpdate',    
          if ~isempty(Data.All.Browser.Handles),          
            HandleInfo=varargin{3};            
            if isequal(HandleInfo,-1),HandleInfo=[];end
            Data=objbrwser('SelectionUpdate',Data,HandleInfo);
          end
          
          if ~isempty(Data.All.ObjTypeTag),          
            LocalUpdateTypeTag(Data); 
          end
                    
          if ~isempty(MenuFig),
             Data=treemove('DetermineAvailMove',Data);
          end         

          set(Data.All.DataHandle,'UserData',Data);         
          if ~isempty(ToolFig),ctlpanel SelectionUpdate;end
          if ~isempty(PropFig),
            %%% This takes care of a select and move occurring at the 
            %%% same time with ctlpanel/SelectMoveResize with Position set
            %%% in the prop field            
            if ~(isequal(varargin{3},-1) &  ...
                strcmp(Data.PropFig.CurrentProp,'Position')),
              propedit SelectionUpdate;
            end
          end            
          if ~isempty(CBFig),cbedit SelectionUpdate;end
          if ~isempty(AlignFig),align Update;end
          if ~isempty(MenuFig),menuedit Update;end
                  
          Data=get(Data.All.DataHandle,'UserData');          
          Data.All.CurrentHandles=Data.All.HandleList;
          editfun('SetMenus',Data);
          
    end % switch
          
  case 4,    
    Action=varargin{1};
    switch Action,  
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      %%% A Guide Tool has been opened/closed %%%
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      case 'ToolUpdate',
        Data=LocalUpdateTool(Figures,varargin{2:4});
        
    end % switch
    
      
  %%%%%%%%%%%%%%%%%%
  %%% Initialize %%%
  %%%%%%%%%%%%%%%%%%
  case 1,   
    Data=LocalGuideInit(varargin{1},0);
    OutputFlag=0;
      
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%% Initialize Guide to Current Figure %%%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  case 0,
    
    if isempty(Figures),
      Data=[];
    else,      
      Data=get(Figures(1),'UserData');
      Data=get(Data.All.DataHandle,'UserData');    
    end      
    HandleList=gnrlfun('InitializeHandleList',Data);
    Data=LocalGuideInit(HandleList,0);
    OutputFlag=0;
    
  %%%%%%%%%%%%%
  %%% Error %%%
  %%%%%%%%%%%%%
  otherwise,
    error('''guide'' can only be called with up to 2 input arguments.');
    
end % switch nargin

if nargout,
  if OutputFlag,
    varargout{1}=Data;
  else,
    warning('''guide'' does not return output arguments');    
    varargout{1}=[];    
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% LocalGuideInit %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%
function Data=LocalGuideInit(HandleList,CustomFlag)
% Initialize Guide

ctlpanel(HandleList,CustomFlag)
Data=gnrlfun('GetUserData','Init');

if strcmp(studio,'on'),
  delete(Data.All.HiddenFigure);
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% LocalUpdateFigHandles %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Data=LocalUpdateFigHandles(Data)

Data.All.Figs.Handles=gnrlfun('GetGuideFigHandles');
ToolFig=findobj(Data.All.Figs.Handles,'flat','Tag','Guide Control Panel');
PropFig=findobj(Data.All.Figs.Handles,'flat','Tag','Guide Property Editor');
CBFig=findobj(Data.All.Figs.Handles,'flat','Tag','Guide Callback Editor');
AlignFig=findobj(Data.All.Figs.Handles,'flat','Tag','Guide Alignment Tool');
MenuFig=findobj(Data.All.Figs.Handles,'flat','Tag','Guide Menu Editor');

CheckVal={'out','in'};
if ~isempty(ToolFig),
  TBtns=findall(ToolFig,'Style','togglebutton');
  
  Handle=findobj(TBtns,'flat','Tag','Property Editor');
  set(Handle,'Value',~isempty(PropFig));
  Handle=findobj(TBtns,'flat','Tag','Callback Editor'); 
  set(Handle,'Value',~isempty(CBFig));
  Handle=findobj(TBtns,'flat','Tag','Alignment Tool') ; 
  set(Handle,'Value',~isempty(AlignFig));
  Handle=findobj(TBtns,'flat','Tag','Menu Editor')    ; 
  set(Handle,'Value',~isempty(MenuFig));
  
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% LocalUpdateTool %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Data=LocalUpdateTool(Figures,Data,ToolHandle,Action);
% Update UserData based on open tools

if ~isempty(Figures),
  switch Action
    case 'add',
      Data=LocalUpdateFigHandles(Data);
      if length(Data.All.Figs.Handles)==1,      
        if Data.All.GuideFlag,              
          set(Data.All.HandleList,'Selected','off');
        end                
        Data=gnrlfun('TakeGeneralControl',Data);      
        set(Data.All.HandleList,'Selected','on');
      end        

    case {'delete','update'},  
      if strcmp(Action,'delete'),    
        % The UserData is stored on this tool
        if ToolHandle==Data.All.DataHandle,         
          Figures(Figures==ToolHandle)=[];
          if length(Figures)>1, % Account for Hidden Figure
            Data.All.DataHandle=Figures(1);          
            TempData.All.DataHandle=Figures(1);          
            set(Figures(2:end),'UserData',TempData);
          else,
            Data.All.DataHandle=[];          
          end % if ~isempty        
        end % if

        delete(ToolHandle);
      end        
      if ~isempty(Data.All.DataHandle),      
        Data=LocalUpdateFigHandles(Data);
      else,
        Data.All.Figs.Handles=[];        
      end        
      
      if isempty(Data.All.Figs.Handles),
        Data=gnrlfun('RelinquishGeneralControl',Data);
      end        
      
      if ~isempty(Data.All.Browser.Handles),
        Data.All.Browser.Handles= ...
          Data.All.Browser.Handles(ishandle(Data.All.Browser.Handles));
      end % if ~isempty
      
      if ~isempty(Data.All.Browser.Complete),
        Data.All.Browser.Complete= ...
          Data.All.Browser.Complete(ishandle(Data.All.Browser.Complete));
      end % if ~isempty

      if ~isempty(Data.All.Browser.Square),
        Data.All.Browser.Square= ...
          Data.All.Browser.Square(ishandle(Data.All.Browser.Square));
      end % if ~isempty

      if ~isempty(Data.All.Browser.Menu),
        Data.All.Browser.Menu= ...
          Data.All.Browser.Menu(ishandle(Data.All.Browser.Menu));
      end % if ~isempty
      
      if ~isempty(Data.All.ObjTypeTag),
        Data.All.ObjTypeTag=Data.All.ObjTypeTag(ishandle(Data.All.ObjTypeTag));
      end % if ~isempty
      
      if ~isempty(Data.All.CutHandle),
        Loc=ishandle(Data.All.CutHandle(:,2));  
        Data.All.CutHandle=Data.All.CutHandle(Loc,:);  
        Data.All.CopyHandle=Data.All.CopyHandle(Loc,:);  
        Data.All.PasteHandle=Data.All.PasteHandle(Loc,:);  
        Data.All.DeleteHandle=Data.All.DeleteHandle(Loc,:);
        Data.All.UndoHandle=Data.All.UndoHandle(Loc,:);        
      end  % if ~isempty

      if ~isempty(Data.All.BtFStBHandles),
        Loc=ishandle(Data.All.BtFStBHandles(:,2));  
        Data.All.BtFStBHandles=Data.All.BtFStBHandles(Loc,:);
      end        

  end % switch
  
  if isequal(Figures,Data.All.HiddenFigure(1)),
    Data.All.HandleList= ...
      Data.All.HandleList(ishandle(Data.All.HandleList));
    set(Data.All.HandleList,'Selected','off');    
    Data.All.CurrentHandles= ...
      Data.All.CurrentHandles(ishandle(Data.All.CurrentHandles));       
    delete(Data.All.HiddenFigure(1));          
    Data.All.DataHandle=Data.All.DataHandle(ishandle(Data.All.DataHandle));
  end    
  
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% LocalUpdateTypeTag %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function LocalUpdateTypeTag(Data)

switch length(Data.All.HandleList),
  case 1,
    TypeString=get(Data.All.HandleList,'Type');  
    CenterString=gnrlfun('GetGoodObjString',TypeString,Data.All.HandleList);
    String=[TypeString ' ' CenterString get(Data.All.HandleList,'Tag')];

  case 0,
    String='None';

  otherwise,  
    String='Multiple';  
end  

set(Data.All.ObjTypeTag,'String',String);
