function varargout = importlti(varargin);
%IMPORTLTI opens the window for importing LTI design models into CODA GUIs
%   ModelData = IMPORTLTI('initialize',ParentFig) opens the Import LTI 
%   Design Model window when issued by a callback from the GUI with handle
%   ParentFig.  The execution of the callback is paused until the Import
%   LTI Design Model window is closed. 
%
%   After the window is closed, the results of the import are passed to
%   the Parent GUI in the structured array ModelData.  If the Cancel button
%   is pressed or the window is deleted, ModelData is empty.
%
%   ModelData = IMPORTLTI('initialize',ParentFig,StructNum,AvailStruct,ModelName)
%   allows the following attributes of the Import window to be specified:
%
%      1) StructNum = The number of the first displayed Feedback Structure
%      2) AvailStruct = The indices of the Feedback Structures that will be 
%            toggled through when pressing the NEXT button
%      3) ModelName = A default name for the Design Model
%
%   See also  LOOPSTRUCT, IMPORTFCN

%   Karen D. Gondoly
%   Copyright (c) 1986-1999 The Mathworks, Inc. All Rights Reserved.
% $Revision: 1.3 $

%---Check if number of input arguments is in the correct range
ni = nargin;
no=nargout;

error(nargchk(2,5,ni));

%---The first input argument should always be a string action
action = varargin{1};
if ~ischar(action)
   error('The first input argument must be a valid string action.');
end

%---Read data based on actions
switch action
case 'initialize',
   ParentFig = varargin{2};
   if ni>2,
      StructNum = varargin{3};
   else
      StructNum=1;
   end
   if ni>3,
      AvailStruct=varargin{4};
   else
      AvailStruct = 0;
   end	
   if ni>4
      ModelName = varargin{5};
      if ~ischar(ModelName),
         error('The fifth input argument must be a character array')
      end
   else
      ModelName= 'NewModel';
   end
   
otherwise
   ImportFig = varargin{2};
   if ni>2,
      ImportUd = varargin{3};
   else
      ImportUd = get(ImportFig,'UserData');
   end
end % switch action

%---Actions
switch action
case 'initialize',
   ImportFig = LocalOpenFig(ParentFig,StructNum,AvailStruct,ModelName);
   
   %---Wait until the figure is closed and return the new Structure number
   uiwait(ImportFig);
   
   if ishandle(ImportFig),
      ImportUd=get(ImportFig,'UserData');
      close(ImportFig)
      ModelData = ImportUd.ModelData;
   else
      ModelData = [];
   end
   if no,
      varargout{1}=ModelData ;
   end
   
case 'radiobutton',
   val = get(gcbo,'Value');
   sibs = get(gcbo,'UserData');
   
   if ~val,
      set(gcbo,'Value',1);
   elseif val==1,
      set(sibs,'Value',0);
      set(ImportUd.Handles.FileNameEdit,'String','', ...
         'UserData',struct('FileName',[],'PathName',[]));
      set([ImportUd.Handles.PlantEdit,...
         ImportUd.Handles.SensorEdit,...
         ImportUd.Handles.FilterEdit],'String','1','UserData',...
         struct('ListIndex',0,'String','1'));
   end % if/else val
   
case 'changeconfig',
   %---Next button callback
   udButton = get(gcbo,'UserData');
   IndCurrent = find(udButton.Current==udButton.Available);
   if isequal(IndCurrent,length(udButton.Available)),
      IndNext=1;
   else
      IndNext = IndCurrent+1;
   end
   
   OldHandles =struct2cell(ImportUd.Handles.Configuration); 
   delete([OldHandles{:}]);
   Handles = loopstruct('drawconfig',ImportUd.Handles.ConfigurationAxes,IndNext);
   ImportUd.Handles.Configuration = Handles;
   ImportUd.ModelData.Structure = IndNext;
   udButton.Current = IndNext;
   set(gcbo,'UserData',udButton)
   set(ImportFig,'UserData',ImportUd);
   
   %---Must toggle visibility of Design Model Edit boxes based on configuration
   %---Revisit for CODA
   
