function Menus = figmenus(sisodb)
%FIGMENUS  Add the SISO Tool figure menus.
%
%   See also SISOTOOL.

%   Karen D. Gondoly and P. Gahinet  
%   Copyright 1986-2000 The MathWorks, Inc.
%   $Revision: 1.24 $  $Date: 2000/08/25 21:35:17 $

% Main figure
SISOfig = sisodb.Figure;
LoopData = sisodb.LoopData;

% File menu
FileMenu.Top = uimenu('Parent',SISOfig,'Label','&File');
FileMenu.Import = uimenu('Parent',FileMenu.Top,...
    'Label','&Import...',...
    'Callback',{@LocalImport sisodb [1 2]});
uimenu('Parent',FileMenu.Top,'Enable','off',...
    'Label','&Export...', ...
    'Callback',{@LocalExport sisodb});  
if usejava('MWT')
    uimenu('Parent',FileMenu.Top,...
        'Label','&Toolbox Preferences...', ...
        'Separator','on', ...
        'Callback','ctrlpref');
end
uimenu('Parent',FileMenu.Top, ...
    'Label','&Print...',...
    'Callback',{@LocalPrint sisodb 'print'}, ...
    'Separator','on', ...
    'Accelerator','P');
uimenu('Parent',FileMenu.Top, ...
    'Label','Print to &Figure',...
    'Callback',{@LocalPrint sisodb 'print2fig'});
uimenu('Parent',FileMenu.Top, ...
    'Callback',{@LocalClose sisodb},... 
    'Separator','on', ...
    'Label','&Close', ...
    'Accelerator','W');

% Edit menu
EditMenu.Top = uimenu('Parent',SISOfig,'Label','&Edit');
EditMenu.Undo = uimenu('Parent',EditMenu.Top,...
   'Label','&Undo','Enable','off', ...
   'Accelerator','Z',...
   'Callback',{@LocalUndo sisodb});  
EditMenu.Redo = uimenu('Parent',EditMenu.Top,...
   'Label','&Redo','Enable','off', ...
   'Accelerator','Y',...
   'Callback',{@LocalRedo sisodb});
% Install listener for enable state
set(EditMenu.Undo,'UserData',...
    handle.listener(LoopData,findprop(LoopData,'Undo'),...
    'PropertyPostSet',{@LocalDoMenu EditMenu.Undo 1}));
set(EditMenu.Redo,'UserData',...
    handle.listener(LoopData,findprop(LoopData,'Redo'),...
    'PropertyPostSet',{@LocalDoMenu EditMenu.Redo 0}));
% Shortcuts to plot editor right-click menus
EditMenu.Rlocus = uimenu('Parent',EditMenu.Top , ...
   'Label','&Root Locus','Enable','off', ...
   'Visible','off');
EditMenu.Bode = uimenu('Parent',EditMenu.Top , ...
   'Label','&Bode ','Enable','off', ...
   'Visible','off');
ViewMenus = [EditMenu.Rlocus;EditMenu.Bode];
for ct=1:length(sisodb.PlotEditors)
    % Install listener for editor visibility
    Editor = sisodb.PlotEditors(ct);
    vlsnr(ct) = handle.listener(Editor,findprop(Editor,'Visible'),...
        'PropertyPostSet',{@LocalToggleMenu sisodb.PlotEditors ViewMenus});
end
set(EditMenu.Top,'UserData',vlsnr)
if usejava('MWT')
    uimenu('Parent',EditMenu.Top , ...
        'Separator','on', ...
        'Callback',{@LocalEditPref sisodb}, ...
        'Label','SISO Tool &Preferences...');
end

% View menu
% RE: Includes all plots that can be viewed within main window
ViewMenu.Top = uimenu('Parent',SISOfig,'Label','&View');
ViewMenu.Editors(1) = uimenu('Parent',ViewMenu.Top, ...
    'Label','&Root Locus', ...
    'Callback',{@LocalToggleView sisodb.PlotEditors(1) 'rlocus'});
