function h = loopdata
%LOOPDATA  Constructor for loop data repository.

%   Author(s): P. Gahinet
%   Copyright 1986-2000 The MathWorks, Inc. 
%   $Revision: 1.8 $ $Date: 2000/09/07 20:50:15 $

if nargout==0
    % Register class 
    c = schema.class(findpackage('sisodata'),'loopdata');
    
    % Public properties
    schema.prop(c,'ClosedLoop','mxArray');     % Closed loop model
    schema.prop(c,'Compensator','handle');     % Compensator data (@compensator object)
    schema.prop(c,'Configuration','double');   % Loop configuration
    schema.prop(c,'FeedbackSign','double');    % Feedback sign
    schema.prop(c,'Margins','mxArray');        % Stability margins
    schema.prop(c,'OpenLoop','mxArray');       % (Normalized) open loop
    schema.prop(c,'Plant','handle');           % Plant data (@model object)
    schema.prop(c,'PreFilter','handle');       % Prefilter data (@model object)
    schema.prop(c,'SavedDesigns','mxArray');   % Design history
    schema.prop(c,'Sensor','handle');          % Sensor data (@model object)
    schema.prop(c,'SystemName','String');      % Control system name
    
    % Private properties
    schema.prop(c,'Redo','handle vector');           % Redo stack
    schema.prop(c,'Undo','handle vector');           % Undo stack
    p = schema.prop(c,'Listeners','handle vector');  % Listeners
    set(p,'AccessFlags.PublicGet','off','AccessFlags.PublicSet','off');

    % Events
    schema.event(c,'LoopDataChanged');    % Notifies of change in loop data
    
else
    % Create class instance
    h = sisodata.loopdata;
    
    % Initialize content of Compensator
    h.Compensator = sisodata.compdata;
    
    % Initialize design history
    h.SavedDesigns = struct(...
        'Name',cell(0,1),...
        'Configuration',[],...
        'FeedbackSign',[],...
        'Plant',[],...
        'Sensor',[],...
        'PreFilter',[],...
        'Compensator',[]);
    
    % Listeners to @loopdata properties
    lsnr(1) = handle.listener(h,findprop(h,'OpenLoop'),'PropertyPreGet',@LocalGetOpenLoop);
    lsnr(2) = handle.listener(h,findprop(h,'Margins'),'PropertyPreGet',@LocalGetMargins);
    lsnr(3) = handle.listener(h,findprop(h,'ClosedLoop'),'PropertyPreGet',@LocalGetClosedLoop);
    
    % Listeners to @compdata properties
    lsnr(4) = handle.listener(h.Compensator,findprop(h.Compensator,'Format'),...
        'PropertyPostSet',{@LocalChangeFormat h});
    h.Listeners = lsnr;
end


%-------------------------Listeners-------------------------


%%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalGetOpenLoop %%%
%%%%%%%%%%%%%%%%%%%%%%%%
function LocalGetOpenLoop(hProp,event)
% Computes normalized open-loop if not already available
LoopData = event.AffectedObject;
if isempty(LoopData.OpenLoop)
    openloop(LoopData);
end

%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalGetMargins %%%
%%%%%%%%%%%%%%%%%%%%%%%
function LocalGetMargins(hProp,event)
% Computes stability margins if not already available
LoopData = event.AffectedObject;
if isempty(LoopData.Margins)
    getmargins(LoopData);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalGetClosedLoop %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%
function LocalGetClosedLoop(hProp,event)
% Computes closed-loop model if not already available
LoopData = event.AffectedObject;
if isempty(LoopData.ClosedLoop)
    closedloop(LoopData);
end

%%%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalChangeFormat %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
function LocalChangeFormat(hProp,event,LoopData)
% Update all plots when changing format (the "normalized" data used in the root locus
% and bode editors becomes stale, causing bad behaviors when changing format, then
% modifying the loop gain, see geck 88273)
dataevent(LoopData,'all');