case 'apply', % Send the new Feedback structure to the Parent's Userdata
   %---Get the new model name
   ImportUd.ModelData.Name = get(ImportUd.Handles.ModelNameEdit,'String');
   
   %---Do error checking based on loop-structure
   switch ImportUd.ModelData.Structure,
   case {1,2}, % SISO loops
      %---Plant
      udPlantEdit = get(ImportUd.Handles.PlantEdit,'UserData');
      if isempty(udPlantEdit.ListIndex), % Nothing entered, use a unity gain
         ImportUd.ModelData.Plant.Name='P';
         ImportUd.ModelData.Plant.Object = zpk(1);
      elseif ~udPlantEdit.ListIndex, % Scalar or LTI object entered
         ImportUd.ModelData.Plant.Name='P';
         ImportUd.ModelData.Plant.Object=eval(udPlantEdit.String);
         if isa(ImportUd.ModelData.Plant.Object,'double'),
            ImportUd.ModelData.Plant.Object=zpk(ImportUd.ModelData.Plant.Object);
         end
      else, % ListBox entry entered
         ImportUd.ModelData.Plant.Name = udPlantEdit.String;
         ImportUd.ModelData.Plant.Object = ...
         	ImportUd.ListData.Objects{udPlantEdit.ListIndex};
      end
               
      %---Sensor
      udSensorEdit = get(ImportUd.Handles.SensorEdit,'UserData');
      if isempty(udSensorEdit.ListIndex), % Nothing entered, use a unity gain
         ImportUd.ModelData.Sensor.Name='H';
         ImportUd.ModelData.Sensor.Object = zpk(1);
      elseif ~udSensorEdit.ListIndex, % Scalar or LTI object entered
         ImportUd.ModelData.Sensor.Name='H';
         ImportUd.ModelData.Sensor.Object=eval(udSensorEdit.String);
         if isa(ImportUd.ModelData.Sensor.Object,'double'),
            ImportUd.ModelData.Sensor.Object=zpk(ImportUd.ModelData.Sensor.Object);
         end
      else, % ListBox entry entered
         ImportUd.ModelData.Sensor.Name = udSensorEdit.String;
         ImportUd.ModelData.Sensor.Object = ...
         	ImportUd.ListData.Objects{udSensorEdit.ListIndex};
      end
      
      %---Filter
      udFilterEdit = get(ImportUd.Handles.FilterEdit,'UserData');
      if isempty(udFilterEdit.ListIndex), % Nothing entered, use a unity gain
         ImportUd.ModelData.Filter.Name='F';
         ImportUd.ModelData.Filter.Object = zpk(1);
      elseif ~udFilterEdit.ListIndex, % Scalar or LTI object entered
         ImportUd.ModelData.Filter.Name='F';
         ImportUd.ModelData.Filter.Object=eval(udFilterEdit.String);
         if isa(ImportUd.ModelData.Filter.Object,'double'),
            ImportUd.ModelData.Filter.Object=zpk(ImportUd.ModelData.Filter.Object);
         end
      else, % ListBox entry entered
         ImportUd.ModelData.Filter.Name = udFilterEdit.String;
         ImportUd.ModelData.Filter.Object = ...
         	ImportUd.ListData.Objects{udFilterEdit.ListIndex};
      end
      
      %---Get all the Sample Times
      Ts=[];
      SISOflag=ones(1,3);
      if ~isstatic(ImportUd.ModelData.Plant.Object),
         Ts=ImportUd.ModelData.Plant.Object.Ts;
         SISOflag(1)=issiso(ImportUd.ModelData.Plant.Object);
      end
      if ~isstatic(ImportUd.ModelData.Sensor.Object),
         Ts=[Ts,ImportUd.ModelData.Sensor.Object.Ts];
         SISOflag(1)=issiso(ImportUd.ModelData.Sensor.Object);
      end
      if ~isstatic(ImportUd.ModelData.Filter.Object),
         Ts=[Ts,ImportUd.ModelData.Filter.Object.Ts];
         SISOflag(1)=issiso(ImportUd.ModelData.Filter.Object);
      end
            
      %---Check that everything is SISO and has the same sampling time.
      if any(~SISOflag),
         warndlg('All Design Model data must be single-input/single-output',...
            'Inport Warning');
         return
      end
      
      if ~isempty(Ts) & (any(Ts==0) & any(Ts~=0)), 
         % Make sure all are continuous or discrete
         warndlg('All Design Model data must be either continuous or discrete.',...
            'Inport Warning');
         return
      elseif ~isempty(Ts) & (all(Ts) & any(diff(Ts(Ts>0)))); 
         % Make sure all discrete have same sample time
         warndlg('All discrete Design Model data must have the same sample time',...
            'Inport Warning');
         return
      end
      
      %---Check that important systems are proper. Otherwise, FEEDBACK will error out
      ProperFlag=isproper(ImportUd.ModelData.Sensor.Object) & ...
         isproper(ImportUd.ModelData.Plant.Object);
      if ~ProperFlag,
         warndlg(['Both the Plant and Sensor Dynamics must be proper systems to be ', ...
               'used within a design GUI'],'Import Warning');
         return
      end % if ~ProperFlag
      
   end % switch Structure number
   set(ImportFig,'UserData',ImportUd)

   uiresume(ImportFig)
   