ViewMenu.Editors(2) = uimenu('Parent',ViewMenu.Top, ...
    'Label','&Bode Diagram', ...
    'Callback',{@LocalToggleView sisodb.PlotEditors(2) 'bode'});
%uimenu('Parent',ViewMenu, ...
%   'Label','Nyquist Diagram', ...
%   'Checked',EditorVis{3}, ...
%   'CallBack','sisomenu(''changeview'')', ...
%   'Tag','NyquistViewMenu');
%uimenu('Parent',ViewMenu, ...
%   'Label','Nichols Chart', ...
%   'Checked',EditorVis{4}, ...
%   'CallBack','sisomenu(''changeview'')', ...
%   'Tag','NicholsViewMenu');
uimenu('Parent',ViewMenu.Top, ...
    'Label','&System Data','Enable','off', ...
    'Separator','on',...
    'CallBack',{@LocalDataView sisodb 'SystemView'});      
uimenu('Parent',ViewMenu.Top, ...
    'Label','&Closed-Loop Poles','Enable','off',...
    'Callback',{@LocalDataView sisodb 'CLView'});
uimenu('Parent',ViewMenu.Top, ...
    'Label','&Design History','Enable','off',...
    'Callback',{@LocalDataView sisodb 'HistoryView'});

% Compensator menu
CompMenu.Top = uimenu('Parent',SISOfig,'Label','&Compensator');
if usejava('MWT')
    uimenu('Parent',CompMenu.Top, ...
        'Label','&Format...','Enable','off',...
        'CallBack',{@LocalFormatComp sisodb});
end
uimenu('Parent',CompMenu.Top, ...
    'Label','&Edit...','Enable','off',...
    'CallBack',{@LocalEditComp sisodb});
if usejava('MWT')
    uimenu('Parent',CompMenu.Top, ...
        'Label','&Store','Enable','off',...
        'Separator','on',...
        'CallBack',{@LocalStoreDesign sisodb});
    uimenu('Parent',CompMenu.Top, ...
        'Label','&Retrieve...','Enable','off',...
        'CallBack',{@LocalRetrieveDesign sisodb});
end
uimenu('Parent',CompMenu.Top, ...
    'Label','&Clear','Enable','off',...
    'CallBack',{@LocalClearComp sisodb});

% Tools menu
% RE: Includes all views and interfaces that span another window
ToolMenu.Top= uimenu('Parent',SISOfig,'Label','&Tools');
% 1. Loop response menu and submenus
RespMenu = uimenu('Parent',ToolMenu.Top, ...
    'Label','Loop &Responses...','Enable','off');
% 1a. Predefined responses
hPlot = zeros(6,1);
hPlot(1) = uimenu('Parent',RespMenu,'Label','Plant Output (Step)');
hPlot(2) = uimenu('Parent',RespMenu,'Label','Control Signal (Step)');
hPlot(3) = uimenu('Parent',RespMenu,'Label','Compensator Bode');
hPlot(4) = uimenu('Parent',RespMenu,'Label','Closed-Loop Bode');
hPlot(5) = uimenu('Parent',RespMenu,'Label','Open-Loop Nyquist');
hPlot(6) = uimenu('Parent',RespMenu,'Label','Open-Loop Nichols');
PlotList = struct(...
    'PlotType',{'step';'step';'bode';'bode';'nyquist';'nichols'},...
    'OpenLoop',{cell(0,1);cell(0,1);{'$C'};cell(0,1);{'$L'};{'$L'}},...
    'ClosedLoop',{{'$T_r2y'};{'$T_r2u'};cell(0,1);{'$T_r2y'};cell(0,1);cell(0,1)});
ToolMenu.PlotSelection = hPlot;
% 1b. Custom response setup
hc = uimenu('Parent',RespMenu,...
    'Separator','on',...
    'Label','Custom...',...
    'CallBack',{@LocalSetupResp sisodb hPlot});
