function varargout = controlSystemDesigner(varargin)
%controlSystemDesigner Control System Designer App.
%
%   controlSystemDesigner opens the Control System Designer app.  This User
%   Interface lets you design single-input/single-output (SISO)
%   compensators by graphically interacting with the root locus, Bode, and
%   Nichols plots of the open-loop system.  To import the plant data into
%   the app, select the Import item from the File menu. By default, the
%   control system configuration is
%
%             r -->[ F ]-->O--->[ C ]--->[ G ]----+---> y
%                        - |                      |
%                          +-------[ H ]----------+
%
%   where C and F are tunable compensators.
%
%   controlSystemDesigner(G) specifies the plant model G to be used in the
%   app. Here G is any linear model created with TF, ZPK, or SS.
%
%   controlSystemDesigner(G,C) and controlSystemDesigner(G,C,H,F) further
%   specify values for the feedback compensator C, sensor H, and prefilter
%   F.  By default, C, H, and F are all unit gains.
%
%   controlSystemDesigner(VIEWS) or controlSystemDesigner(VIEWS,G,...)
%   specifies the initial set of views for graphically editing C and F.
%   You can set VIEWS to any of the following strings or combination of
%   strings:
%       'rlocus'      Root locus plot
%       'bode'        Bode diagram of the open-loop response
%       'nichols'     Nichols plot of the open-loop response
%       'filter'      Bode diagram of the prefilter F
%   For example
%       controlSystemDesigner({'nichols','bode'})
%   opens a Control System Designer app showing the Nichols plot and Bode
%   diagrams for the open loop CGH.
%
%   controlSystemDesigner(INITDATA) initializes the Control System Designer
%   app with more general control system configurations.  Use SISOINIT to
%   build the initialization data structure INITDATA.
%
%   controlSystemDesigner(SESSIONDATA) opens the Control System Designer
%   app with a previously saved session where SESSIONDATA is the MAT file
%   for the saved session.
%
%   See also SISOINIT, LINEARSYSTEMANALYZER, RLOCUS, BODE, NICHOLS.

%   Copyright 1986-2020 The MathWorks, Inc.

% Obsolete Syntax:  extra argument OPTIONS (structure) to specify any
% of the following options:
%   OPTIONS.Location    Location of C ('forward' for forward path,
%                       'feedback' for return path)
%   OPTIONS.Sign        Feedback sign (-1 for negative, +1 for positive)

varargin = controllib.internal.util.hString2Char(varargin);

