function Frame = configframe(sisodb)
%CONFIGFRAME  Create feedback structure frame.
%
%   See also SISOTOOL.

%   Author(s): Karen D. Gondoly and P. Gahinet  
%   Copyright 1986-2000 The MathWorks, Inc. 
%   $Revision: 1.12 $  $Date: 2000/08/02 16:06:39 $

% Main figure
SISOfig = sisodb.Figure;
StdUnit = get(SISOfig,'Unit');

% Dimensions parameters
FigPos = get(SISOfig,'Position');
fHeight = 3.8;
fWidth = 25;
xBorder = 2.5;
X0 = FigPos(3)-(xBorder+fWidth);
Y0 = FigPos(4)-1-fHeight;

ConfigAxes = axes('Parent',SISOfig, ...
   'Units',StdUnit, ...
   'Box','on', ...
   'Color',[1 1 1], ...
   'Position',[X0 Y0 fWidth fHeight], ...
   'Tag','ConfigurationAxes', ...
   'XColor',[0 0 0], ...
   'XTickMode','manual', ...
   'YColor',[0 0 0], ...
   'YTickMode','manual', ...
   'ZColor',[0 0 0],...
   'Ylim',[0 1],...
   'Xlim',[0 .9],...
   'HelpTopicKey','feedbackstructure');

% Sign button
ChangeSign = uicontrol('Parent',SISOfig, ...
    'Units',StdUnit, ...
    'Position',[X0 Y0 4 1.2], ...
    'String','+/-', ...
    'TooltipString','Toggle feedback sign',...
    'Callback',{@LocalChangeSign sisodb},...
    'HelpTopicKey','feedbacksign');

% Configuration selector
bWidth = 4.5;
ChangeConfig = uicontrol('Parent',SISOfig, ...
    'Units',StdUnit, ...
    'Position',[X0+fWidth-bWidth Y0 bWidth 1.2], ...
    'String','FS', ...
    'TooltipString','Alter feedback structure',...
    'HelpTopicKey','feedbackstructure',...
    'Callback',{@LocalChangeConfig sisodb}',...
    'UserData',[1;2]);

% Install listener to (re)draw loop config
setappdata(ConfigAxes,'Listener',...
    handle.listener(sisodb.LoopData,findprop(sisodb.LoopData,'Configuration'),...
    'PropertyPostSet',{@ChangedConfigCB ConfigAxes sisodb}));

% Return frame
Frame = struct(...
    'ConfigAxes',ConfigAxes,...
    'ChangeSign',ChangeSign,...
    'ChangeConfig',ChangeConfig);


%---------------- Callback functions ---------------------

%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalChangeSign %%%
%%%%%%%%%%%%%%%%%%%%%%%
function LocalChangeSign(hSrc,event,sisodb)
% Callback for "change feedback sign" event

LoopData = sisodb.LoopData;

% Start transaction
T = handle.transaction(get(findpackage('sisodata'),'DefaultDatabase'));
set(T,'Name','Change Sign',...
    'OperationStore','on','InverseOperationStore','on');

% Update sign
LoopData.FeedbackSign = -LoopData.FeedbackSign;

% Register transaction 
register(LoopData,T);

% Trigger update
dataevent(LoopData,'all');

% Update status bar and history
if LoopData.FeedbackSign>0
    Text = 'positive';
else
    Text = 'negative';
end
Status = sprintf('The compensator now uses %s feedback.',sprintf(Text));
sisodb.send('StatusChanged',...
        sisodata.dataevent(sisodb,'StatusChanged',{Status,Status}));


%%%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalChangeConfig %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
function LocalChangeConfig(hSrc,event,sisodb)
% Callback for "change feedback structure" event

LoopData = sisodb.LoopData;

% List of available configurations
AvailConfigs = get(hSrc,'UserData');

% Next configuration
NewConfig = 1+rem(LoopData.Configuration,length(AvailConfigs));

% Start transaction
T = handle.transaction(get(findpackage('sisodata'),'DefaultDatabase'));
set(T,'Name','Change Configuration',...
    'OperationStore','on','InverseOperationStore','on');

% Update configuration
LoopData.Configuration = AvailConfigs(NewConfig);

% Register transaction 
register(LoopData,T);

% Trigger update
dataevent(LoopData,'all');

% Update status bar and history
ConfigNames = {'forward','feedback'};
Status = sprintf('The compensator is now in the %s path.',sprintf(ConfigNames{NewConfig}));
sisodb.send('StatusChanged',...
        sisodata.dataevent(sisodb,'StatusChanged',{Status,Status}));


%%%%%%%%%%%%%%%%%%%%%%%
%%% ChangedConfigCB %%%
%%%%%%%%%%%%%%%%%%%%%%%
function ChangedConfigCB(hSrcProp,event,ConfigAxes,sisodb)
% Redraws feedback configuration.

CurrentConfig = get(ConfigAxes,'UserData');
NewConfig = event.NewValue;

% Redraw configuration if it does not match currently drawn
if ~isequal(NewConfig,CurrentConfig)
   % Draw loop configuration
   Configuration = loopstruct(NewConfig,ConfigAxes);
   
   % Draw feedback sign and attach listener to LoopData.FeedbackSign
   LoopData = sisodb.LoopData;
   hSignText = text(0.24,0.4,LocalGetSign(LoopData.FeedbackSign),...
       'Parent',ConfigAxes,'FontWeight','bold');
   set(hSignText,'UserData',...
       handle.listener(LoopData,findprop(LoopData,'FeedbackSign'),...
       'PropertyPostSet',{@ChangedSignCB hSignText}),...
       'HelpTopicKey','feedbacksign')
   
   % Set ButtonDownFcn's of the configuration
   set([Configuration.PlantPatch,Configuration.SensorPatch,Configuration.FilterPatch,...
           Configuration.PlantText,Configuration.SensorText,Configuration.FilterText],...
       'ButtonDownFcn',{@LocalShowData sisodb});
   set([Configuration.CompPatch,Configuration.CompText],...
       'ButtonDownFcn',{@LocalEditComp sisodb});
   
   % Set help topic key
   c = struct2cell(Configuration);
   set(cat(1,c{:}),'HelpTopicKey','feedbackstructure')
   
   % Store handles of configuration plot
   set(ConfigAxes,'UserData',NewConfig)  % store config # in axis UserData
end


%%%%%%%%%%%%%%%%%%%%%
%%% ChangedSignCB %%%
%%%%%%%%%%%%%%%%%%%%%
function ChangedSignCB(hSrcProp,event,hSignText)
% Update HG rendering of feedback sign
set(hSignText,'String',LocalGetSign(event.NewValue));


%%%%%%%%%%%%%%%%%%%%%
%%% LocalShowData %%%
%%%%%%%%%%%%%%%%%%%%%
function LocalShowData(hSrc,event,sisodb)
% Launch System Data view
send(sisodb,'ShowData');


%%%%%%%%%%%%%%%%%%%%%
%%% LocalEditComp %%%
%%%%%%%%%%%%%%%%%%%%%
function LocalEditComp(hSrc,event,sisodb)
% Brings up Edit Compensator window
send(sisodb,'ShowPZEditor');


%-------------------------Helper Functions-------------------------

%%%%%%%%%%%%%%%%%%%%
%%% LocalGetSign %%%
%%%%%%%%%%%%%%%%%%%%
function SignText = LocalGetSign(Sign)

if Sign>0,
   SignText='+';
else
   SignText='-';
end