set(hPlot,'CallBack',{@LocalShowResp sisodb PlotList hPlot hc}) 
% 2. Conversions
uimenu('Parent',ToolMenu.Top, ...
    'Label','Continuous/Discrete &Conversions...','Enable','off', ...
    'CallBack',{@LocalDiscretize sisodb});
if exist('simulink.mdl')==4
    uimenu('Parent',ToolMenu.Top, ...
        'Enable','off',...
        'Label','Draw &Simulink Diagram...', ...
        'Callback',{@LocalDraw LoopData});
end

% Window menu
WindowMenu.Top = uimenu(SISOfig, 'Label', '&Window', ...
    'Callback', winmenu('callback'), 'Tag', 'winmenu');
winmenu(double(SISOfig));  % Initialize the submenu

% Help menu
HelpMenu.Top = uimenu('Parent',SISOfig,'Label',sprintf('&Help'));
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('SISO Design Tool &Help'), ...
   'Callback','ctrlguihelp(''sisotoolmainhelp'');');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('Control System &Toolbox Help'), ...
   'Callback','doc(''control/'');');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('&What''s This?'), ...
   'Separator','on',...
   'CallBack',{@LocalWhatsThis sisodb});
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('&Importing/Exporting Models'), ...
   'Separator','on',...
   'CallBack','ctrlguihelp(''sisoimportexport'');');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('Tuning &Compensators'), ...
   'CallBack','ctrlguihelp(''sisocompdesign'');');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('Viewing Loop &Responses'), ...
   'Callback','ctrlguihelp(''sisoloopresponses'');');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('Viewing &Model Data'), ...
   'Callback','ctrlguihelp(''sisomodeldata'');');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('&Storing/Retrieving Designs'), ...
   'Callback','ctrlguihelp(''sisosavecomp'');');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('C&ustomizing the SISO Tool'), ...
   'Callback','ctrlguihelp(''sisocustomizing'');');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('&Demos'), ...
   'Separator','on',...
   'CallBack','demo toolbox control');
uimenu('Parent',HelpMenu.Top, ...
   'Label',sprintf('&About the Control System Toolbox'), ...
   'Separator','on',...
   'CallBack','aboutcst');

Menus = struct(...
    'File',FileMenu,...
    'Edit',EditMenu,...
    'View',ViewMenu,...
    'Tools',ToolMenu,...
    'Compensator',CompMenu,...
    'Window',WindowMenu,...
    'Help',HelpMenu);

%-------------------------Local Functions-------------------------

%%%%%%%%%%%%%%%%%%%
%%% LocalImport %%%
%%%%%%%%%%%%%%%%%%%
function LocalImport(hSrc,event,sisodb,AvailConfig)
% Opens Import dialog
importdlg(sisodb,AvailConfig);


%%%%%%%%%%%%%%%%%%%
%%% LocalExport %%%
%%%%%%%%%%%%%%%%%%%
function LocalExport(hSrc,event,sisodb)
% Opens export dialog

% REVISIT: remove this when Java runs on HP/IBM
if usejava('MWT')
    ExportFrame = get(hSrc,'UserData');
    if isempty(ExportFrame)
        % Create export dialog
        ExportFrame = exportdlg(sisodb);
        set(hSrc,'UserData',ExportFrame);
    else
        % Bring it up front
        set(ExportFrame,'Minimize','off','Visible','off','Visible','on');
    end
else
    % HG back up
    ExportData = exportdata2(sisodb.LoopData);
    exportlti('initialize',sisodb.Figure,ExportData,'SISO Tool Export');
end
   
   
%%%%%%%%%%%%%%%%%%
%%% LocalPrint %%%
%%%%%%%%%%%%%%%%%%
function LocalPrint(hSrcProp,event,sisodb,request)
% Print callback
print(sisodb,request);


%%%%%%%%%%%%%%%%%%
%%% LocalClose %%%
%%%%%%%%%%%%%%%%%%
function LocalClose(hSrc,event,sisodb)
% Close SISO Tool
delete(sisodb.Figure);


