function varargout = rguifcn(action,LTIviewerFig,varargin)
%RGUIFCN  Contains the callback functions used by the LTI Viewer
%   RGUIFCN(ACTION,FIG) performs the callback specified by action
%   for the figure with handle FIG. FIG can be either a figure
%   containing Response Objects or an LTI Viewer.
%
%   See also LTIVIEW

%   Authors: Karen Gondoly, 9-9-96
%   Revised: Adam DiVergilio, 10-27-99
%   Copyright 1986-2000 The MathWorks, Inc. 
%   $Revision: 1.58 $  $Date: 2000/06/14 19:59:12 $

switch action
case 'addsystems'
   %---Append new systems to plots (either for 'current' plottype or after an import.
   
   %---A third input argument contains the system data in a structure with fields
   %----'Systems','Names','PlotStyles','ExtraArgs'
   if nargin<3
      error('Wrong number of input arguments for "AddSystems" action.');
   end
   
   SystemData = varargin{1};
   
   %---A possible 4th input argument allows the Warning to be toggled on or off
   %    PromptFlag=1: Warning is shown when Systems will be overwritten
   %    PromptFlag=0: Overwrites duplicate systems without warning.
   if isequal(nargin,4)
      PromptFlag=varargin{2};
   else
      PromptFlag=0;
   end
   
   ViewerObj = get(LTIviewerFig,'UserData');
   AllViewProps = get(ViewerObj);
   
   %---Look for systems that were already in the Viewer (based on System Name)
   [OldSystems,indNew,indOld] = intersect(SystemData.Names,AllViewProps.SystemNames);
   OverwriteFlag=0;
   if ~isempty(OldSystems)
      if PromptFlag
         Str = [{'The following systems already exist in the LTI Viewer:';
               ''};
            SystemData.Names(indNew);
            {'';
               'Do you want to overwrite the old values of these systems';
               'with the newer versions?'}];
         switch questdlg(Str,'Updating the LTI Viewer');
         case 'Yes', % Deletes the systems
            OverwriteFlag = 1;
         case 'No'
            % Do not delete the systems
         case 'Cancel'
            %---Kill's entire Add System, even if systems have changed
            status(ViewerObj,'Import canceled.',1);
            if nargout, varargout{1}=-1; end;
            return
         end
      else
         OverwriteFlag = 1;
      end
   end
   
   % Update data for overwritten systems
   % RE: Do not change plot styles!
   if OverwriteFlag
      AllViewProps.Systems(indOld) = SystemData.Systems(indNew);
      AllViewProps.SystemNames(indOld) = SystemData.Names(indNew);
      %AllViewProps.PlotStyles(indOld) = SystemData.PlotStyles(indNew);
   end
   
   % Structure deletion fails when index is empty.  Others are NOPs.
   SystemData.Systems(indNew) = [];
   SystemData.Names(indNew) = [];
   SystemData.PlotStyles(indNew) = [];
   
   Systems = [AllViewProps.Systems;SystemData.Systems];
   Names = [AllViewProps.SystemNames;SystemData.Names];
   PlotStyles = [AllViewProps.PlotStyles; SystemData.PlotStyles];
   
   NewSystemData = struct('PlotStyles',{PlotStyles},'Names',{Names},'Systems',{Systems});
   ViewerObj = initview(ViewerObj,NewSystemData);

   if nargout, varargout{1}=0; end;

case 'importsys'
   %---Callback to apply an import
   ViewerObj = get(LTIviewerFig,'UserData');

   %---Names of systems to import
   SystemNames = varargin{1};

   %---Determine valid system size
   OldSystems = get(ViewerObj,'Systems');
   if ~isempty(OldSystems)
      [numout,numin] = size(OldSystems{1});
   else
      numout = [];
      numin = [];
   end

   %---Check status of systems
   [NewSystems,SystemsStatus] = systemstat(SystemNames,numout,numin);
   IsDiffSize = find(SystemsStatus==0);
   IsSameSize = find(SystemsStatus==1);

   %---Notify user that systems of different size will not be imported (default 'continue')
   if length(IsDiffSize)>0
      Str = cat(1,...
            {'The following systems have a different number of';...
             'inputs and/or outputs than those currently displayed:';...
             ''},...
             strcat({'     '},SystemNames(IsDiffSize,:)),...
            {'';...
             'These systems will not be imported.';...
             ''});
      switch questdlg(Str,'Updating the LTI Viewer','Continue','Cancel','Continue')
      case 'Cancel'
         status(ViewerObj,'Import canceled.',1);
         return
      end
   end

   %---Add valid systems to viewer
   if length(IsSameSize)>0
      PlotStyles = struct('Color',cell(length(IsSameSize),1),'LineStyle',[],'Marker',[],'Legend',[]);
      SystemData = struct('Names',{SystemNames(IsSameSize,:)},...
         'Systems',{NewSystems(IsSameSize,:)},...
         'PlotStyles',{PlotStyles});
      addstatus = rguifcn('addsystems',LTIviewerFig,SystemData,1);
      if addstatus<0
         %---Import was canceled
         return
      end
   end

   %---Build status string
   if     length(IsSameSize)==0, StatusStr = sprintf('No valid systems imported');
   elseif length(IsSameSize)==1, StatusStr = sprintf('1 valid system imported');
   else,                         StatusStr = sprintf('%0.3g valid systems imported',length(IsSameSize));
   end
   if     length(IsDiffSize)==0, StatusStr = sprintf('%s.',StatusStr);
   elseif length(IsDiffSize)==1, StatusStr = sprintf('%s, 1 invalid system skipped.',StatusStr);
   else,                         StatusStr = sprintf('%s, %0.3g invalid systems skipped.',StatusStr,length(IsDiffSize));
   end
   status(ViewerObj,StatusStr,1);

case 'deletesys'
   %---Callback from the Delete menu
   ViewerObj = get(LTIviewerFig,'UserData');
   SysNames = varargin{1};
   indDelete = find(ismember(get(ViewerObj,'SystemNames'),SysNames));
   ViewerObj = deletesys(ViewerObj,indDelete);

   %---Build status string
   n = length(indDelete);
   if     n==0, StatusStr = sprintf('No systems deleted.');
   elseif n==1, StatusStr = sprintf('1 system deleted.');
   else,        StatusStr = sprintf('%0.3g systems deleted.',n);
   end
   status(ViewerObj,StatusStr,1);

case 'showbox'
   %---ButtonDownFcn for the plotted lines

   %---Left-click on line only (normal)
   if ~strcmpi(get(LTIviewerFig,'SelectionType'),'normal'), return; end

   %---Get line/axes handles
   lobj = gcbo;
   ax = get(lobj,'Parent');

   %---Get Response Data
   ContextMenu = get(ax,'UIContextMenu');
   RespObj = get(ContextMenu,'UserData');
   AllRespProps = get(RespObj,'Undocumented');
   InputName = AllRespProps.InputLabel;
   OutputName = AllRespProps.OutputLabel;
   ResponseType = AllRespProps.ResponseType;
   ResponseHandles = AllRespProps.ResponseHandles;
   SystemNames = AllRespProps.SystemNames;
   udLine = get(lobj,'UserData');
   SystemIndex = find(strcmp(udLine.System,SystemNames));
   SystemIndex = SystemIndex(1);
   Handles = ResponseHandles{SystemIndex}{udLine.Output,udLine.Input};
   IOSize = size(AllRespProps.SelectedChannels);
   ArraySize = size(Handles);

   %---Make appropriate system name string
   sysstr = rguihelper('labelsystem',udLine.System,...
      udLine.Input,udLine.Output,udLine.Array,IOSize,ArraySize,ResponseType);

   %---If the response is on the LTI Viewer, also show the sampling time
   if isequal(get(LTIviewerFig,'Tag'),'ResponseGUI')
      ViewerObj = get(LTIviewerFig,'UserData');
      Systems = get(ViewerObj,'Systems');
      if isdt(Systems{SystemIndex})
         if isequal(Systems{SystemIndex}.Ts,-1)
            Tdstr = 'unspecified';
         else
            Tdstr = num2str(Systems{SystemIndex}.Ts);
         end
         sysstr = sprintf('%s\nSampling time: %s',sysstr,Tdstr);
      end
   end

   %---Add I/O information
   switch ResponseType
   case {'sigma','margin'}
      ;   % No I/O info
   case {'lsim';'initial'}
      if ~( length(OutputName)==1 & strcmpi(OutputName{1},'Y(1)') )
         outname = OutputName{udLine.Output};
         sysstr = sprintf('%s\nOutput: %s',sysstr,outname);
      end
   otherwise
      if ~( length(InputName)==1 & length(OutputName)==1 & strcmpi(InputName{1},'U(1)') & strcmpi(OutputName{1},'Y(1)') )
         inname = InputName{udLine.Input};
         outname = OutputName{udLine.Output};
         sysstr = sprintf('%s\nI/O: %s to %s',sysstr,inname,outname);
     end
   end

   %---Get XLabel and YLabel based on ResponseType
   switch ResponseType
   case {'bode','margin'}
      Xstr = AllRespProps.Xlabel;
      [numout,numin] = find(AllRespProps.PlotAxes==ax);
      if ~rem(numout,2)
         Ystr = sprintf('Phase (%s)',AllRespProps.PhaseUnits);
      else
         Ystr = sprintf('Magnitude (%s)',AllRespProps.MagnitudeUnits);
      end
   case 'nichols'
      Xstr = sprintf('Phase (%s)',AllRespProps.PhaseUnits);
      Ystr = sprintf('Gain (%s)',AllRespProps.MagnitudeUnits);
      Fstr = sprintf('Freq (%s)',AllRespProps.FrequencyUnits);
   case 'nyquist'
      Xstr = 'Real';
      Ystr = 'Imag';
      Fstr = sprintf('Freq (%s)',AllRespProps.FrequencyUnits);
   otherwise
      Xstr = AllRespProps.Xlabel;
      Ystr = AllRespProps.Ylabel;
   end

   switch ResponseType
   %---For nyquist/nichols plots, show X, Y, and Frequency data
   case {'nyquist','nichols'}
      Freq = AllRespProps.Frequency;
      ArrayInd = num2cell(udLine.Array);  % array indices
      SysFreq = Freq{SystemIndex}{ArrayInd{:}};
      %---For Nyquist plot, determine whether to display +w or -w
      if strcmp(ResponseType,'nyquist') & isequal(find(lobj==Handles{ArrayInd{:}}),2)
         SysFreq = -SysFreq;
      end
      textstr = sprintf('%s\n%s: %%0.3g\n%s: %%0.3g\n%s: %%0.3g',sysstr,Xstr,Ystr,Fstr);
      linescan(lobj,'xy',1,textstr,get(lobj,'XData'),get(lobj,'YData'),SysFreq);
   %---For plots vs frequency, track in 'xy' mode (helps track peaks/notches)
   case {'bode','bodemag','sigma','margin'}
      textstr = sprintf('%s\n%s: %%0.3g\n%s: %%0.3g',sysstr,Xstr,Ystr);
      linescan(lobj,'xy',1,textstr,get(lobj,'XData'),get(lobj,'YData'));
   %---Otherwise, just track in 'x' mode
   otherwise
      textstr = sprintf('%s\n%s: %%0.3g\n%s: %%0.3g',sysstr,Xstr,Ystr);
      linescan(lobj,'x',1,textstr,get(lobj,'XData'),get(lobj,'YData'));
   end
   
case 'plotoptbuttondown'
   %----ButtonDownFcn for the PlotOption lines

   %---Left-click on line only (normal)
   if ~strcmpi(get(LTIviewerFig,'SelectionType'),'normal'), return; end

   lobj = gcbo;
   linescan(lobj,'x',0,get(lobj,'UserData'),get(lobj,'XData'),get(lobj,'YData'));

end