Version = controllibutils.CSTCustomSettings.getControlSystemDesignerVersion;
switch Version
    case {2,3}
        ni=nargin;
        narginchk(0,6)
        try
            isLoading = false;
            h = [];
            if ni==0
                % Open GUI w/o data
                for ct = 1:4
                    Models{ct} = tf(1);
                end
                Arch = ctrlguis.csdesignerapp.data.architectures.internal.Config1Architecture(Models{2},Models{4},Models{1},Models{3});
                h = ctrlguis.csdesignerapp.internal.ControlSystemDesignerApp(Arch);
                DesignViews = {'rlocus','bode'};
                AnalysisView = true;
            elseif isequal(length(varargin),1) && isa(varargin{1},'slTuner')
                Arch = ctrlguis.csdesignerapp.data.architectures.internal.SimulinkArchitecture(varargin{1});
                h = ctrlguis.csdesignerapp.internal.ControlSystemDesignerApp(Arch);
                DesignViews = {};
                AnalysisView = false;
            elseif isequal(length(varargin),1) && isa(varargin{1},'char') && ...
                    ~any(strcmpi(varargin{1},{'rlocus','bode','nichols','filter'}))
                DesignViews = {};
                AnalysisView = false;
                % load project (Version 3,2)
                sw = ctrlMsgUtils.SuspendWarnings('Slcontrol:sllinearizer:AddPointOpening','Control:ltiobject:UpdatePreviousVersion',...
                                                  'Simulink:Commands:InvSimulinkObjectName','Slcontrol:controldesign:InvalidParam2',...
                                                  'Slcontrol:sllinearizer:NonExistentModel');
                S = load(varargin{1});
                delete(sw);
                if ~isempty(S) && ...
                        ((isfield(S,getString(message('Control:designerapp:CSDSessionName'))) && isa(S.ControlSystemDesignerSession,'ctrlguis.csdesignerapp.data.internal.SessionData'))...
                        ||  (isfield(S,'Projects') && isa(S.Projects,'controlnodes.SISODesignTask')) ...
                        ||  (isfield(S,'Projects') && isa(S.Projects,'explorer.Project')))
                    % Open GUI w/o data
                    for ct = 1:4
                        Models{ct} = tf(1);
                    end
                    Arch = ctrlguis.csdesignerapp.data.architectures.internal.Config1Architecture(Models{2},Models{4},Models{1},Models{3});
                    h = ctrlguis.csdesignerapp.internal.ControlSystemDesignerApp(Arch);
                    isLoading = true;
                    h.loadSession(S);
                    isLoading = false;
                else
                    % Version 1
                    [fname,~] = strtok(varargin{1},'.');
                    fullname = [fname '.mat'];
                    sw = ctrlMsgUtils.SuspendWarnings; %#ok<NASGU>
                    s = load(fullname,'SessionData');
                    clear sw
                    if isempty(fields(s))
                        error(message('Control:compDesignTask:SISOTool1'))
                    else
                        for ct = 1:4
                            Models{ct} = tf(1);
                        end
                        Arch = ctrlguis.csdesignerapp.data.architectures.internal.Config1Architecture(Models{2},Models{4},Models{1},Models{3});
                        h = ctrlguis.csdesignerapp.internal.ControlSystemDesignerApp(Arch);
                        isLoading = true;
                        h.loadSession(s);
                        isLoading = false;
                    end
                end
            elseif isa(varargin{1},'sisodata.design') || isa(varargin{1}, 'sisogui.session')||...
                    isa(varargin{1},'ctrlguis.csdesignerapp.data.internal.SessionData')
                DesignViews = {};
                AnalysisView = false;
                % From sisoinit
                for ct = 1:4
                    Models{ct} = tf(1);
                end
                Arch = ctrlguis.csdesignerapp.data.architectures.internal.Config1Architecture(Models{2},Models{4},Models{1},Models{3});
                h = ctrlguis.csdesignerapp.internal.ControlSystemDesignerApp(Arch);
                isLoading = true;
                h.loadSession(varargin{1});
                isLoading = false;
            else
                AnalysisView = true;
                % Parse input list
                % a) Views
                LastInput = 0;
                ValidViews = {'rlocus','bode','nichols','filter'};
                if ni && (iscellstr(varargin{1}) || ischar(varargin{1}))
                    DesignViews = varargin{1};
                    if ~iscell(DesignViews)
                        DesignViews = {DesignViews};
                    end
                    AllValid = all(ismember(DesignViews,ValidViews));
                    if ~AllValid,
                        error(message('Control:compDesignTask:SISOTool2'))
                    end
                    LastInput = LastInput + 1;
                    UseDefaultDesignViews = false;
                else
                    UseDefaultDesignViews = true;
                    DesignViews = {'rlocus','bode'};
                end
                
                % Models G,C,H,F
                Models = cell(4,1);
                for ct=1:min(4,ni-LastInput),
                    NextArg = varargin{LastInput+1};
                    isModel = isa(NextArg,'lti'); % REVISIT: should be "system" parent class
                    if ~isa(NextArg,'double') && ~isModel
                        % done scanning model inputs
                        break
                    elseif issparse(NextArg)
                        error(message('Control:designerapp:ErrorSparseModel'));
                    else
                        if ~isequal(NextArg,[])  % skip []'s
                            Models{ct} = NextArg;
                        end
                    end
                    LastInput = LastInput+1;
                end
                
                % Options (last arg)
                if ni>LastInput && isa(varargin{LastInput+1},'struct')
                    Options = varargin{LastInput+1};
                    LastInput = LastInput+1;
                else
                    Options = [];
                end
                
                % There should be no more input argument
                if ni>LastInput,
                    error(message('Control:general:InvalidSyntaxForCommand','sisotool','sisotool'))
                end
                
                % Read options
                if isfield(Options,'Location')
                    LoopConfig = Options.Location;
                    if ~isa(LoopConfig,'char')
                        error(message('Control:compDesignTask:SISOTool3'))
                    else
                        switch lower(LoopConfig(1:min(2,end))),
                            case 'fo',
                                LoopConfig = 1;
                            case 'fe',
                                LoopConfig = 2;
                            otherwise,
                                error(message('Control:compDesignTask:SISOTool3'))
                        end
                    end
                else
                    LoopConfig = 1;
                end
                
                if isfield(Options,'Sign')
                    LoopSign = Options.Sign;
                    if ~ismember(LoopSign,[1,-1]),
                        error(message('Control:compDesignTask:SISOTool4'))
                    end
                else
                    LoopSign = -1;
                end
                
                % Build init structure
                for ct=1:4
                    if isempty(Models{ct})
                        Models{ct} = tf(1);
                    end
                end
                
                if UseDefaultDesignViews
                    if any(cellfun(@(x)isa(x,'frd'),Models))
                        DesignViews = {'bode'};
                    else
                        DesignViews = {'rlocus','bode'};
                    end
                end
                
                % At this point, we have models, design views, loop sign,
                % configuration
                ArchClass = sprintf('Config%dArchitecture',LoopConfig);
                Arch = ctrlguis.csdesignerapp.data.architectures.internal.(ArchClass)(Models{2},Models{4},Models{1},Models{3});
                LS = Arch.getLoopSignWithID;
                setLoopSignWithID(Arch, LS{1},LoopSign);
                h = ctrlguis.csdesignerapp.internal.ControlSystemDesignerApp(Arch);
            end
            createPlots(h,AnalysisView,DesignViews);
            if nargout
                varargout{1} = h;
            end
        catch ME
            if isLoading && isvalid(h)
                % Error during loading. Close the invalid control system
                % designer session
                delete(h);
            end
            throw(ME);
        end
    case 1
        ni=nargin;
        narginchk(0,7)
        if ni && isstruct(varargin{end}) && isfield(varargin{end},'FromSisotool')
            InputNames = varargin{end};
            idx = ni-1;
        else
            InputNames = [];
            idx = ni;
        end
        % Parse inputs
        DataProvided = false;
        SessionProvided = false;
        OldSessionProvided = false;
        if idx==0
            % Open GUI w/o data
            InitData = sisoinit(1);  % default config
            DataProvided = true;
            %InitData.G = [];         % no data specified
        elseif isequal(idx,1) && isa(varargin{1},'char') ...
                && ~any(strcmpi(varargin{1},{'rlocus','bode','nichols','filter'}));
            try
                explorer.loadProject(varargin{1});
                if nargout
                    varargout{1} = [];
                end
                return
            catch %#ok<CTCH>
                [fname,~] = strtok(varargin{1},'.');
                fullname = [fname '.mat'];
                sw = ctrlMsgUtils.SuspendWarnings; %#ok<NASGU>
                s = load(fullname,'SessionData');
                clear sw
                if isempty(fields(s))
                    error(message('Control:compDesignTask:SISOTool1'))
                else
                    OldSessionProvided = true;
                    InitData = sisoinit(1);
                    DataProvided = true;
                end
            end
        elseif isa(varargin{1},'sisodata.design')
            % Open GUI with setup object
            InitData = varargin{1};
            DataProvided = true;
        elseif isa(varargin{1},'sisogui.session')
            % Open GUI with session data
            SessionData = varargin{1};
            InitData = SessionData.Designs(1);
            SessionProvided = true;
        else
            % Parse input list
            % a) Views
            
            LastInput = 0;
            ValidViews = {'rlocus','bode','nichols','filter'};
            
            if idx && (iscellstr(varargin{1}) || ischar(varargin{1}))
                DesignViews = varargin{1};
                if ~iscell(DesignViews)
                    DesignViews = {DesignViews};
                end
                AllValid = all(ismember(DesignViews,ValidViews));
                if ~AllValid,
                    error(message('Control:compDesignTask:SISOTool2'))
                end
                LastInput = LastInput + 1;
                UseDefaultDesignViews = false;
            else
                UseDefaultDesignViews = true;
                DesignViews = {'rlocus','bode'};
            end
            
            idxG = LastInput+1; % position of G argument
            
            if idx>=idxG
                if isempty(InputNames)
                    % System name is inherited from G
                    InitData.Name = inputname(idxG);
                else
                    % System name is inherited from G
                    InitData.Name = InputNames.InitData; %#ok<STRNU>
                end
            end
            
            % Models G,C,H,F
            ModelID = {'G';'C';'H';'F'};
            Models = cell(4,1);
            ModelNames = ModelID; % strcat('untitled',ModelID);
            ModelVars = repmat({''},[4 1]);
            for ct=1:min(4,idx-LastInput),
                NextArg = varargin{LastInput+1};
                isModel = isa(NextArg,'lti'); % REVISIT: should be "system" parent class
                if ~isa(NextArg,'double') && ~isModel
                    % done scanning model inputs
                    break
                else
                    if ~isequal(NextArg,[])  % skip []'s
                        DataProvided = true;
                        Models{ct} = NextArg;
                        if isempty(InputNames)
                            VarName = inputname(LastInput+1);
                        else
                            VarName = InputNames.ModelVars{ct};
                        end
                        
                        % Model name
                        if isa(NextArg,'lti') && ~isempty(NextArg.Name)
                            ModelNames{ct} = NextArg.Name;
                        end
                        % Variable name
                        ModelVars{ct} = VarName;
                    end
                end
                LastInput = LastInput+1;
            end
            
            % Options (last arg)
            if idx>LastInput && isa(varargin{LastInput+1},'struct')
                Options = varargin{LastInput+1};
                LastInput = LastInput+1;
            else
                Options = [];
            end
            
            % There should be no more input argument
            if idx>LastInput,
                error(message('Control:general:InvalidSyntaxForCommand','sisotool','sisotool'))
            end
            
            % Read options
            if isfield(Options,'Location')
                LoopConfig = Options.Location;
                if ~isa(LoopConfig,'char')
                    error(message('Control:compDesignTask:SISOTool3'))
                else
                    switch lower(LoopConfig(1:min(2,end))),
                        case 'fo',
                            LoopConfig = 1;  % forward loop
                        case 'fe',
                            LoopConfig = 2;  % feedback loop
                        otherwise,
                            error(message('Control:compDesignTask:SISOTool3'))
                    end
                end
            else
                LoopConfig = 1;
            end
            
            if isfield(Options,'Sign')
                LoopSign = Options.Sign;
                if ~ismember(LoopSign,[1,-1]),
                    error(message('Control:compDesignTask:SISOTool4'))
                end
            else
                LoopSign = -1;
            end
            
            % Build init structure
            InitData = sisoinit(LoopConfig);
            InitData.FeedbackSign = LoopSign;
            hasFRD = false;
            for ct=1:4
                id = ModelID{ct};
                InitData.(id).Name = ModelNames{ct};
                InitData.(id).Variable = ModelVars{ct};
                if ~isempty(Models{ct})
                    InitData.(id).Value = Models{ct};
                    if isa(Models{ct},'frd') % covers idfrd too
                        hasFRD = true;
                    end
                end
            end
            
            if UseDefaultDesignViews
                if hasFRD
                    DesignViews = {'bode'};
                else
                    DesignViews = {'rlocus','bode'};
                end
            end
            
            idxf = find(strcmp(DesignViews,'filter'));
            if isempty(idxf)
                InitData.CL1.View = cell(1,0);
            end
            DesignViews(idxf) = [];
            InitData.OL1.View = DesignViews;
        end
        
        % Number of Loops
        LoopID = InitData.Loops;
        nL = length(LoopID);
        
        %
        %---- CREATE DATABASE ---------------
        %
        
        % Create model database
        LoopData = sisodata.loopdata;
        
        % Initialize configuration
        LoopData.setconfig(InitData)    % triggers config. rendering
        
        % Validate model data before creating GUI (avoids pain of destroying it)
        if DataProvided
            try
                InitData = checkdata(LoopData,InitData);
            catch ME
                throw(ME)
            end
        end
        
        % Create GUI database
        sisodb = sisogui.sisotool;
        sisodb.LoopData = LoopData;
        
        % Show waitbar
        hWaitbar = waitbar(0,getString(message('Control:compDesignTask:strSisoToolLoading')));
        
        
        %
        %---- CREATE GUI ---------------
        %
        
        % Create figure
        SISOfig = LocalOpenFig;
        sisodb.Figure = handle(SISOfig);
        
        % Create event manager
        sisodb.EventManager = ctrluis.framemgr(SISOfig);
        sisodb.EventManager.EventRecorder = ctrluis.recorder;
        
        % Initialize preferences
        waitbar(0.1,hWaitbar)
        sisodb.Preferences = LocalInitPref(sisodb,SISOfig);
        CompFormat = sisodb.Preferences.CompensatorFormat;
        for ct=1:length(LoopData.C)
            LoopData.C(ct).Format = CompFormat;
        end
        
        % Render GUI frames, menus, and toolbar
        addcontrols(sisodb)
        
        % Install GUI-wide listeners
        addlisteners(sisodb)
        
        % Create text editors
        waitbar(0.3, hWaitbar)
        ted1 = sisogui.pzeditor(LoopData, sisodb);
        ted2 = sisogui.tooldlg([]);
        sisodb.TextEditors = [ted1;ted2];
        
        
        %
        %---- RENDER LOOP DATA ---------------
        %
        
        
        % Render loop parameters
        if ~isempty(InitData.Name)
            LoopData.Name = InitData.Name;  % triggers fig name update
        end
        
        if SessionProvided
            % Start up with saved session
            % Make figure visible
            waitbar(0.5,hWaitbar)
            set(SISOfig,'Visible','on')
            % Load session data
            waitbar(0.7,hWaitbar)
            sisodb.load(SessionData,'norecord')
            % Empty start (no plant data)
            ImportStatus = getString(message('Control:compDesignTask:msgRightClickForDesignOptions'));
        else
            waitbar(0.7,hWaitbar)
            if DataProvided,
                % Import model data if provided (RE: already validated, so no error here...)
                LoopData.importdata(InitData);
                LoopData.LoopView = InitData.getLoopView;
                % Force update of configuration-dependent views and menus
                % RE: once all names are correct
                LoopData.send('ConfigChanged')
                % Notify peers of data change
                LoopData.dataevent('all');
                % Push placeholder "first import" transaction onto stack
                T = ctrluis.transaction(LoopData);
                sisodb.EventManager.record(T);
                % Status message
                ImportStatus = getString(message('Control:compDesignTask:msgRightClickForDesignOptions'));
            else
                LoopData.importdata(InitData);
                LoopData.LoopView = InitData.getLoopView;
                % Force update of configuration-dependent views and menus
                LoopData.send('ConfigChanged')
                % Empty start (no plant data)
                ImportStatus = getString(message('Control:compDesignTask:strUseImportFileMenu'));
            end
            % Make figure and graphical editors visible (maximum of 4)
            waitbar(0.9,hWaitbar)
            %  set(SISOfig,'Visible','on')
            if length(sisodb.PlotEditors)>6
                warning(message('Control:compDesignTask:MaxEditors'))
            end
            %  set(sisodb.PlotEditors(1:min(4,end)),'Visible','on');
        end
        
        
        % Create graphical design tools (editors)
        % Revisit
        if ~SessionProvided
            for idxL=1:nL
                [~,iu] = unique(InitData.(LoopID{idxL}).View);
                LoopViews = InitData.(LoopID{idxL}).View(sort(iu));
                if InitData.(LoopID{idxL}).getProperty('Feedback')
                    % Create one editor per requested view
                    for ct=1:length(LoopViews)
                        switch LoopViews{ct}
                            case 'rlocus'
                                sisodb.addeditor('sisogui.rleditor',idxL);      % Root Locus Editor
                            case 'bode'
                                sisodb.addeditor('sisogui.bodeditorOL',idxL);
                            case 'nichols'
                                sisodb.addeditor('sisogui.nicholseditor',idxL);
                        end
                    end
                else
                    % Filter component
                    if any(strcmp(LoopViews,'rlocus') | strcmp(LoopViews,'nichols'))
                        warning(message('Control:compDesignTask:EditorRequiresOpenLoop'))
                    end
                    if any(strcmp(LoopViews,'bode'))
                        sisodb.addeditor('sisogui.bodeditorF',idxL);
                        % Editors = [Editors ; sisogui.bodeditorF(LoopData,1)]; % Filter Bode editor
                    end
                end
            end
            
            % Initialize plot editors
            waitbar(0.95,hWaitbar)
        end
        
        
        % --- Add to project explorer
        % Create the project explorer
        %% Get the frame and workspace handles
        [projectframe,workspace,treemanager] = slctrlexplorer;
        
        
        % Block explorer to prevent closing during a load
        % and set treemanager as busy to prevent closing of gui
        projectframe.setBlocked(true, []);
        treemanager.setBusy(true);
        
        % Make sure to reset state of projectframe and treemanager if error occurs
        try
            % Get the default nodes
            sisotask = controlnodes.SISODesignTask(getString(message('Control:compDesignTask:strSISODesignTask')),sisodb);
            sisotask.Label = sisotask.createDefaultName(getString(message('Control:compDesignTask:strSISODesignTask')), workspace);
            sisodb.LoopData.Name = sisotask.Label;
            
            % Add the SISO Task node to the workspace
            workspace.addNode(sisotask);
            sisodb.setNode(sisotask);
            
            % Create DesignTask
            junk = getTaskPanel(sisodb); %#ok<NASGU>
            
            % Show Architecture Panel
            sisodb.DesignTask.show;
            sisodb.DesignTask.refreshTab;
            
            % Show CETM
            projectframe.toFront;
            projectframe.setVisible(true);
            
            % Show SISOTOOL
            set(SISOfig,'Visible','on')
            if isempty(sisodb.PlotEditors)
                % Call layout when no graph editors are present so status text is
                % not improperly rendered.
                sisodb.layout;
            else
                % Setting the editor visibility on calls the layout function
                set(sisodb.PlotEditors(1:min(6,end)),'Visible','on');
            end
            
            if OldSessionProvided
                try
                    load(sisodb,s.SessionData,'norecord')
                    % Update status bar and history
                    Msg = getString(message('Control:compDesignTask:strLoadedSessionFromFile',fname));
                    sisodb.EventManager.newstatus(Msg);
                    sisodb.EventManager.recordtxt('history',Msg);
                catch ME %#ok<NASGU>
                    errordlg(getString(message('Control:compDesignTask:strLoadErrorMsg1')),...
                        getString(message('Control:compDesignTask:strLoadError')),'modal')
                end
            end
            
            
            
            %
            %---- COMPLETE INIT IN BACKGROUND
            %
            
            waitbar(1,hWaitbar)
            close(hWaitbar)
            
            % Store database handle, set figure callbacks, and make figure visible
            set(SISOfig,'UserData',sisodb,...
                'CloseRequestFcn',{@LocalCloseCB sisodb},...
                'DeleteFcn',{@LocalDeleteTask sisodb},...
                'ResizeFcn',{@LocalResize sisodb},...
                'KeyPressFcn',{@LocalKeyevent sisodb},...
                'WindowButtonMotionFcn',{@LocalMouseevent sisodb})
            
            % Initialize status and history
            sisodb.EventManager.newstatus(ImportStatus);
            sisodb.EventManager.recordtxt('history',...
                getString(message('Control:compDesignTask:strStartSISOToolForSystemMsg',...
                date,sisodb.LoopData.Name)));
            
            % Call the start-up message box
            LocalStartUpMsgBox(sisodb);
            
            % Return figure handle if requested
            if nargout,
                varargout{1} = SISOfig;
            end
            
            % Set dirty listeners for the project
            sisotask.setDirtyListener
            
            % Unblock explorer
            projectframe.setBlocked(false, []);
            treemanager.setBusy(false);
            
        catch ME %#ok<NASGU>
            % Unblock explorer
            projectframe.setBlocked(false, []);
            treemanager.setBusy(false);
            if nargout,
                varargout{1} = [];
            end
        end