case 'cancel', % Close the Feedback Structure window without saving any changes
   ImportUd.ModelData=[];
   set(ImportFig,'UserData',ImportUd);
   uiresume(ImportFig)
   
case 'help',
   set(ImportFig,'WindowStyle','normal');
   
   helptext={'Importing LTI Design Models', ...
         {'The Import LTI Design Models window is used to import all the model';
         'data needed to characterize a design model within the MATLAB Control ';
         'Design and Analysis environment';
         '';
         'The following data is needed to completely specify the design model:';
         '  1) The feedback structure';
         '  2) The model name';
         '  3) Data for each block in the selected feedback structure';
         '';
         'Press OK to import the specified model.';
         'Press Cancel to close the window without importing a design model.';
         '-------------------------------------------------------------------';
         '';
         '';
         'Feedback Structure';
         ' ';
         'The feedback structure shows you how the compensator interacts with the';
         'design model and where the signals for closed-loop analysis are located';
         '';
         'The variables contained in the feedback structure are:';
         '   1) P = Plant';
         '   2) H = Sensor Dynamics';
         '   3) F = Pre-filter';
         '';
         'Press the Next button to see all the available feedback structures.'
         '';
         'For SISO Root Locus Design, there are two available feedback structures:';
         '   1) Compensator in the forward loop';
         '   2) Compensator in the feedback loop';
         '-------------------------------------------------------------------';
         '';
         '';
         'Model Source';
         ' ';
         'The Import From: field under the Feedback Structure determines where the';
         'Import window looks for the model data.';
         '';
         'Data can be imported from one of three locations:';
         '   1) The Workspace - lists all LTI objects in MATLAB''s workspace';
         '   2) A MAT-file - lists all LTI objects in the specified MAT-file';
         '   3) A Simulink diagram - lists all LTI blocks in the specified diagram';
         '';
         'When selecting MAT-file or Simulink diagram, either:';
         '   1) Enter the appropriate file or diagram name in the editable text box';
         '   2) Press the Browse button to search for a particular file or diagram.';
         '';
         'Caution: The file or diagram must exist on the current MATLAB path.';
         '-------------------------------------------------------------------';
         '';
         '';
         'Model List';
         ' ';
         'The Model List box shows all the LTI models or blocks found in the location';
         'indicated in the Import From: field. All model data must be in this list.';
         '';
         'To move an item in the list to the Design Model field:';
         '   1) Select the variable name in the list box';
         '   2) Press the arrow button associated with the appropriate data field';
         '-------------------------------------------------------------------';
         '';
         '';
         'Design Model';
         ' ';
         'The Design model shows all the data that will be imported, along with the';
         'the feedback structure.';
         '';
         'Enter a name for the Design Model in the Name: editable text box.';
         ''
         'Enter data into the Model Data editable text boxes by either:';
         '   1) Selecting an item in the list box and pressing the appropriate';
         '      arrow button';
         '   2) Typing the name of a list box variable in the editable text box';
         '';
         'Cautions:';
         '   1) Only the following values can be entered as the Design model data:';
         '         a) Variables shown in the Contents list box';
         '         b) Scalar gains';
         '         c) MATLAB expressions that evaluate to a gain or LTI object';
         '   2) All Model Data must be entered before exiting the Import window'}};
         
         
         
         helpwin(helptext);
   
end % switch action

%--------------------------Internal Functions------------------------
%%%%%%%%%%%%%%%%%%%%
%%% LocalOpenFig %%%
%%%%%%%%%%%%%%%%%%%%
function a = LocalOpenFig(ParentFig,StructNum,AvailStruct,ModelName);

StdColor = get(0,'DefaultFigureColor');
PointsToPixels = 72/get(0,'ScreenPixelsPerInch');
StdUnit = 'points';

ud = struct('Parent',ParentFig,...
   'ListData',struct('Names',[],'Objects',[]),...
   'ModelData',struct('Name',ModelName,'Structure',StructNum,'FeedbackSign',-1,...
         'Plant',struct('Name','plant','Object',zpk(1)),...
         'Sensor',struct('Name','sensor','Object',zpk(1)),...
         'Filter',struct('Name','filter','Object',zpk(1))), ...
   'Handles',[]);

