function RespObj = pvset(RespObj,varargin)
%PVSET  Set properties of Response Objects.
%
%   RespObj = PVSET(RespObj,'Property1',Value1,'Property2',Value2,...)
%   sets the values of the properties with exact names 'Property1',
%   'Property2',...
%
%   See also SET.

%   Authors: P. Gahinet
%   Revised: A. DiVergilio
%   Copyright 1986-2000 The MathWorks, Inc. 
%   $Revision: 1.11 $  $Date: 2000/06/14 20:07:30 $

% RE: PVSET is performing object-specific property value setting
%     for the generic RESPONSE/SET method. It expects true property names.

ContextMenu = RespObj.UIContextMenu;

for i=1:2:nargin-1,
   % Set each PV pair in turn
   Property = varargin{i};
   Value = varargin{i+1};
      
   switch Property
   case 'ArraySelector',
      Value=lower(Value);
      if length(find(strcmpi(Value,{'on';'off'}))) ~= 1,
         error(sprintf('Bad value for response property %s.',Property))
      else
         RespObj.ArraySelector = Value;
         ArrayHandle = get(RespObj.UIContextMenu.ArrayMenu,'UserData');
         
         %---Toggle the Selector
         switch Value,
         case 'on',
            if ishandle(ArrayHandle),
               paramsel('#criterion',RespObj);
               figure(ArrayHandle);
            else
               paramsel('#init',RespObj);
            end
         case 'off',
            if ishandle(ArrayHandle)
               set(ArrayHandle,'visible','off')
            end
         end % switch Value
      end
      
   case 'AxesGrouping',
      %---Called by all responses except Bode
      lVal = length(Value);
      ValidGroup = {'none';'all';'inputs';'outputs'};
      NewGroup = find(strncmpi(Value,ValidGroup,lVal));
      if isempty(NewGroup),
         error(sprintf('Bad value for response property %s.',Property))
      end
      
      RespObj.AxesGrouping = ValidGroup{NewGroup};
      %---Change the Checked property of the Axes Group Context Menus
      GroupMenus = struct2cell(RespObj.UIContextMenu.GroupMenu);
      set([GroupMenus{2:5}],'Checked','off')
      set(GroupMenus{NewGroup+1},'Checked','on')
      
      %---Resize the grouped axes and re-parent the ResponseHandles
      if ~any(strcmpi(RespObj.ResponseType,{'sigma';'pzmap'})),
         configaxes(RespObj)
      end
      
      %---Turn off zoom and set flag for recomputing the axis limits
      if ~any(strcmp(RespObj.Zoom,{'tight','critical'})),
         RespObj = zoomsetup(RespObj,'off');
         RespObj.XlimMode = 'auto';
         RespObj.YlimMode = 'auto';
      end
      RespObj.RefreshAxisLimits = 1;
         
      %---Adjust labels.
      labeltog(RespObj)
            
   case 'ChannelSelector',
      Value=lower(Value);
      if ~any(strcmpi(Value,{'on';'off'})) | length(find(strcmpi(Value,{'on';'off'}))) > 1,
         error(sprintf('Bad value for response property %s.',Property))
      else
         RespObj.ChannelSelector = Value;
         SelectorHandle = get(RespObj.UIContextMenu.ChannelMenu,'UserData');
         
         %---Toggle the Selector
         switch Value,
         case 'on',
            if ishandle(SelectorHandle),
               set(SelectorHandle,'visible','on');
               figure(SelectorHandle)
            else
               %---Call function to generate a selector
               RespObj = respfcn('makeselector',RespObj);         
            end
         case 'off',
            if ishandle(SelectorHandle)
               set(SelectorHandle,'visible','off')
            end
         end % switch Value
      end
      
   case 'ColorOrder',
      [Value,stat] = cstrchk(Value,Property);
      error(stat);
      RespObj.ColorOrder = Value;
      
   case 'Grid',
      % Handles 'grid' setting except for NICPLOT and PZPLOT
      Value=lower(Value);
      if ~any(strcmpi(Value,{'on';'off'})) | length(find(strcmpi(Value,{'on';'off'}))) > 1,
         error(sprintf('Bad value for response property %s.',Property))
      else
         RespObj.Grid = Value;
         %---Change the Checked property of the Grid Context Menu
         set(RespObj.UIContextMenu.GridMenu,'Checked',Value)
         %---Call function that toggles Grid
         RespObj = respfcn('setgrid',RespObj);
      end
      
   case 'InputLabel',
      if ~iscell(Value),
         Value=cellstr(Value);
      end
      %---Check number of inputs labels with size of Plot Axes
      if ~isempty(RespObj.InputLabel) & ...
            ~isequal(length(Value),size(RespObj.PlotAxes,2)),
         error(sprintf('Bad value for response property %s.',Property))
      end
      RespObj.InputLabel= Value(:);
      labeltog(RespObj)
      
   case 'LineStyleOrder',
      [Value,stat] = cstrchk(Value,Property);
      error(stat);
      RespObj.LineStyleOrder = Value;
      
   case 'MarkerOrder',
      [Value,stat] = cstrchk(Value,Property);
      error(stat);
      RespObj.MarkerOrder = Value;
            
   case 'NextPlot',
      RespObj.NextPlot = Value;
      set([RespObj.BackgroundAxes;RespObj.PlotAxes(:)],'NextPlot',Value);
      
   case 'OutputLabel',
      if ~iscell(Value),
         Value=cellstr(Value);
      end
      NumOutputs=size(RespObj.PlotAxes,1);
      if any(strcmp(RespObj.ResponseType,{'bode','margin'}))
         NumOutputs=NumOutputs/2;
      end
      if ~isempty(RespObj.OutputLabel) & ~isequal(length(Value),NumOutputs),
         error(sprintf('Bad value for response property %s.',Property))
      end
      RespObj.OutputLabel= Value(:);
      labeltog(RespObj)
      
   case 'ResponseHandles',
      RespObj.ResponseHandles = Value;
      
   case 'SelectedChannels',
      %---Check the size of the new SelectedChannels matrix
      NumChannels = size(RespObj.PlotAxes);
      if any(strcmp(RespObj.ResponseType,{'bode','margin'}))
         NumChannels(1) = NumChannels(1)/2;
      end
      if ~isequal(NumChannels,size(Value)),
         error(sprintf('Bad value for response property %s.',Property))
      end
      RespObj.SelectedChannels = logical(Value);
      
      %---Update the Selector Figure, if applicable
      SelectorHandle = get(RespObj.UIContextMenu.ChannelMenu,'UserData');
      if ishandle(SelectorHandle),
         RespObj = respfcn('updateselector',RespObj);
      end 
      
      %---Turn the right display axes on
      configaxes(RespObj)
      
      %---Turn the right response handles on
      RespObj = modeltog(RespObj);
      
      %--Adjust labels
      labeltog(RespObj)
      
      %--Set flag to recompute axis limits
      RespObj.RefreshAxisLimits = 1;
       
   case 'SelectedModels',
      if ~isa(Value,'cell'),
         Value = {Value};
      end
      if ~isequal(size(RespObj.SelectedModels),size(Value)) | ...
            ~isequal(cellfun('ndims',RespObj.SelectedModels),cellfun('ndims',Value)) | ...
            ~isequal(cellfun('prodofsize',RespObj.SelectedModels),cellfun('prodofsize',Value))
         error(sprintf('Bad value for response property %s.',Property))
      end
      for k=1:length(Value)
         RespObj.SelectedModels{k} = logical(Value{k});
      end
      
      %---Callback to plot the correct models
      RespObj = modeltog(RespObj);
      
      %--Set flag to recompute axis limits
      RespObj.RefreshAxisLimits = 1;
       
   case 'SystemNames',
      if ~isa(Value,'cell'),
         Value=cellstr(Value);
      end
      
      SysNameMenus = RespObj.UIContextMenu.Systems.Names;
      if ~isequal(length(SysNameMenus),length(Value)),
         error(sprintf('Bad value for response property %s.',Property))
      end
      
      if ~isequal(RespObj.SystemNames,Value);
         OldNames = RespObj.SystemNames;
         RespObj.SystemNames = Value;  
         PlotOptMarkers = [findall(RespObj.PlotAxes,'Tag','PeakResponseMarker');
            findall(RespObj.PlotAxes,'Tag','RiseTimeMarker');
            findall(RespObj.PlotAxes,'Tag','SteadyStateMarker');
            findall(RespObj.PlotAxes,'Tag','SettlingTimeMarker');
            findall(RespObj.PlotAxes,'Tag','StabilityMarginMarker')];
         PlotOptMarkers = findobj(PlotOptMarkers,'Marker','o');
         
         %---Reset UIcontext System Menu labels
         for ctN=1:length(SysNameMenus),
            MenuStr = get(SysNameMenus(ctN),'Label');
            [oldname,legend] = strtok(MenuStr,' (');
            set(SysNameMenus(ctN),'Label',...
               [Value{ctN},legend]);
         end, % for ctN
         
         %---Reset any Plot Characteristic markers
         for ctM = 1:length(PlotOptMarkers),
            str = get(PlotOptMarkers(ctM),'UserData');
            Name = str{1}(9:end);
            [Name,ArrayInd]=strtok(Name,'[');
            nameind = strcmp(Name,OldNames);
            if ~isempty(ArrayInd),
               ArrayInd = [' ',ArrayInd];
               Name = Name(1:end-1);
            end
            str{1}=[sprintf('System: '),Value{nameind},ArrayInd];
            set(PlotOptMarkers(ctM),'UserData',str)
         end % for ctM
         
         %---Update System name info in LTIresponseLine userdata
         for ctSys=1:length(Value)
            RH = RespObj.ResponseHandles{ctSys};
            RH = cat(1,RH{:});
            RH = cat(1,RH{:});
            LineH = findobj(RH,'Tag','LTIresponseLines');
            for k=1:length(LineH)
               udLine = get(LineH(k),'UserData');
               % REVISIT: should make UserData format consistent!
               if isa(udLine,'struct')
                  udLine.System = Value{ctSys};
               else
                  udLine{1} = sprintf('System: %s',Value{ctSys});
               end
               set(LineH(k),'UserData',udLine)
            end
         end
       end % if ~isequal(RespObj.SystemNames,Value)
         
   case 'SystemVisibility',
      if ~iscell(Value),
         Value=cellstr(Value);
      end
      if ~all(ismember(Value,{'on';'off'})),
          error(sprintf('Bad value for response property %s.',Property))
      elseif length(RespObj.ResponseHandles)<length(Value),
         error('Length of SystemVisibility vector exceeds number of plotted responses.')
      end
      
      RespObj.SystemVisibility = Value(:);
      
      %---Call function that changes response line property
      %   Use MODELTOG as not all models may be on
      RespObj = modeltog(RespObj);
      
      %--Set flag to recompute axis limits
      RespObj.RefreshAxisLimits = 1;
      
   case {'Title','Xlabel','Ylabel'},
      if ~isstr(Value),
         error(sprintf('Bad value for response property %s.',Property))
      end
      labelH = getfield(RespObj.Handles,Property);
      if strcmp(Property,'Ylabel')
         if strcmpi(RespObj.ResponseType,'margin') | ...
            ( strcmpi(RespObj.ResponseType,'bode') & (length(RespObj.OutputLabel)==1) )
            idx = findstr(';',Value);
            if ~isempty(idx)
               v1 = Value(1:idx-1);
               v2 = Value(idx+1:end);
               v1 = deblank(fliplr(deblank(fliplr(v1))));
               v2 = deblank(fliplr(deblank(fliplr(v2))));
            else
               v1 = Value;
               v2 = '';
            end
            set(labelH(1),'String',xlate(v1));
            set(labelH(2),'String',xlate(v2));
         else
            set(labelH(1),'String',xlate(Value));
            set(labelH(2),'String','');
         end
         labelpos(RespObj); %---Update location of ylabel(s)
      else
         set(labelH,'String',xlate(Value));
      end
      Property(1) = upper(Property(1));
      builtin('subsasgn',RespObj,struct('type','.','subs',Property),xlate(Value))

   case 'UIContextMenu',
      %---Need proper error handling
      RespObj.UIContextMenu = Value;
                        
   case {'XlimMode','YlimMode'},
      % Set X and Y limit modes
      Value = lower(Value);
      if ~any(strcmpi(Value,{'auto';'manual'}))
         error(sprintf('Bad value for response property %s.',Property))
      elseif strcmpi(Property(1),'x'),
         RespObj.XlimMode = Value;
      else
         RespObj.YlimMode = Value;
      end
           
      %--Set flag to recompute axis limits
      RespObj.RefreshAxisLimits = 1;
      
   case {'Xlim','Ylim'}
      % Set X and Y limits
      Xflag = strcmpi(Property(1),'x');
      NumLims = size(RespObj.PlotAxes,1+Xflag);
      
      %---If a single non-cell limit is entered, use it as the standard
      if isa(Value,'double'),
         Lims = cell(NumLims,1);
         Lims(:) = {Value};
      elseif isa(Value,'cell')
         Lims = Value(:);
      else
         error(sprintf('Bad value for response property %s.',Property))
      end
      % No inf allowed
      if any(isinf([Lims{:}]))
         error(sprintf('Bad value for response property %s.',Property))
      end
      
      % Check dimensioning
      rs = cellfun('size',Lims,1);
      cs = cellfun('size',Lims,2);
      if any(cellfun('ndims',Lims)~=2) | any(rs~=1) | any(cs~=2),
         error('Xlim and Ylim values must be row vectors')
      else
         CheckVal = cat(1,Lims{:});
         if any(CheckVal(:,1)>=CheckVal(:,2)),
            error('Xlim and Ylim values must be non decreasing.')
         end 
      end
      
      % Turn zoom off
      if ~strcmp(RespObj.Zoom,'off')
         RespObj = zoomsetup(RespObj,'off');
      end
      
      if Xflag, 
         % Set new X limits
         for ctAx = 1:NumLims,
            set(RespObj.PlotAxes(:,ctAx),'Xlim',Lims{ctAx})
         end
         RespObj.Xlim = Lims;
         RespObj.XlimMode = 'manual';
      else
         % Set new Y limits
         for ctAx=1:NumLims,
            set(RespObj.PlotAxes(ctAx,:),'Ylim',Lims{ctAx})
         end % for ctax
         RespObj.Ylim = Lims;
         RespObj.YlimMode = 'manual';
      end  
      
      %--Set flag to recompute axis limits
      RespObj.RefreshAxisLimits = 1;
      
   case 'Zoom',
      %---Zoom setup
      NewState = lower(Value);
      OldState = RespObj.Zoom;
      ZoomInd = find(strcmpi(NewState,...
         {'off';'on';'xon';'yon';'reset';'tight';'critical'}));
      
      if isempty(ZoomInd),
         error(sprintf('Bad value for response property %s.',Property))
      elseif ~strcmpi(NewState,OldState),
         %---If zoom is on, turn it off first
         if ZoomInd>1 & any(strcmp(OldState,{'on','xon','yon'})),
            RespObj = zoomsetup(RespObj,'off');
         end
         
         %---Check correct item in zoom menu
         ZoomMenus = struct2cell(RespObj.UIContextMenu.ZoomMenu);
         set([ZoomMenus{2:end}],'Checked','off')
         if ZoomInd>1 & ZoomInd~=5,
            set(ZoomMenus{ZoomInd},'Checked','on')
         end
         
         %---Call zoom setup method
         RespObj = zoomsetup(RespObj,NewState);
      end 
      
   otherwise
      error(sprintf('Attempt to modify read-only property %s',Property))
       
   end % switch Property
end % for