end

%-------------------------Internal Functions-------------------------


%%%%%%%%%%%%%%%%%%%%
%%% LocalOpenFig %%%
%%%%%%%%%%%%%%%%%%%%
function SISOfig = LocalOpenFig()

Color = get(0,'DefaultUIControlBackground');
SISOfig = figure(...
    'WindowStyle','normal',...
    'Color',Color,...
    'IntegerHandle','off', ...
    'DoubleBuffer','on', ...
    'MenuBar','none', ...
    'Name',getString(message('Control:compDesignTask:strSISODesignTool')), ...
    'NumberTitle','off', ...
    'Unit','character', ...
    'Visible','off', ...
    'Tag','SISODesignFig',...
    'DockControls','off');

% Colormap must be set after figure is created
% (for some reason this will open a new figure if handlevis=off)
pos = get(SISOfig,'Position') + [0 -7 0 7];
set(SISOfig,'Colormap',gray(size(get(SISOfig,'Colormap'),1)),'HandleVisibility','callback','Position',pos);

% Install CS help
ctrlcshelp(SISOfig);
mapfile = ctrlguihelp;
if ~isempty(mapfile)
    set(SISOfig,'HelpTopicMap',mapfile,'HelpFcn',@LocalHelpCB);
end


%%%%%%%%%%%%%%%%%%%%
%%% LocalResize %%%
%%%%%%%%%%%%%%%%%%%%
function LocalResize(~,~,sisodb)
resize(sisodb);