%---Open the Import LTI Design Model Figure
a = figure('Units','points', ...
	'Color',StdColor, ...
   'MenuBar','none', ...
   'visible','off',...
   'IntegerHandle','off',...
   'WindowStyle','modal',...
	'Name','Import LTI Design Model', ...
	'NumberTitle','off', ...
	'Position',PointsToPixels*[7 94 521 273], ...
   'Tag','ImportLTIfig');
  
%---Add Feedback Structure controls
b = uicontrol('Parent',a, ...
   'BackgroundColor',StdColor, ...
   'Unit',StdUnit,...
	'Position',PointsToPixels*[30 246 123 20], ...
	'String','Feedback Structure', ...
	'Style','text');
ud.Handles.ConfigurationAxes = axes('Parent',a, ...
   'Unit',StdUnit,...
	'Box','on', ...
	'Color',StdColor, ...
	'Position',PointsToPixels*[9 161 166 97], ...
	'Tag','ConfigurationAxes', ...
	'XTick',[], ...
   'YTick',[]);
Handles = loopstruct('drawconfig',ud.Handles.ConfigurationAxes,StructNum);
ud.Handles.Configuration = Handles;

ud.Handles.NextButton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'Callback','importlti(''changeconfig'',gcbf);',...
   'Position',PointsToPixels*[9 161 50 19], ...
   'String','Other...', ...
   'UserData',struct('Available',AvailStruct,'Current',StructNum),...
   'Tag','NextButton');

%---Add Source controls
b = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Position',PointsToPixels*[10 9 165 134], ...
   'Style','frame');
b = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Position',PointsToPixels*[45 132 91 20], ...
	'String','Import From:', ...
	'Style','text');
ud.Handles.Wbutton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'BackgroundColor',StdColor, ...
   'Callback','importlti(''radiobutton'',gcbf);importfcn(''workspace'',gcbf);',...
	'Position',PointsToPixels*[19 117 100 19], ...
	'String','Workspace', ...
	'Style','radiobutton', ...
	'Tag','Wbutton', ...
	'Value',1);
ud.Handles.Mbutton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
   'Callback','importlti(''radiobutton'',gcbf);importfcn(''matfile'',gcbf);',...
	'Position',PointsToPixels*[19 98 100 19], ...
	'String','MAT-file', ...
	'Style','radiobutton', ...
	'Tag','Mbutton');
ud.Handles.Sbutton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
   'Callback','importlti(''radiobutton'',gcbf);importfcn(''simulink'',gcbf);',...
	'Position',PointsToPixels*[19 79 100 19], ...
	'String','Simulink', ...
	'Style','radiobutton', ...
   'Tag','Sbutton');
set(ud.Handles.Wbutton,'UserData',[ud.Handles.Mbutton,ud.Handles.Sbutton]);
set(ud.Handles.Mbutton,'UserData',[ud.Handles.Wbutton,ud.Handles.Sbutton]);
set(ud.Handles.Sbutton,'UserData',[ud.Handles.Mbutton,ud.Handles.Wbutton]);
ud.Handles.FileNameText = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Enable','off', ...
	'Position',PointsToPixels*[20 54 141 20], ...
   'String','MAT-file name:', ...
   'Tag','FileNameText',...
	'Style','text');
ud.Handles.FileNameEdit = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'Enable','off', ...
   'Horiz','left',...
   'BackgroundColor',[1 1 1], ...
   'Callback','importfcn(''clearpath'',gcbf)',...
	'Position',PointsToPixels*[19 36 141 20], ...
   'Style','edit', ...
   'UserData',struct('FileName',[],'PathName',[]),...
	'Tag','FileNameEdit');
ud.Handles.BrowseButton= uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'Callback','importfcn(''browsemat'',gcbf);',...
	'Enable','off', ...
	'Position',PointsToPixels*[19 14 142 20], ...
	'String','Browse', ...
   'Tag','BrowseButton');

%---Add Model Listbox
b = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Position',PointsToPixels*[180 41 148 217], ...
	'Style','frame');
ud.Handles.ModelText = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Position',PointsToPixels*[192 246 123 20], ...
	'String','Workspace Contents', ...
   'Style','text',...
   'Tag','ModelText');
ud.Handles.ModelList = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',[1 1 1], ...
	'Position',PointsToPixels*[187 49 132 197], ...
	'Style','listbox', ...
	'Tag','ModelList', ...
	'Value',1);