%%%%%%%%%%%%%%%%%
%%% LocalUndo %%%
%%%%%%%%%%%%%%%%%
function LocalUndo(hMenu,event,sisodb)
% Undo callback
Status = undo(sisodb.LoopData);
% Update status and history
sisodb.send('StatusChanged',...
    sisodata.dataevent(sisodb,'StatusChanged',{Status,Status}));


%%%%%%%%%%%%%%%%%
%%% LocalRedo %%%
%%%%%%%%%%%%%%%%%
function LocalRedo(hMenu,event,sisodb)
% Redo callback
Status = redo(sisodb.LoopData);
% Update status and history
sisodb.send('StatusChanged',...
    sisodata.dataevent(sisodb,'StatusChanged',{Status,Status}));


%%%%%%%%%%%%%%%%%%%
%%% LocalDoMenu %%%
%%%%%%%%%%%%%%%%%%%
function LocalDoMenu(hProp,event,hMenu,MinStackLength)
% Update menu state and label
Stack = event.NewValue;
if length(Stack)<=MinStackLength
    % Empty stack
    set(hMenu,'Enable','off','Label',sprintf('&%s',get(hProp,'Name')))
else
    % Get last transaction's name
    ActionName = get(Stack(end),'Name');
    Label = sprintf('&%s %s',get(hProp,'Name'),ActionName);
    set(hMenu,'Enable','on','Label',Label)
end


%%%%%%%%%%%%%%%%%%%%% 
%%% LocalEditPref %%% 
%%%%%%%%%%%%%%%%%%%%% 
function LocalEditPref(hSrc,event,sisodb) 
% Edit SISO Tool prefs 
edit(sisodb.Preferences); 


%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalToggleView %%%
%%%%%%%%%%%%%%%%%%%%%%%
function LocalToggleView(hSrc,event,Editor,Type)
% Toggle editor visibility (hSrc=uimenu)
if strcmp(get(hSrc,'Checked'),'on')
    set(Editor,'Visible','off');
    Status = 'hidden';
else
    set(Editor,'Visible','on');
    Status = 'visible';
end
% Confirm operation in status bar
switch Type
case 'rlocus'
    Editor.up.Status = sprintf('The Root Locus plot is now %s.',Status);
case 'bode'
    Editor.up.Status = sprintf('The Bode Diagram is now %s.',Status);
end 
    

%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalToggleMenu %%%
%%%%%%%%%%%%%%%%%%%%%%%
function LocalToggleMenu(hSrc,event,Editors,ViewMenus)
% Toggle visibility of Edit menus associated with plot editors
set(ViewMenus,'Separator','off',{'Visible'},get(Editors,{'Visible'}))
idxVis = find(strcmp(get(ViewMenus,'Visible'),'on'));
if ~isempty(idxVis)
    set(ViewMenus(idxVis(1)),'Separator','on')
end


%%%%%%%%%%%%%%%%%%%%%
%%% LocalDataView %%%
%%%%%%%%%%%%%%%%%%%%%
function LocalDataView(hSrcProp,event,sisodb,ViewID)
% Launches System Data view
addview(sisodb,ViewID);


%%%%%%%%%%%%%%%%%%%%%
%%% LocalShowResp %%%
%%%%%%%%%%%%%%%%%%%%%
function LocalShowResp(hSrc,event,sisodb,PlotList,hCheckMenus,hCustom)
% Show subset of predefined plots
% Update menu state
if strcmp(get(hSrc,'Checked'),'on')
    set(hSrc,'Checked','off')
else
    set(hSrc,'Checked','on')
end
PlotSelection = PlotList(strcmp(get(hCheckMenus,'Checked'),'on'));

% Hide dialog for custom setup
set(get(hCustom,'UserData'),'Visible','off')

% Update reponse plot
respview(sisodb,PlotSelection);