%%%%%%%%%%%%%%%%%%%%
%%% LocalMouseevent %%%
%%%%%%%%%%%%%%%%%%%%
function LocalMouseevent(~,~,sisodb)
% Only process mouse event if not in a scribemode.
ModeManager = uigetmodemanager(sisodb.Figure);
if isempty(ModeManager.CurrentMode)
    mouseevent(sisodb,'wbm');
end

%%%%%%%%%%%%%%%%%%%%
%%% LocalKeyevent %%%
%%%%%%%%%%%%%%%%%%%%
function LocalKeyevent(~,~,sisodb)
keyevent(sisodb);

%%%%%%%%%%%%%%%%%%%%
%%% LocalCloseCB %%%
%%%%%%%%%%%%%%%%%%%%
function LocalCloseCB(hSrc,~,sisodb) %#ok<INUSD>
set(hSrc,'Visible','off')


%%%%%%%%%%%%%%%%%%%%
%%% LocalDeleteTask %%%
%%%%%%%%%%%%%%%%%%%%
function LocalDeleteTask(~,~,sisodb)
% Remove delete Fcn callback on figure
SISOfig = sisodb.Figure;
set(SISOfig,'DeleteFcn','')

DesignTaskNode = sisodb.getNode;
delete(DesignTaskNode.Handles.sisodbDeleteListener);
% Delete the current node
parent = DesignTaskNode.up;