%---Add Design Model Specification controls
b = uicontrol('Parent',a, ...
	'BackgroundColor',StdColor, ...
   'Unit',StdUnit,...
	'Position',PointsToPixels*[362 41 149 218], ...
	'Style','frame');
b = uicontrol('Parent',a, ...
	'BackgroundColor',StdColor, ...
   'Unit',StdUnit,...
	'Position',PointsToPixels*[390 246 90 20], ...
	'String','Design Model', ...
	'Style','text');
b = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'HorizontalAlignment','left', ...
	'Position',PointsToPixels*[368 222 40 20], ...
	'String','Name:', ...
	'Style','text');
ud.Handles.ModelNameEdit = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',[1 1 1], ...
   'Callback','importfcn(''namecallback'',gcbf);',...
	'Position',PointsToPixels*[374 199 125 20], ...
   'Style','edit', ...
   'Horiz','left',...
   'String',ModelName,...
   'UserData',ModelName,...
	'Tag','ModelNameEdit');
b = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Position',PointsToPixels*[368 109 23 22], ...
	'String','P =', ...
	'Style','text', ...
   'Tag','PlantText');
EditUd = struct('ListIndex',0,'String','1');
ud.Handles.PlantEdit = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',[1 1 1], ...
   'Callback','importfcn(''editcallback'',gcbf);',...
   'Horiz','left',...
   'Position',PointsToPixels*[397 113 100 20], ...
   'String','1',...
   'Style','edit', ...
   'UserData',EditUd,...
	'Tag','PlantEdit');
ud.Handles.PlantButton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'Callback','importfcn(''buttoncallback'',gcbf);',...
	'Position',PointsToPixels*[333 111 25 21], ...
   'String','-->', ...
   'UserData',ud.Handles.PlantEdit,...
	'Tag','PlantButton');
b = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Position',PointsToPixels*[368 79 23 22], ...
	'String','H =', ...
	'Style','text', ...
	'Tag','SensorText');
ud.Handles.SensorEdit = uicontrol('Parent',a, ...
	'BackgroundColor',[1 1 1], ...
   'Callback','importfcn(''editcallback'',gcbf);',...
   'Horiz','left',...
   'Unit',StdUnit,...
	'Position',PointsToPixels*[397 84 100 20], ...
   'String','1',...
	'Style','edit', ...
   'UserData',EditUd,...
	'Tag','SensorEdit');
ud.Handles.SensorButton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'Callback','importfcn(''buttoncallback'',gcbf);',...
	'Position',PointsToPixels*[333 81 25 21], ...
   'String','-->', ...
   'UserData',ud.Handles.SensorEdit,...
	'Tag','SensorButton');
b = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Position',PointsToPixels*[368 45 23 22], ...
	'String','F =', ...
	'Style','text', ...
	'Tag','FilterText');
ud.Handles.FilterEdit = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',[1 1 1], ...
   'Horiz','left',...
   'Callback','importfcn(''editcallback'',gcbf);',...
	'Position',PointsToPixels*[397 53 100 20], ...
   'String','1',...
   'Style','edit', ...
   'UserData',EditUd,...
	'Tag','FilterEdit');
ud.Handles.FilterButton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'Callback','importfcn(''buttoncallback'',gcbf);',...
	'Position',PointsToPixels*[333 49 25 21], ...
   'String','-->', ...
   'UserData',ud.Handles.FilterEdit,...
	'Tag','FilterButton');

%---Add window buttons
b = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
	'BackgroundColor',StdColor, ...
	'Position',PointsToPixels*[179 9 334 28], ...
	'Style','frame');
ud.Handles.HelpButton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'Callback','importlti(''help'',gcbf);',...
	'Position',PointsToPixels*[184 13 74 20], ...
	'String','Help', ...
	'Tag','HelpButton');
ud.Handles.CancelButton = uicontrol('Parent',a, ...
   'Callback','importlti(''cancel'',gcbf);',...
   'Unit',StdUnit,...
	'Position',PointsToPixels*[433 13 74 20], ...
	'String','Cancel', ...
   'Tag','CancelButton');
ud.Handles.OKButton = uicontrol('Parent',a, ...
   'Unit',StdUnit,...
   'Callback','importlti(''apply'',gcbf);',...
	'Position',PointsToPixels*[308 13 74 20], ...
   'String','OK', ...
	'Tag','OKButton');

set(a,'UserData',ud,'visible','on')
importfcn('workspace',a);