%%%%%%%%%%%%%%%%%%%%%%
%%% LocalSetupResp %%%
%%%%%%%%%%%%%%%%%%%%%%
function LocalSetupResp(hSrc,event,sisodb,hCheckMenus)
% Open response setup dialog
% hSrc = handle of Custom... menu (UserData contains dialog handle)

% Open dialog
respdlg(sisodb,hSrc);

% Unselect all check menus
set(hCheckMenus,'Checked','off')



%%%%%%%%%%%%%%%%%%%%
%%% LocalConvert %%%
%%%%%%%%%%%%%%%%%%%%
function LocalDiscretize(hSrc,event,sisodb)
% Opens continous/discrete conversion UI

%---Callback for the Convert to Discrete/Continuous menu 
% Check at most one model in P,H,F is dynamic
LoopData = sisodb.LoopData;
if sum([isstatic(LoopData.Plant.Model) ; ...
            isstatic(LoopData.Sensor.Model) ; ...
            isstatic(LoopData.PreFilter.Model)]) < 2,
    WarnTxt = {'Continuous/discrete conversions are performed' ; ...
            'independently on each of the components P, H, C, and F.';...
            ' ';...
            'The resulting feedback loop may not accurately describe';...
            'your system when all components have dynamics.';...
            ' '};
    if strcmp(questdlg(WarnTxt,'Conversion Warning','OK','Cancel','Cancel'),'Cancel')
        return
    end
end

% Open conversion GUI (modal)
c2dtool(sisodb);


%%%%%%%%%%%%%%%%%
%%% LocalDraw %%%
%%%%%%%%%%%%%%%%%
function LocalDraw(hSrcProp,event,LoopData)
% Print callback
drawdiagram(LoopData);


%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalFormatComp %%%
%%%%%%%%%%%%%%%%%%%%%%%
function LocalFormatComp(hSrc,event,sisodb)
% Callback for Compensator:Format menu
edit(sisodb.Preferences); 
selecttab(sisodb.Preferences,3);


%%%%%%%%%%%%%%%%%%%%%%
%%% LocalEditComp %%%
%%%%%%%%%%%%%%%%%%%%%%
function LocalEditComp(hSrc,event,sisodb)
% Callback for "edit compensator" event
show(sisodb.TextEditors(1));


%%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalStoreDesign %%%
%%%%%%%%%%%%%%%%%%%%%%%%
function LocalStoreDesign(hSrc,event,sisodb)
% Adds current design to design history
StoreAs = storedlg(sisodb,'Store as:','Store Compensator');
if ~isempty(StoreAs),
    % Store current design
    savecomp(sisodb.LoopData,StoreAs);
    % Update status bar and history
    Status = sprintf('Stored compensator as %s.',StoreAs);
    sisodb.send('StatusChanged',...
        sisodata.dataevent(sisodb,'StatusChanged',{Status,Status}));
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalRetrieveDesign %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%
function LocalRetrieveDesign(hSrc,event,sisodb)
% Adds current design to design history
retrievedlg(sisodb);


%%%%%%%%%%%%%%%%%%%%%%
%%% LocalClearComp %%%
%%%%%%%%%%%%%%%%%%%%%%
function LocalClearComp(hSrc,event,sisodb)
% Callback for "clear compensator" event

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

% Reset compensator to 1 (error-free, may adjust sample time)
C = struct('Name','untitledC','Model',zpk(1));
importdata(sisodb.LoopData,[],[],[],C);

% Commit and register transaction
register(sisodb.LoopData,T);

% Notify peers of data change
dataevent(sisodb.LoopData,'all');

% Update status bar and history
Status = 'Cleared compensator.';
sisodb.send('StatusChanged',...
        sisodata.dataevent(sisodb,'StatusChanged',{Status,Status}));

    
%%%%%%%%%%%%%%%%%%%%%%
%%% LocalWhatsThis %%%
%%%%%%%%%%%%%%%%%%%%%%
function LocalWhatsThis(hSrc,event,sisodb)
% Callback for What's This menu item
HelpIcon = sisodb.HG.Toolbar(end);
set(HelpIcon,'State','on')

    