if ~isempty(parent)
    parent.removeNode(DesignTaskNode);
end


%%%%%%%%%%%%%%%%%%%%%
%%% LocalInitPref %%%
%%%%%%%%%%%%%%%%%%%%%
function Preferences = LocalInitPref(sisodb,SISOfig)
% Initializes preferences
Preferences = sisogui.sisoprefs(sisodb);

% Set default fonts
set(SISOfig,...
    'DefaultUIControlFontSize',Preferences.UIFontSize,...
    'DefaultAxesFontSize',Preferences.AxesFontSize,...
    'DefaultTextFontSize',Preferences.AxesFontSize)

%%%%%%%%%%%%%%%%%%%
%%% LocalHelpCB %%%
%%%%%%%%%%%%%%%%%%%
function LocalHelpCB(hFigure,varargin)
% Invoke help browser
Selection = get(hFigure,'CurrentObject');
HelpTopicKey = get(Selection,'HelpTopicKey');
if ~isempty(HelpTopicKey)
    helpview(get(hFigure,'HelpTopicMap'),HelpTopicKey,'CSHelpWindow');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% LocalStartUpMsgBox %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%
function LocalStartUpMsgBox(sisodb)
% Reads the cstprefs.mat file and shows start-up message box if required

h = sisodb.Preferences.ToolboxPreferences;
if strcmp(h.StartUpMsgBox.SISOtool,'on')
    Handles = startupdlg(sisodb.Figure, 'SISOtool', h);
    set(Handles.Figure, 'Name', getString(message('Control:compDesignTask:strGettingStartedSISOTool')));
    set(Handles.HelpBtn,'Callback','ctrlguihelp(''sisotoolmainhelp'');');
    set(Handles.TextMsg,'String', ...
        {getString(message('Control:compDesignTask:strGettingStartedSISOToolMsg1')), ...
        ' ', ...
        getString(message('Control:compDesignTask:strGettingStartedSISOToolMsg2'))});
end
