%SCHEMER_IMPORT Import a MATLAB color scheme
%   SCHEMER_IMPORT() with no input will prompt the user to locate the
%   color theme source file via the GUI.
%
%   SCHEMER_IMPORT(FILENAME) imports the color scheme options given in
%   the file FILENAME.
%
%   SCHEMER_IMPORT(FILENAME, INCLUDEBOOLS) can control whether boolean
%   preferences are included in import (default: FALSE). If INCLUDEBOOLS
%   is set to true, boolean preference options such as whether to
%   highlight autofixable errors, or to show variables with shared scope in
%   a different colour will also be overridden, should they be set in the
%   input file.
%
%   SCHEMER_IMPORT(INCLUDEBOOLS, FILENAME), with a boolean or numeric input
%   followed by a string input, will also work as above because the input
%   order is reversible.
%
%   SCHEMER_IMPORT(INCLUDEBOOLS) with a single boolean input will open the
%   GUI to pick the file, and will load boolean preferences in accordance
%   with INCLUDEBOOLS.
%
%   RET = SCHEMER_IMPORT(...) returns 1 on success, 0 on user
%   cancellation at input file selection screen, -1 on fopen error, and -2
%   on any other error.
%
%   NOTE:
%   The file to import can either be a color scheme file as generated by
%   SCHEMER_EXPORT, or an entire MATLAB preferences file such as the file
%   you will find located at FULLFILE(PREFDIR,'matlab.prf'). This could be
%   a MATLAB preferences file taken from a different computer or previous
%   MATLAB installation. However, if you are importing from a matlab.prf
%   file instead of a color scheme .prf file you should be aware that any
%   colour preferences which have been left as the defaults on preference
%   panels which the user has not visited on the origin system of the
%   matlab.prf file will not be present in the file, and hence not updated
%   on import.
%
%   The MATLAB preference options which will be overwritten by
%   SCHEMER_IMPORT are:
%   - All settings in the Color pane of Preferencs
%   - All colour settings in the Color > Programming Tools pane, but no
%     checkboxes
%   - From Editor/Debugger > Display pane, the following:
%      - Highlight current line (colour, but not whether to)
%      - Right-hand text limit (colour and thickness, but not on/off)
%   - From Editor/Debugger > Language, the syntax highlighting colours for
%     each language.
%
%   Once the current colour preferences are overridden they cannot be
%   undone, so it is recommended that you export your current preferences
%   with SCHEMER_EXPORT before importing a new theme if you think you
%   may wish to revert.
%
%   This is not necessary if you are using the default MATLAB color scheme
%   which ships with the installation, as SCHEMER comes with a copy of the
%   MATLAB default color scheme (default.prf).
%
%   If you wish to revert to the default MATLAB color scheme, it is
%   recommended you import the file default.prf included in this
%   package. This will reset Editor/Debugger>Display colours, colours for
%   syntax highlighting in additional languages, as well as the colours set
%   in the Colors pane. You can also revert the colors by clicking
%   "Restore Default Colors" in the MATLAB preference panel interface, but
%   this will be less effective because there are several panels which set
%   syntax colours and not all of them have a restore button.
%
%   For more details on how to get and set MATLAB preferences with
%   commands, see the following URL.
%   http://undocumentedmatlab.com/blog/changing-system-preferences-programmatically/
%
%   See also SCHEMER_EXPORT, PREFDIR.

% Copyright (c) 2013-2016,  Scott C. Lowe <scott.code.lowe@gmail.com>
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%     * Redistributions of source code must retain the above copyright
%       notice, this list of conditions and the following disclaimer.
%     * Redistributions in binary form must reproduce the above copyright
%       notice, this list of conditions and the following disclaimer in
%       the documentation and/or other materials provided with the distribution
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.

% Known issues:
%
% 1. Text colour of automatically highlighted variables does not change
%    colour immediately. This is an issue with matlab; if you change the main
%    text colour in the preferences pane, highlighted variables will still
%    have the old text colour until matlab is restarted.
%
% 2. Java exception is thrown when first trying to update the setting
%    Editor.VariableHighlighting.Color. This only happens the first
%    time SCHEMER_IMPORT is run, so the current fix is to catch the error
%    and then try again. However, it might be possible for other Java
%    exceptions get thrown under other mysterious circumstances, which could
%    cause the function to fail.

function varargout = schemer_import(fname, inc_bools)

% ------------------------ Parameters -------------------------------------
SCHEMER_VERSION = 'v1.4.0';

% ------------------------ Input handling ---------------------------------
% ------------------------ Default inputs ---------------------------------
if nargin<2
    inc_bools = false; % Default off, so only override extra options if intended
end
if nargin<1
    fname = []; % Ask user to select file
end
% Input switching
if nargin>=1 && ~ischar(fname) && ~isempty(fname)
    if ~islogical(fname) && ~isnumeric(fname)
        error('Invalid input argument 1');
    end
    if nargin==1
        % First input omitted
        inc_bools = fname;
        fname = [];
    elseif ischar(inc_bools)
        % Inputs switched
        tmp = fname;
        fname = inc_bools;
        inc_bools = tmp;
        clear tmp;
    else
        error('Invalid combination of inputs');
    end
end

% ------------------------ Check for file ---------------------------------
filefilt = ...
   {'*.prf'      , 'MATLAB preference files (*.prf)'   ; ...
    '*.prf;*.txt', 'Text and pref files (*.prf, *.txt)'; ...
    '*'          ,  'All Files'                        };

if ~isempty(fname)
    if ~exist(fname, 'file')
        error('Specified file does not exist');
    end
else
    % Dialog asking for input filename
    % Need to make this dialogue include .txt by default, at least
    [filename, pathname] = uigetfile(filefilt);
    % End if user cancels
    if isequal(filename, 0);
        if nargout>0; varargout{1} = 0; end;
        return;
    end
    fname = fullfile(pathname, filename);
end

% ------------------------ Catch block ------------------------------------
% Somewhat inexplicably, a Java exception is thrown the first time we try
% to set 'Editor.VariableHighlighting.Color'.
% But if we try again immediately, it can be set without any problems.
% The issue is very consistent.
% The solution is to try to set this colour along with all the others,
% catch the exception when it occurs, and then attempt to set all the
% preferences again.
try
    [varargout{1:nargout}] = main(fname, inc_bools);
catch ME
    if ~strcmp(ME.identifier, 'MATLAB:Java:GenericException');
        rethrow(ME);
    end
    % disp('Threw and ignored a Java exception. Retrying.');
    [varargout{1:nargout}] = main(fname, inc_bools);
end

end

% ======================== Main code ======================================
function varargout = main(fname, inc_bools)

% ------------------------ Parameters -------------------------------------
% Names of boolean preferences which should always be imported
names_boolean = {                                   ...
    'ColorsUseSystem'                               ... % Color:    Desktop:    Use system colors
};
% Names of boolean preferences which the user can choose whether to import
names_boolextra = {                                 ...
    'ColorsUseMLintAutoFixBackground'               ... % Color>PT: Analyser:   autofix highlight
    'Editor.VariableHighlighting.Automatic'         ... % Color>PT: Var&fn:     auto highlight
    'Editor.NonlocalVariableHighlighting'           ... % Color>PT: Var&fn:     with shared scope
    'EditorCodepadHighVisible'                      ... % Color>PT: CellDisp:   highlight cells
    'EditorCodeBlockDividers'                       ... % Color>PT: CellDisp:   show lines between cells
    'Editorhighlight-caret-row-boolean'             ... % Editor>Display:       Highlight current line
    'EditorRightTextLineVisible'                    ... % Editor>Display:       Show Right-hand text limit
};
% Names of preferences for which the values are integers
names_integer = {                                   ...
    'EditorRightTextLimitLineWidth'                 ... % Editor>Display:       Right-hand text limit Width
};
% Names of preferences for which the values are strings
%   column 1: name of preference
%   column 2: a regex which the string must match if it is to be exported
%             use '.' or '.+' to allow any non-empty string to be output
%             use  '' or '.*' for anything, including empty strings
%             use '\S' for anything except empty or whitespace-only strings
%             use '^str1|str2|str3$' to allow only a finite set of strings
names_string = {                                    ...
    'Editor.Language.Java.method'                       , ... % Java: Show methods
        '^(none|bold|italic)$'                             ; ...
};
% Names of colour preferences, and their default value if not present in
% the .prf file
%    column 1: name of preference
%    column 2: default value.
%               - Empty if no default,
%               - Integer if specific colour,
%               - String if inherited from another colour setting (which
%                   should appear higher up in the list)
%               - Cell array of strings to take the average colour from
%    column 3: whether a restart is required if this value changes
names_color = { ...
    'ColorsText'                                        , ... % Color:    Desktop:    main text colour
        ''                                              , ...
        false                                               ; ...
    'ColorsBackground'                                  , ... % Color:    Desktop:    main background
        ''                                              , ...
        true                                                ; ...
    'Colors_M_Errors'                                   , ... % Color:    Syntax:     errors
        -65536                                          , ...
        true                                                ; ...
    'Colors_M_Warnings'                                 , ... % Color>PT: Analyser:   warnings
        -27648                                          , ...
        true                                                ; ...
    'Colors_M_Keywords'                                 , ... % Color:    Syntax:     keywords
        'ColorsText'                                    , ...
        false                                               ; ...
    'Colors_M_Comments'                                 , ... % Color:    Syntax:     comments
        {'ColorsText','ColorsBackground'}               , ...
        false                                               ; ...
    'Colors_M_Strings'                                  , ... % Color:    Syntax:     strings
        'ColorsText'                                    , ...
        false                                               ; ...
    'Colors_M_UnterminatedStrings'                      , ... % Color:    Syntax:     unterminated strings
        'Colors_M_Errors'                               , ...
        false                                               ; ...
    'Colors_M_SystemCommands'                           , ... % Color:    Syntax:     system commands
        'Colors_M_Keywords'                             , ...
        false                                               ; ...
    'Colors_HTML_HTMLLinks'                             , ... % Color:    Other:      hyperlinks
        'ColorsText'                                    , ...
        false                                               ; ...
    'Color_CmdWinWarnings'                              , ... % Color:    Other:      Warning messages
        'Colors_M_Warnings'                             , ...
        false                                               ; ...
    'Color_CmdWinErrors'                                , ... % Color:    Other:      Error messages
        'Colors_M_Errors'                               , ...
        false                                               ; ...
    'ColorsMLintAutoFixBackground'                      , ... % Color>PT: Analyser:   autofix
        'ColorsBackground'                              , ...
        false                                               ; ...
    'Editor.VariableHighlighting.Color'                 , ... % Color>PT: Var&fn:     highlight
        'ColorsBackground'                              , ...
        true                                                ; ...
    'Editor.NonlocalVariableHighlighting.TextColor'     , ... % Color>PT: Var&fn:     with shared scope
        'ColorsText'                                    , ...
        false                                               ; ...
    'Editorhighlight-lines'                             , ... % Color>PT: CellDisp:   highlight
        'ColorsBackground'                              , ...
        false                                               ; ...
    'Editorhighlight-caret-row-boolean-color'           , ... % Editor>Display:       Highlight current line Color
        'Editorhighlight-lines'                         , ...
        false                                               ; ...
    'EditorRightTextLimitLineColor'                     , ... % Editor>Display:       Right-hand text limit line Color
        -5723992                                        , ...
        false                                               ; ...

    'Editor.Language.MuPAD.Color.keyword'               , ... % MuPAD: Keywords
        'Colors_M_Keywords'                             , ...
        false                                               ; ...
    'Editor.Language.MuPAD.Color.operator'              , ... % MuPAD: Operators
        'Colors_M_SystemCommands'                       , ...
        false                                               ; ...
    'Editor.Language.MuPAD.Color.block-comment'         , ... % MuPAD: Comments
        'Colors_M_Comments'                             , ...
        false                                               ; ...
    'Editor.Language.MuPAD.Color.option'                , ... % MuPAD: Options
        'Colors_M_UnterminatedStrings'                  , ...
        false                                               ; ...
    'Editor.Language.MuPAD.Color.string'                , ... % MuPAD: Strings
        'Colors_M_Strings'                              , ...
        false                                               ; ...
    'Editor.Language.MuPAD.Color.function'              , ... % MuPAD: System Functions
        {'Colors_M_Keywords','ColorsBackground'}        , ...
        false                                               ; ...
    'Editor.Language.MuPAD.Color.constant'              , ... % MuPAD: Constants
        'Editor.NonlocalVariableHighlighting.TextColor' , ...
        false                                               ; ...

    'Editor.Language.TLC.Color.Colors_M_SystemCommands' , ... % TLC: Commands
        'Colors_M_Keywords'                             , ...
        false                                               ; ...
    'Editor.Language.TLC.Color.Colors_M_Keywords'       , ... % TLC: Macros
        'Colors_M_SystemCommands'                       , ...
        false                                               ; ...
    'Editor.Language.TLC.Color.Colors_M_Comments'       , ... % TLC: Comments
        'Colors_M_Comments'                             , ...
        false                                               ; ...
    'Editor.Language.TLC.Color.string-literal'          , ... % TLC: C Strings
        'Colors_M_Strings'                              , ...
        false                                               ; ...

    'Editor.Language.C.Color.keywords'                  , ... % C/C++: Keywords
        'Colors_M_Keywords'                             , ...
        false                                               ; ...
    'Editor.Language.C.Color.line-comment'              , ... % C/C++: Comments
        'Colors_M_Comments'                             , ...
        false                                               ; ...
    'Editor.Language.C.Color.string-literal'            , ... % C/C++: Strings
        'Colors_M_Strings'                              , ...
        false                                               ; ...
    'Editor.Language.C.Color.preprocessor'              , ... % C/C++: Preprocessor
        'Colors_M_SystemCommands'                       , ...
        false                                               ; ...
    'Editor.Language.C.Color.char-literal'              , ... % C/C++: Characters
        'Colors_M_UnterminatedStrings'                  , ...
        false                                               ; ...
    'Editor.Language.C.Color.errors'                    , ... % C/C++: Bad characters
        'Colors_M_Errors'                               , ...
        false                                               ; ...

    'Editor.Language.Java.Color.keywords'               , ... % Java: Keywords
        'Colors_M_Keywords'                             , ...
        false                                               ; ...
    'Editor.Language.Java.Color.line-comment'           , ... % Java: Comments
        'Colors_M_Comments'                             , ...
        false                                               ; ...
    'Editor.Language.Java.Color.string-literal'         , ... % Java: Strings
        'Colors_M_Strings'                              , ...
        false                                               ; ...
    'Editor.Language.Java.Color.char-literal'           , ... % Java: Characters
        'Colors_M_UnterminatedStrings'                  , ...
        false                                               ; ...

    'Editor.Language.VHDL.Color.Colors_M_Keywords'      , ... % VHDL: Keywords
        'Colors_M_Keywords'                             , ...
        false                                               ; ...
    'Editor.Language.VHDL.Color.operator'               , ... % VHDL: Operators
        'Colors_M_SystemCommands'                       , ...
        false                                               ; ...
    'Editor.Language.VHDL.Color.Colors_M_Comments'      , ... % VHDL: Comments
        'Colors_M_Comments'                             , ...
        false                                               ; ...
    'Editor.Language.VHDL.Color.string-literal'         , ... % VHDL: Strings
        'Colors_M_Strings'                              , ...
        false                                               ; ...

    'Editor.Language.Verilog.Color.Colors_M_Keywords'   , ... % Verilog: Keywords
        'Colors_M_Keywords'                             , ...
        false                                               ; ...
    'Editor.Language.Verilog.Color.operator'            , ... % Verilog: Operators
        'Colors_M_SystemCommands'                       , ...
        false                                               ; ...
    'Editor.Language.Verilog.Color.Colors_M_Comments'   , ... % Verilog: Comments
        'Colors_M_Comments'                             , ...
        false                                               ; ...
    'Editor.Language.Verilog.Color.string-literal'      , ... % Verilog: Strings
        'Colors_M_Strings'                              , ...
        false                                               ; ...

    'Editor.Language.XML.Color.error'                   , ... % XML: Error
        'Colors_M_Errors'                               , ...
        false                                               ; ...
    'Editor.Language.XML.Color.tag'                     , ... % XML: Tag
        'Colors_M_Keywords'                             , ...
        false                                               ; ...
    'Editor.Language.XML.Color.attribute'               , ... % XML: Attribute name
        'Colors_M_UnterminatedStrings'                  , ...
        false                                               ; ...
    'Editor.Language.XML.Color.operator'                , ... % XML: Operator
        'Colors_M_SystemCommands'                       , ...
        false                                               ; ...
    'Editor.Language.XML.Color.value'                   , ... % XML: Attribute value
        'Colors_M_Strings'                              , ...
        false                                               ; ...
    'Editor.Language.XML.Color.comment'                 , ... % XML: Comment
        'Colors_M_Comments'                             , ...
        false                                               ; ...
    'Editor.Language.XML.Color.doctype'                 , ... % XML: DOCTYPE declaration
        'Colors_HTML_HTMLLinks'                         , ...
        false                                               ; ...
    'Editor.Language.XML.Color.ref'                     , ... % XML: Character
        'Colors_M_UnterminatedStrings'                  , ...
        false                                               ; ...
    'Editor.Language.XML.Color.pi-content'              , ... % XML: Processing instruction
        'Colors_HTML_HTMLLinks'                         , ...
        false                                               ; ...
    'Editor.Language.XML.Color.cdata-section'           , ... % XML: CDATA section
        'Editor.NonlocalVariableHighlighting.TextColor' , ...
        false                                               ; ...

    'Editor.Language.VRML.Color.keyword'                , ... % VRML: Keywords
        'Editor.Language.XML.Color.doctype'             , ...
        false                                               ; ...
    'Editor.Language.VRML.Color.node-keyword'           , ... % VRML: Node types
        'Editor.Language.XML.Color.tag'                 , ...
        false                                               ; ...
    'Editor.Language.VRML.Color.field-keyword'          , ... % VRML: Fields
        'Editor.Language.XML.Color.attribute'           , ...
        false                                               ; ...
    'Editor.Language.VRML.Color.data-type-keyword'      , ... % VRML: Data types
        'Editor.Language.XML.Color.cdata-section'       , ...
        false                                               ; ...
    'Editor.Language.VRML.Color.terminal-symbol'        , ... % VRML: Terminal symbols
        'Editor.Language.XML.Color.operator'            , ...
        false                                               ; ...
    'Editor.Language.VRML.Color.comment'                , ... % VRML: Comments
        'Editor.Language.XML.Color.comment'             , ...
        false                                               ; ...
    'Editor.Language.VRML.Color.string'                 , ... % VRML: Strings
        'Editor.Language.XML.Color.value'               , ...
        false                                               ; ...

    'Editor.Language.VRMLX3DV.Color.keyword'            , ... % VRML/X3DV: Keywords
        'Editor.Language.VRML.Color.keyword'            , ...
        false                                               ; ...
    'Editor.Language.VRMLX3DV.Color.node-keyword'       , ... % VRML/X3DV: Node types
        'Editor.Language.VRML.Color.node-keyword'       , ...
        false                                               ; ...
    'Editor.Language.VRMLX3DV.Color.field-keyword'      , ... % VRML/X3DV: Fields
        'Editor.Language.VRML.Color.field-keyword'      , ...
        false                                               ; ...
    'Editor.Language.VRMLX3DV.Color.data-type-keyword'  , ... % VRML/X3DV: Data types
        'Editor.Language.VRML.Color.data-type-keyword'  , ...
        false                                               ; ...
    'Editor.Language.VRMLX3DV.Color.terminal-symbol'    , ... % VRML/X3DV: Terminal symbols
        'Editor.Language.VRML.Color.terminal-symbol'    , ...
        false                                               ; ...
    'Editor.Language.VRMLX3DV.Color.comment'            , ... % VRML/X3DV: Comments
        'Editor.Language.VRML.Color.comment'            , ...
        false                                               ; ...
    'Editor.Language.VRMLX3DV.Color.string'             , ... % VRML/X3DV: Strings
        'Editor.Language.VRML.Color.string'             , ...
        false                                               ; ...
};

verbose = 0;

% ------------------------ Setup ------------------------------------------
if nargout==0
    varargout = {};
else
    varargout = {-2};
end
if inc_bools
    names_boolean = [names_boolean names_boolextra];
end
needs_restart = false;

% ------------------------ Check file seems okay --------------------------
% Read in the contents of the entire file
flestr = fileread(fname);
% Search for occurances of main text colour
txtprf = regexp(flestr, '\sColorsText=(?<pref>[^#\s]+)\s', 'names');
if isempty(txtprf)
    error('Text colour not present in colorscheme file:\n%s', fname);
elseif length(txtprf) > 1
    error('Text colour defined multiple times in colorscheme file:\n%s', fname);
end
% Search for occurances of main background colour
bkgprf = regexp(flestr, '\sColorsBackground=(?<pref>[^#\s]+)\s', 'names');
if isempty(bkgprf)
    error('Background colour not present in colorscheme file:\n%s', fname);
elseif length(bkgprf) > 1
    error('Background colour defined multiple times in colorscheme file:\n%s', fname);
end
% Make sure the main text and background colours are not exactly the same
if strcmp(txtprf.pref, bkgprf.pref)
    error('Main text and background colours are the same in this file:\n%s', fname);
end

% ------------------------ File stuff -------------------------------------
% Open for read access only
fid = fopen(fname, 'r', 'n');
if isequal(fid, -1);
    if nargout>0; varargout{1} = -1; end;
    return;
end
% Add a cleanup object incase of failure
finishup = onCleanup(@() fclose(fid));

% ------------------------ Read and Write ---------------------------------
% Initialise tracker for unset colours
isColorSet = false(size(names_color, 1), 1);
% Loop over prf file
while ~feof(fid)
    % Get one line of preferences/theme file
    l = fgetl(fid);

    % Ignore empty lines and lines which begin with #
    if length(l)<1 || strcmp('#', l(1))
        if verbose; disp('Comment'); end;
        continue;
    end

    % Look for name pref pair, seperated by '='
    %    Must be at begining of string (hence ^ anchor)
    %    Cannot contain comment marker (#)
    n = regexp(l, '^(?<name>[^=#]+)=(?<pref>[^#]+)', 'names');

    % If no match, continue and scan next line
    if isempty(n)
        if verbose; disp('No match'); end;
        continue;
    end

    % Trim whitespace from pref
    n.pref = strtrim(n.pref);

    if ismember(n.name, names_boolean)
        % Deal with boolean type
        switch lower(n.pref)
            case 'btrue'
                % Preference is true
                com.mathworks.services.Prefs.setBooleanPref(n.name, 1);
                if verbose; fprintf('Set bool true %s\n', n.name); end
            case 'bfalse'
                % Preference is false
                com.mathworks.services.Prefs.setBooleanPref(n.name, 0);
                if verbose; fprintf('Set bool false %s\n', n.name); end
            otherwise
                % Shouldn't be anything else
                warning('Bad boolean for %s: %s', n.name, n.pref);
        end

    elseif ismember(n.name, names_integer)
        % Deal with integer type
        if ~strcmpi('I', n.pref(1))
            warning('Bad integer pref for %s: %s', n.name, n.pref);
            continue;
        end
        int = str2double(n.pref(2:end));
        com.mathworks.services.Prefs.setIntegerPref(n.name, int);
        if verbose; fprintf('Set integer %d for %s\n', int, n.name); end

    elseif ismember(n.name,names_string(:, 1))
        % Deal with string type
        if ~strcmpi('S', n.pref(1))
            warning('Bad string pref for %s: %s', n.name, n.pref);
            continue;
        end
        str = n.pref(2:end);
        % Look up which of the preference settings this is
        [~, idx] = ismember(n.name, names_string(:, 1));
        % Check that the setting allowed by the regex it must satisfy
        if isempty(regexp(str, names_string{idx, 2}, ...
                    'start', 'emptymatch'))
            % If not, we can't set the value to be this
            warning('Invalid string for %s: %s', n.name, str);
            continue;
        end
        com.mathworks.services.Prefs.setStringPref(n.name, str);
        if verbose; fprintf('Set string %s for %s\n', str, n.name); end

    elseif ismember(n.name, names_color(:, 1))
        % Deal with colour type (final type to consider)
        if ~strcmpi('C', n.pref(1))
            warning('Bad color for %s: %s', n.name, n.pref);
            continue;
        end
        [~, idx] = ismember(n.name, names_color(:, 1));
        % Get the current setting for this parameter
        previousVal = ...
            com.mathworks.services.Prefs.getColorPref(names_color{idx, 1});
        % Set the colour to the target value
        rgb = str2double(n.pref(2:end));
        jc = java.awt.Color(rgb);
        com.mathworks.services.Prefs.setColorPref(n.name, jc);
        com.mathworks.services.ColorPrefs.notifyColorListeners(n.name);
        if verbose
            fprintf('Set color (%3.f, %3.f, %3.f) for %s\n', ...
                jc.getRed, jc.getGreen, jc.getBlue, n.name);
        end
        % Note that we have allocated this colour
        isColorSet(idx) = true;
        % Check if the colour has changed
        if names_color{idx, 3} && ~isequal(previousVal, jc)
            needs_restart = true;
        end

    else
        % Silently ignore irrelevant preferences
        % (This means you can load a whole matlab.prf file and anything not
        % listed above as relevant to the color scheme will be ignored.)

    end

end

% Check that at least one colour was actually set
if ~any(isColorSet)
    error('Did not find any colour settings in file\n%s', fname);
    if nargout>0; varargout{1} = -2; end;
    return;
end

% For colours which have not been set by the color scheme, we set them from
% a backup
% Get a row vector of indices of all unset colours
unsetColorIndices = find(~isColorSet)';
% Loop over unset colours
for idx=unsetColorIndices
    % Get the backup setting for this colour parameter
    backupVal = names_color{idx, 2};
    % Get the current setting for this parameter
    previousVal = ...
        com.mathworks.services.Prefs.getColorPref(names_color{idx, 1});

    clear jc; % Clear variable

    % Switch based on the type of backup
    if isempty(backupVal)
        % No backup is set
        continue;

    elseif iscell(backupVal)
        % Backup is one of several methods of which involve refactoring one
        % or more other colours
        % Get an RGB value for the colour through whichever method
        if all(cellfun(@ischar, backupVal))
            % Backup is a list of other names to sample and average
            % Initialise a holding matrix
            RGB = nan(numel(backupVal), 3);
            for i=1:numel(backupVal)
                % Load each of the other colours
                jc = com.mathworks.services.Prefs.getColorPref(backupVal{i});
                % Put the R, G, B values into the holding matrix
                RGB(i, 1) = jc.getRed;
                RGB(i, 2) = jc.getGreen;
                RGB(i, 3) = jc.getBlue;
            end
            % Take the average of each RGB value from the other colours
            RGB = mean(RGB);

        elseif length(backupVal)==2
            % Backup is a name of a colour and a scale factor to apply
            jc = com.mathworks.services.Prefs.getColorPref(backupVal{1});
            % Get the R, G, B values
            RGB = [jc.getRed, jc.getGreen, jc.getBlue];
            % Rescale them
            RGB = RGB * backupVal{2};

        else
            error('Bad backup cell for %s', names_color{idx, 1});

        end
        % Turn the RGB value into a Java color object
        % Ensure RGB is integer and does not exceed 255
        RGB = min(255, round(RGB));
        % Convert to a float
        RGB = RGB/255;
        % Make a Java color object for this colour
        jc = java.awt.Color(RGB(1), RGB(2), RGB(3));

    elseif ischar(backupVal)
        % The backup colour is a reference to another colour
        % Look up the colour from the backup reference
        jc = com.mathworks.services.Prefs.getColorPref(backupVal);

    elseif isnumeric(backupVal) && numel(backupVal)==1
        % The backup colour is a specific colour
        % Make a java color object for this specific colour
        jc = java.awt.Color(backupVal);

    else
        error('Bad backup value for %s', names_color{idx, 1});

    end
    % Assign the neglected colour to be this Java colour object from the
    % backup
    com.mathworks.services.Prefs.setColorPref(names_color{idx, 1}, jc);
    com.mathworks.services.ColorPrefs.notifyColorListeners(names_color{idx, 1});

    % Check if the colour has changed
    if names_color{idx, 3} && ~isequal(previousVal, jc)
        needs_restart = true;
    end

end

% ------------------------ Tidy up ----------------------------------------
% fclose(fid); % Don't need to close as it will autoclose
if nargout>0; varargout{1} = 1; end;

if inc_bools
    fprintf('Imported color scheme WITH boolean options from\n%s\n', fname);
else
    fprintf('Imported color scheme WITHOUT boolean options from\n%s\n', fname);
end
if needs_restart
    disp('Some changes require MATLAB to be restarted to be activated.');
end

end


function [ns_RESULT, nsLibraryInfo] = ns_GetLibraryInfo();

%ns_GetLibraryInfo   Get library version information
%
%   Usage:
%       [ns_RESULT, nsLibraryInfo] = ns_GetLibraryInfo()
%
%   Description:
%       Obtains information about the API library.
%
%   Return Values:
%       nsLibraryInfo   Structure to receive library version information.
%       ns_RESULT   This function returns ns_OK if the file is successfully
%                   opened. Otherwise one of the following error codes is
%                   generated:
%
%                       ns_LIBERROR	Library Error
%
%   Copyright (C) 2003 Neuroshare Project
%   Author: Almut Branner
%   Last modification: 8/11/2003

[ns_RESULT, nsLibraryInfo] = mexprog(2);


function figureca(command,~)
    % This function is a callback for makemenus.
    % It should not be called from the command line.
    % figureca (previously internally known as FigureCallback)
    %
    % Keith Rogers 11/30/93

    report_this_filefun(mfilename('fullpath'));

    if (command == 1)
        if(strcmp(get(gcm2,'Label'),'Landscape'))
            set(gcf,'PaperOrientation','landscape');
            set(gcm2,'Label','Portrait');
        else
            set(gcf,'PaperOrientation','portrait');
            set(gcm2,'Label','Landscape');
        end
    end


% This file is only useful if you're using BCILAB to rebuild the .c files in here.
Libraries = 'dl';


function ED = edl_readexpdefs(filename)
%EDL_READEXPDEFS Reads in an experiment definition from XML file
%
% $ Syntax $
%   - ED = edl_readexpdefs(filename)
%
% $ Arguments $
%   - filename:     the filename of the experiment definition XML
%   - ED:           the read experiment definition struct
%
% $ Description $
%   - ED = edl_readexpdefs(filename) reads in an experiment definition
%     struct from an XML file. The format of XML can be referred to
%     the edl.spec.txt. The struct ED has following fields:
%
%       - name: the experiment definition name
%       - selfpath: the absolute path of the experiment definition self
%       - envconf: the filename of environment configuration
%       - env:     the environment configuration struct
%       - scriptdir: the script directory
%       - reportdir: the report directory
%       - mfiledir:  the m-files directory
%       - logfile:   the path of log file
%       - logger:    the logger
%
%       - variables: a struct of all variables,
%           using variable names as field names
%           using variable values as field values
%       - scripts: the struct of scripts
%           - using name as fieldnames, each field is a struct with
%               - func:     the scripting function
%               - path:     the path of the script file
%               - ctrlpath: the path of the control file
%               - params:   the other parameters
%               - refs:     the struct array of referenced scripts
%                   using role as field name
%                   using script name as field value
%               - refreps:  the struct array of referenced reports
%                   using role as field name
%                   using report name as field value
%               - refpaths: the struct array of referenced paths
%                   using role as field name
%                   using xml path of (script or report) as field value
%               - refscopes: the struct array of scope names of references
%                            (scripts | reports)
%                   using role as field name
%                   using scope names as field values
%       - experiments: the struct of experiments
%           - using name as fieldnames, each field is a struct with
%               - func:         the experiment function
%               - script:       the script name
%               - scriptpath:   the script filepath
%               - ctrlpath:     the control filepath
%       - reports: the struct array of reports
%           similar to scripts, except for that there is no ctrlpath
%
% $ History $
%   - Created by Dahua Lin, on Aug 12nd, 2006
%

%% Read file

xdoc = xmlread(filename);
edparent = slfilepart(filename, 'parent');
docelem = xdoc.getDocumentElement;

%% Read Header

headerfns = { ...
    'name', ...
    'envconf', ...
    'scriptdir', ...
    'reportdir', ...
    'mfiledir', ...
    'logfile'};
ED = cell2struct(cell(1, length(headerfns)), headerfns, 2);
headers = xml_getattribs(docelem);
ED = slparseprops(ED, headers);

if slisabspath(filename)
    ED.selfpath = filename;
else
    ED.selfpath = sladdpath(filename, cd());
end

if isempty(ED.envconf)
    ED.env = [];
else
    envpath = sladdpath(ED.envconf, edparent);
    ED.env = edl_readenvvars(envpath);
end

if isempty(ED.env) || ~isfield(ED.env, 'envname')
    error('edl:parseerror', ...
        'The environment must has variable named %s', 'envname');
end
envname = ED.env.envname;

ED.logger = sllog('rootpath', edparent);
if ~isempty(ED.logfile)
    ED.logfile = [ED.logfile, '.', envname, '.log'];
    ED.logger = addfiles(ED.logger, ED.logfile);
end

%% First-Pass Parsing
% 1. Build variable table progressively
% 2. Build basic structures
% 3. Translate variables

ED.variables = [];
ED.scripts = [];
ED.experiments = [];
ED.reports = [];

ED = first_pass(ED, docelem, struct('workdir', ''));

%% Second-Pass Parsing
% 1. Extract paths from cross-references
%   (a) build refpaths for scripts and reports
%   (b) build scriptpath and ctrlpath for experiments
%

% 1.(a)
ED.scripts = build_refpaths(ED, ED.scripts);
ED.reports = build_refpaths(ED, ED.reports);

% 1.(b)
ED.experiments = build_exppaths(ED, ED.experiments);

%% Core function for First-Pass (recursive invoking)

function ED = first_pass(ED, xelem, groupvars)

nodeList = xelem.getChildNodes;
n = nodeList.getLength;

for i = 1 : n   % enumerate all children

    node = nodeList.item(i-1);
    if (node.getNodeType == node.ELEMENT_NODE)
        tag = char(node.getTagName);

        switch tag

            case 'Var'
                [varname, varval] = parse_var(ED, node);
                ED.variables.(varname) = varval;

            case 'Script'
                [scriptname, scriptstruct] = parse_script(ED, node);
                scriptstruct.params = weak_update(scriptstruct.params, groupvars);
                ED.scripts.(scriptname) = scriptstruct;

            case 'Report'
                [reportname, reportstruct] = parse_report(ED, node);
                ED.reports.(reportname) = reportstruct;

            case 'Experiment'
                [expname, expstruct] = parse_experiment(ED, node);
                ED.experiments.(expname) = expstruct;

            case 'Group'
                subgroupvars = parse_group(ED, groupvars, node);
                ED = first_pass(ED, node, subgroupvars);

            otherwise
                error('edl:parseerror', ...
                    'Invalid element with tag name %s', tag);
        end

    end

end

%% Core functions for Second-Pass

function S = build_refpaths(ED, S)

fns = fieldnames(S);
n = length(fns);

for i = 1 : n
    fn = fns{i};

    S.(fn) = build_refpaths_fortype(ED, fn, S.(fn), 'scripts', 'refs');
    S.(fn) = build_refpaths_fortype(ED, fn, S.(fn), 'reports', 'refreps');

end

function S = build_refpaths_fortype(ED, name, S, typeset, typefield)

if ~isfield(S, 'refpaths')
    S.refpaths = [];
end
if ~isfield(S, 'refscopes')
    S.refscopes = [];
end

curset = S.(typefield);
if isempty(curset)
    return;
end

fns = fieldnames(curset);
n = length(fns);
pool = ED.(typeset);

for i = 1 : n
    role = fns{i};
    refname = curset.(role);
    if ~isfield(pool, refname)
        error('edl:parseerror', ...
            'The reference with role %s (name = %s) in %s is not found in pool %s', ...
            role, refname, name, typeset);
    end

    S.refpaths.(role) = pool.(refname).path;
    S.refscopes.(role) = typeset;
end

function ES = build_exppaths(ED, ES)

if isempty(ES)
    return;
end

fns = fieldnames(ES);
n = length(fns);

for i = 1 : n
    fn = fns{i};
    scriptname = ES.(fn).script;
    if ~isfield(ED.scripts, scriptname)
        error('edl:parseerror', ...
            'The referred script named %s for %s is not found', ...
            scriptname, fn);
    end

    curscript = ED.scripts.(scriptname);

    ES.(fn).scriptpath = curscript.path;
    ES.(fn).ctrlpath = curscript.ctrlpath;
end

%% Node Parsing functions

% variable parsing

function [vname, vval] = parse_var(ED, xelem)

vname = make_name(ED, 'variables', xelem);
vval = get_tattrib(ED, xelem, 'variables', vname, 'val');

% script parsing

function [sname, scr] = parse_script(ED, xelem)

sname = make_name(ED, 'scripts', xelem);

scr.func = get_tattrib(ED, xelem, 'scripts', sname, 'func');
scr.func = sladdpath(scr.func, ED.mfiledir);

scr.path = '';
scr.ctrlpath = '';
scr = update_fields(ED, scr, xelem, {'path', 'ctrlpath'});
scr.params = get_tattribs(ED, xelem, ...
    'exclude', {'name', 'func', 'path', 'ctrlpath'});

if isempty(scr.path)
    scr.path = [sname, '.script.xml'];
end
if isempty(scr.ctrlpath)
    scrfiletitle = slfilepart(scr.path, 'title');
    scr.ctrlpath = slchangefilepart(scr.path, 'title', [scrfiletitle, '.control']);
end

scr.path = sladdpath(scr.path, ED.scriptdir);

scr = build_reftables(ED, scr, xelem);

% report parsing

function [rname, rep] = parse_report(ED, xelem)

rname = make_name(ED, 'reports', xelem);

rep.func = get_tattrib(ED, xelem, 'reports', rname, 'func');
rep.func = sladdpath(rep.func, ED.mfiledir);

rep.path = '';
rep = update_fields(ED, rep, xelem, {'path'});
rep.params = get_tattribs(ED, xelem, ...
    'exclude', {'name', 'func', 'path', 'ctrlpath'});

if isempty(rep.path)
    rep.path = [rname, '.report.xml'];
end
rep.path = sladdpath(rep.path, ED.reportdir);

rep = build_reftables(ED, rep, xelem);

% experiment parsing

function [expname, es] = parse_experiment(ED, xelem)

expname = make_name(ED, 'experiments', xelem);

es.func = get_tattrib(ED, xelem, 'experiments', expname, 'func');
es.func = sladdpath(es.func, ED.mfiledir);

es.script = '';
es = update_fields(ED, es, xelem, {'script'});

if isempty(es.script)
    es.script = expname;
end

% group parsing

function newvars = parse_group(ED, gvars, xelem)

newvars = get_tattribs(ED, xelem, 'exclude', {'title'});

if ~isfield(newvars, 'workdir') || isempty(newvars.workdir)
    newvars.workdir = gvars.workdir;
else
    newvars.workdir = sladdpath(newvars.workdir, gvars.workdir);
end

newvars = weak_update(newvars, gvars);

%% Auxiliary functions

function val = translate_attribval(ED, attrval)

val = attrval;
if length(val) > 1 && val(1) == '$'
    varname = val(2:end);
    if ~isfield(ED.variables, varname)
        error('edl:parseerror', ...
            'The variable %s is not found', varname);
    end
    val = ED.variables.(varname);
end

function aval = get_tattrib(ED, xelem, scope, elemname, attrname)

if xelem.hasAttribute(attrname)
    aval = char(xelem.getAttribute(attrname));
    aval = translate_attribval(ED, aval);
else
    error('edl:parseerror', ...
        'The attribute %s is not found in %s of %s', attrname, elemname, scope);
end

function A = get_tattribs(ED, xelem, varargin)

A = xml_getattribs(xelem, varargin{:});

if ~isempty(A)
    fns = fieldnames(A);
    n = length(fns);
    for i = 1 : n
        fn = fns{i};
        A.(fn) = translate_attribval(ED, A.(fn));
    end
end

function name = make_name(ED, scope, xelem)

if xelem.hasAttribute('name')
    name = char(xelem.getAttribute('name'));
    if isfield(ED.(scope), name)
        error('edl:parseerror', ...
            'Redefinition of %s in %s', name, scope);
    end
else
    error('edl:parseerror', ...
        'Encounter an element without name in %s', scope);
end

function S = update_fields(ED, S, xelem, fns)

S = slparseprops(S, get_tattribs(ED, xelem, ...
    'select', fns, ...
    'forceexist', false));

function S = weak_update(S, Scomp)

fns = fieldnames(Scomp);
n = length(fns);
for i = 1 : n
    fn = fns{i};
    if ~isfield(S, fn)
        S.(fn) = Scomp.(fn);
    end
end

function S = build_reftables(ED, S, xelem)

refNodes = xelem.getElementsByTagName('Ref');
nrs = refNodes.getLength;

S.refs = [];
S.refreps = [];

for i = 1 : nrs
    curnode = refNodes.item(i-1);
    cur = get_tattribs(ED, curnode, 'select', {'role', 'name'});
    S.refs.(cur.role) = cur.name;
end

refrepNodes = xelem.getElementsByTagName('RefReport');
nrr = refrepNodes.getLength;

for i = 1 : nrr
    curnode = refrepNodes.item(i-1);
    cur = get_tattribs(ED, curnode, 'select', {'role', 'name'});
    S.refreps.(cur.role) = cur.name;
end


function jframe = getjframe(hFig)
% getjframe Retrieves the underlying Java frame for a figure
%
% Syntax:
%    jframe = getjframe(hFigureOrComponent)
%
% Description:
%    GETJFRAME retrieves the current figure (gcf)'s underlying Java frame,
%    thus enabling access to all 35 figure callbacks that are not exposed
%    by Matlab's figure.
%
%    Notable callbacks include: FocusGainedCallback, FocusLostCallback,
%    KeyPressedCallback, KeyReleasedCallback, MouseEnteredCallback,
%    MouseExitedCallback, MousePressedCallback, MouseReleasedCallback,
%    WindowActivatedCallback, WindowClosedCallback, WindowClosingCallback,
%    WindowOpenedCallback, WindowStateChangedCallback and 22 others.
%
%    The returned jframe object also allows access to other useful window
%    features: 'AlwaysOnTop', 'CloseOnEscapeEnabled', 'Resizable',
%    'Enabled', 'HWnd' (for those interested in Windows integration) etc.
%    Type "get(jframe)" to see the full list of properties.
%
%    GETJFRAME(hFig) retrieves a specific figure's underlying Java frame.
%    hFig is a Matlab handle, or a list of graphic handles (not necessarily
%    figure handle(s) - the handles' containing figure is used).
%
% Examples:
%    get(getjframe,'ListOfCallbacks');  %display list of supported callbacks
%    set(getjframe,'WindowStateChangedCallback','disp(''Window min/maxed'')')
%    set(getjframe,'WindowDeiconifiedCallback',@winMaximizedCallback)
%    set(getjframe,'WindowIconifiedCallback',{@winMinimizedCallback,mydata})
%    set(getjframe,'CloseOnEscapeEnabled','on')
%    jframes = getjframe([gcf,hButton]);  % get 2 java frames, from 2 figures
%
% Bugs and suggestions:
%    Please send to Yair Altman (altmany at gmail dot com)
%
% Change log:
%    2007-08-05: First version posted on MathWorks File Exchange
%    2007-08-11: Added Matlab figure handle property; improved responsiveness handling; added support for array of handles; added sanity checks for illegal handles
%    2011-10-14: Fix for R2011b
%    2014-09-02: Fix for R2014b (HG2)
%    2018-06-28: Additional fixes for R2014b onward (HG2)
%    2019-03-01: Extra check for additional robustness
%
% See also:
%    gcf, findjobj (on the File Exchange)

% Programmed by Yair M. Altman: altmany(at)gmail.com
% $Revision: 1.2 $  $Date: 2020/02/07 07:00:37 $

  try
      % Default figure = current (gcf)
      if nargin < 1 || ~all(ishghandle(hFig))
          if nargin && ~all(ishghandle(hFig))
              error('hFig must be a valid GUI handle or array of handles');
          end
          hFig = gcf;
      end

      % Require Java engine to run
      if ~usejava('jvm')
          error([mfilename ' requires Java to run.']);
      end

      % Initialize output var (needed in case hFig is empty)
      jframe = handle([]);

      % Loop over all requested figures
      for figIdx = 1 : length(hFig)

          % Get the root Java frame
          jff = getJFrame(hFig(figIdx));

          % Add the 'ListOfCallbacks' read-only property to jframe
          fields = fieldnames(get(jff));
          cb1Idx = find(~cellfun('isempty',strfind(fields,'Callback'))); %#ok<*STRCL1>
          cb2Idx = find(~cellfun('isempty',strfind(fields,'CallbackData')));
          cbIdx = setdiff(cb1Idx, cb2Idx)';
          cbNames = fields(cbIdx);
          jframe(figIdx) = handle(jff,'callbackproperties');
          addReadOnlyProp(jframe(figIdx),'ListOfCallbacks',cbNames);

          % Add another read-only property for direct access to the wrapped java object
          addReadOnlyProp(jframe(figIdx),'JavaComponent',jff);

          % Add another read-only property for direct access to the original Matlab figure handle
          addReadOnlyProp(jframe(figIdx),'MatlabFigureHandle',hFig(figIdx));
      end

  % Error handling
  catch
      v = version;
      if v(1)<='6'
          err.message = lasterr;  %#ok<*LERR> % no lasterror function...
      else
          err = lasterror;
      end
      try
          err.message = regexprep(err.message,'Error using ==> [^\n]+\n','');
      catch
          try
              % Another approach, used in Matlab 6 (where regexprep is unavailable)
              startIdx = findstr(err.message,'Error using ==> '); %#ok<*FSTR>
              stopIdx = findstr(err.message,char(10)); %#ok<*CHARTEN>
              for idx = length(startIdx) : -1 : 1
                  idx2 = min(find(stopIdx > startIdx(idx)));  %#ok ML6
                  err.message(startIdx(idx):stopIdx(idx2)) = [];
              end
          catch
              % never mind...
          end
      end
      if isempty(findstr(mfilename,err.message))
          % Indicate error origin, if not already stated within the error message
          err.message = [mfilename ': ' err.message];
      end
      if v(1)<='6'
          while err.message(end)==char(10)
              err.message(end) = [];  % strip excessive Matlab 6 newlines
          end
          error(err.message);
      else
          rethrow(err);
      end
  end

%% Add a read-only property to an object
function addReadOnlyProp(obj,propName,initValue)
  try
      % This will fail in R2014b+ since schema.prop is no longer supported in HG2
      sp = schema.prop(obj,propName,'mxArray');
      set(obj,propName,initValue);
      set(sp,'AccessFlags.PublicSet','off');
  catch
      % Never mind - property might already exist...
  end

%% Get the root Java frame (up to 10 tries, to wait for figure to become responsive)
function jframe = getJFrame(hFigHandle)

  % Ensure that hFig is a figure handle...
  hFig = ancestor(hFigHandle,'figure');
  if isempty(hFig)
      error(['Cannot retrieve the figure handle for handle ' num2str(hFigHandle)]);
  end

  jframe = [];
  maxTries = 10;
  while maxTries > 0
      try
          % Get the figure's underlying Java frame
          oldWarn = warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
          jf = get(handle(hFig),'JavaFrame');
          warning(oldWarn);

          % Get the Java frame's root frame handle
          %jframe = jf.getFigurePanelContainer.getComponent(0).getRootPane.getParent;
          try
              jClient = jf.fFigureClient;  % This works up to R2011a
          catch
              try
                  jClient = jf.fHG1Client;  % This works from R2008b-R2014a
              catch
                  jClient = jf.fHG2Client;  % This works from R2014b and up
              end
          end
          jframe = jClient.getWindow;  % equivalent to above...
          if ~isempty(jframe)
              break;
          else
              maxTries = maxTries - 1;
              drawnow; pause(0.1);
          end
      catch
          maxTries = maxTries - 1;
          drawnow; pause(0.1);
      end
  end
  if isempty(jframe)
      try jframe = javax.swing.SwingUtilities.getWindowAncestor(jf.getAxisComponent); catch, end % see controllibutils.centerfig (%matlabroot%\toolbox\shared\controllib\graphics\+controllibutils.m)
  end
  if isempty(jframe)
      error('Cannot retrieve the java frame for the specified handle');
  end


%TestCaseTest Unit tests for the TestCase class

%   Steven L. Eddins
%   Copyright The MathWorks 2008

classdef TestCaseTest < TestCaseInDir

    methods
        function self = TestCaseTest(name)
            self = self@TestCaseInDir(name, ...
                fullfile(fileparts(which(mfilename)), 'helper_classes'));
        end

        function testConstructor(self)
            % Exercise the constructor.  Verify that the Name and Location
            % properties are set correctly.
            tc = TwoPassingTests('testMethod1');
            assertEqual(tc.Name, 'testMethod1');
            assertEqual(tc.Location, which('TwoPassingTests'));
        end

        function testPassingTests(self)
            % Verify that the expected observer notifications are received in
            % the proper order.
            logger = TestRunLogger();
            TestSuite('TwoPassingTests').run(logger);
            assertTrue(isequal(logger.Log, ...
                {'TestRunStarted', 'TestComponentStarted', ...
                'TestComponentStarted', 'TestComponentFinished', ...
                'TestComponentStarted', 'TestComponentFinished', ...
                'TestComponentFinished', 'TestRunFinished'}));
        end

        function testFixtureCalls(self)
            % Verify that fixture calls are made in the proper order.
            tc = LoggingTestCase('testMethod');
            tc.run(TestRunLogger());
            assertTrue(isequal(tc.log, {'setUp', 'testMethod', 'tearDown'}));
        end

        function testTestFailure(self)
            % Verify that a test failure is recorded.
            logger = TestRunLogger();
            TestSuite('FailingTestCase').run(logger);
            assertTrue(isequal(logger.NumFailures, 1));
        end

        function testTestError(self)
            % Verify that a test error is recorded.
            logger = TestRunLogger();
            TestSuite('BadFixture').run(logger);
            assertTrue(isequal(logger.NumErrors, 1));
        end

    end

end


% [INPUT]
% txt = A string representing the text to clear.
%
% [OUTPUT]
% out = A string representing the escaped text.
%
% [NOTES]
% The function strips HTML tags and escapes backslashes.

function out = clear_text(varargin)

    persistent ip;

    if (isempty(ip))
        ip = inputParser();
        ip.addRequired('txt',@(x)validateattributes(x,{'char'},{}));
    end

    ip.parse(varargin{:});

    ipr = ip.Results;
    txt = ipr.txt;

    nargoutchk(1,1);

    out = clear_text_internal(txt);

end

function out = clear_text_internal(txt)

    if (isempty(txt))
        out = txt;
    else
        out = regexprep(txt,'<[^>]*>','');
        out = strrep(out,filesep(),[filesep() filesep()]);
    end

end


classdef MemoryManager < handle

    methods (Access = public, Abstract)

        link(obj)
        allocateMemory(obj)
        freeSpareMemory(obj)
        transferData(obj)

    end

end


function enableM(plant)
    plant.isMEnabled = 1;
end


function set_legend_fontsize(h_leg, fontsize);
set(h_leg, 'FontSize', fontsize);


classdef prtUiManagerPanel < prtUiManager

    properties (Dependent)
        title
        fontSize
    end

    methods
        function self = prtUiManagerPanel(varargin)
           self = self@prtUiManager(varargin{:});
        end

        function create(self)
            self.managedHandle = uipanel('BackgroundColor',get(0,'DefaultFigureColor'),...
                'BorderType','none');
        end

        function set.title(self,str)
            set(self.managedHandle,'title',str)
        end
        function val = get.title(self)
            val = get(self.managedHandle,'title');
        end

        function val = get.fontSize(self)
            val = get(self.managedHandle,'fontSize');
        end
        function set.fontSize(self,val)
            set(self.managedHandle, 'fontsize', val);
        end

    end
end


%% function for get files full name by replacing relative locations like '.', '~'
function nam = get_fullname(nam)
tmp_dir = cd();
[dir_nm, file_nm, ext] = fileparts(nam);
if isempty(dir_nm)
    dir_nm = tmp_dir;
end
cd(dir_nm);
dir_nm = cd();
nam = [dir_nm,filesep, file_nm, ext];
cd(tmp_dir);
end


fprintf('Spectral Clustering: Adding directories to current path...\n');

% make sure we add the correct folders even if this file is
% not called from the current folder
fileName = mfilename();
filePath = mfilename('fullpath');
filePath = filePath(1:end-size(fileName, 2));

% Add folders to current path
path(genpath([filePath 'files']), path);

fprintf('Spectral Clustering: Starting GUI...\n');

% Open main GUI
guiMain;

fprintf('Spectral Clustering: Ready.\n\n');

% clear variables
clearvars fileName filePath


function output = prtPath(varargin)
% prtPath Adds necessary directories for the PRT to your path.

if isdeployed
    return;
end

addpath(fullfile(prtRoot,'util'));
origPath = prtUtilGenCleanPath(prtRoot);
addpath(origPath);

for iArg = 1:length(varargin)
    cArg = varargin{iArg};
    cDir = fullfile(prtRoot,cat(2,']',cArg));
    assert(logical(exist(cDir,'file')),']%s is not a directory in %s',cArg,prtRoot);
    P = prtUtilGenCleanPath(cDir,'removeDirStart',{'.'});
    addpath(P);
    origPath = cat(2,origPath,P);
end
if nargout > 0
    output = origPath;
end


function obj = update(obj)
	% Biafra Ahanonu
	% Started: 2021.03.25 [22:11:25] (branched from ciatah.m)

	% Notify user if they are behind version-wise.
	ciapkg.io.updatePkg;
	uiwait(ciapkg.overloaded.msgbox('The CIAtah GitHub website will open. Click "Clone or download" button to download most recent version of CIAtah.'))
	web(obj.githubUrl);
end


function clipboardData = clipboardpaste(format)
    %clipboardpaste v0.1.3
    %   Usage:
    %       clipboardData = clipboardpaste(format)
    %
    %   Input Arguments:
    %       format (optional)
    %           Requested image format. If the clipboard contains an image,
    %           then the image will be automatically set to format. Valid
    %           formats are:
    %               'png'
    %               'jpg' (or 'jpeg')
    %               'tif' (or 'tiff')
    %               'bmp'
    %               'gif'
    %               'ico'
    %               'cur'
    %               'pnm'
    %               'ppm'
    %               'pbm'
    %               'ras'
    %               'xwd'
    %               'fts'/'fits'
    %
    %           By default, the format is 'png'.
    %
    %   Output Arguments:
    %       clipboardData
    %           Struct representing the data on the clipboard. It has three
    %           fields:
    %               (1) primaryType: String denoting which kind of data was
    %               retrieved from the clipboard. It can be one of several
    %               possibilities:
    %                   -- 'text'
    %                   -- 'binary'
    %
    %               (2) subType: String denoting specifically which kind of
    %               data was retrieved from the clipboard. It can be one of
    %               several possibilities:
    %                   -- 'url'
    %                   -- 'image'
    %                   -- 'plain-text'
    %                   -- 'email'
    %
    %               (3) data: Data from the clipboard. This can be of
    %               several types, depending on the primaryType/subType
    %               combination:
    %                   -- 'text'/'url': A string denoting a URL
    %                   -- 'text'/'email': A string denoting an email
    %                   address
    %                   -- 'text'/'plain-text': A string
    %                   -- 'binary'/'image': An image of the specified
    %                   format (uint8 array). It is viewable by using the
    %                   command imshow()
    %
    %   Description:
    %       Retrieves data from the clipboard. The clipboard data may be of
    %       several types and it is encapsulated in a self-describing
    %       structure. This function is based on clipboardimage, by Saurabh
    %       Kumar, saurabhkumar_@rediffmail.com, with heavy modifications to
    %       address various cross-platform issues.
    %
    %   Example:
    %       First, copy something on to the clipboard. Say that you copy
    %       the number 14584 onto the clipboard.
    %       >> clipData = clipboardpaste %now paste it into the workspace
    %       clipData =
    %
    %                  data: '14584'
    %           primaryType: 'text'
    %               subType: 'plain-text'
    %       >> data = clipData.data; %get the actual data from the clipboard
    %
    %   =======================
    %   Written by Bryan Raines on May 5, 2008
    %   Last updated on May 6, 2008.
    %   Email: rainesb@ece.osu.edu
    %
    %   See also clipboard.

    usesXClipboard = isunix && ~strcmpi(computer, 'mac');

    if usesXClipboard
        if isempty(get(0,'DefaultFigureXDisplay'))
            error('MATLAB:clipboard:NoXDisplay', 'There is no X display set.');
        end
    else
        err = javachk('awt', 'Clipboard access');
        if (~isempty(err))
            error('MATLAB:clipboard:UnsupportedPlatform', err.message);
        end
    end

    clipboardData     = [];
    error(nargchk(0,1,nargin));

    if nargin < 1
        format = 'png';
    end

    try
        tKit                =       java.awt.Toolkit.getDefaultToolkit();
        clipboardHandle     =       tKit.getSystemClipboard();
        reqObj              =       java.lang.Object;
        clipboardContents   =       clipboardHandle.getContents(reqObj); %get all objects on clipboard
        Dflavor             =       clipboardContents.getTransferDataFlavors();

        %Go through the various DataFlavors until you find one that is
        %recognized
        for ii = 1:length(Dflavor)
            dataType = char(Dflavor(ii).getMimeType);

            switch dataType
                case 'image/x-pict; class=java.io.InputStream'
                    imarray = clipboardContents.getTransferData(Dflavor(ii));
                    clipboardData = encapsulateImageData(getImageFromClipboardData(imarray,format));
                    break;

                case 'image/x-java-image; class=java.awt.Image'
                    imarray = clipboardContents.getTransferData(Dflavor(ii));
                    clipboardData = encapsulateImageData(getImageFromClipboardData(imarray,format));
                    break;

                case 'application/x-java-file-list; class=java.util.List'
                    fileList = clipboardContents.getTransferData(Dflavor(ii));
                    clipboardData = encapsulateFileListData(fileList);
                    break;

                case 'application/x-java-url; class=java.net.URL'
                    urlText = char(clipboardContents.getTransferData(Dflavor(end))');
                    urlText = strtrim(urlText);

                    if isURLType(urlText)
                        if isImageType(urlText)
                            clipboardData = encapsulateImageData(downloadImage(urlText,format));
                        else
                            clipboardData = encapsulateURLData(urlText);
                        end
                        break;
                    end

                case 'application/x-java-serialized-object; class=java.lang.String'
                    textData = char(clipboardContents.getTransferData(Dflavor(ii)));
                    textData = strtrim(textData);

                    if isURLType(textData)
                        clipboardData = encapsulateURLData(textData);
                    elseif isEmailType(textData)
                        [tf emailAddress] = isEmailType(textData);
                        clipboardData = encapsulateEmailData(emailAddress);
                    else
                        clipboardData = encapsulatePlainTextData(textData);
                    end

                    break;
            end
        end
    catch
        disp('Error occurred in retrieving clipboard data');
    end
end

%=========== Encapsulate Clipboard Data in a clipboardStruct ===========
function clipboardData = encapsulateImageData(data)
    clipboardData.data = data;
    clipboardData.primaryType = 'binary';
    clipboardData.subType = 'image';
end

function clipboardData = encapsulateURLData(data)
    clipboardData.data = data;
    clipboardData.primaryType = 'text';
    clipboardData.subType = 'url';
end

function clipboardData = encapsulatePlainTextData(data)
    clipboardData.data = data;
    clipboardData.primaryType = 'text';
    clipboardData.subType = 'plain-text';
end

function clipboardData = encapsulateEmailData(data)
    clipboardData.data = data;
    clipboardData.primaryType = 'text';
    clipboardData.subType = 'email';
end

function clipboardData = encapsulateFileListData(data)
    fileListArray = data.toArray;

    for ii = 1:length(fileListArray)
        fileList{ii,1} = char(fileListArray(ii).toString);
    end

    clipboardData.data = fileList;
    clipboardData.primaryType = 'text';
    clipboardData.subType = 'file-list';
end

%=========== Determine Clipboard Data Type ===========
function tf = isImageType(textData)
    [var1 var2 ext] = fileparts(textData); %determine the file type
    imageTypes = {'.png','.jpg','.tif','.tiff','.bmp','.gif'};
    tf = any(strcmpi(imageTypes,ext));
end

function tf = isURLType(textData)
    %if the text just starts with www, then attach http:// as a prefix
    if ~isempty(regexp(textData,'^www','once'))
        textData = ['http://' textData];
    end

    %If the text starts with a protocol, then assume that it is a URL
    protocols = {'http','ftp','https','vnc','smb','file','irc'};

    for ii = 1:length(protocols)
        tf(ii) = ~isempty(regexp(textData,['^' protocols{ii}], 'once' ));
    end

    tf = any(tf);
end

function [tf emailAddress] = isEmailType(textData)
    emailAddress = regexp(textData,'^(mailto:)*(?<email>[\w\-\_\.]+@[\w\.\-\_]+)','tokens','once');
    tf = ~isempty(emailAddress);
    if tf
        emailAddress = emailAddress{2};
    end
end

%=========== Get Image from Clipboard ===========
function clipboardData = getImageFromClipboardData(imarr,format)
    %Grabs an image from the clipboard
    filename = [tempname '.' format];

    if ismac
        theImage = getImageFromPictStream(imarr);
    else
        theImage = imarr;
    end
    filehandle = java.io.File(filename);
    javax.imageio.ImageIO.write(theImage,format,filehandle);
    clipboardData = imread(filename);
    delete(filename);
end

function clipboardData = downloadImage(urlText,format)
    %Grabs an image by downloading it using the URL from the clipboard
    imarray = imread(urlText);
    filename = [tempname '.' format];
    imwrite(imarray,filename);
    clipboardData = imread(filename);
    delete(filename);
end

function awtImage = getImageFromPictStream(inputstream)
    %Exists for Mac OS X compabilibility. Requires Quicktime for Java to be
    %properly installed.

    %Check if QT for Java is installed
    try
        quicktime.QTSession.isInitialized();
    catch
        warning('Quicktime for Java is not installed.'); %#ok<WNTAG>
    end

    baos = java.io.ByteArrayOutputStream();

    isc = com.mathworks.mlwidgets.io.InterruptibleStreamCopier.getInterruptibleStreamCopier;
    isc.copyStream(inputstream,baos);
    baos.close;

    imgBytes = typecast(baos.toByteArray,'uint8');
    imgBytes = [cast(zeros(512,1),'uint8'); imgBytes];

    if ~quicktime.QTSession.isInitialized()
        quicktime.QTSession.open();
    end

    handle = quicktime.util.QTHandle(imgBytes);
    gi = quicktime.std.image.GraphicsImporter(quicktime.util.QTUtils.toOSType('PICT'));
    gi.setDataHandle(handle);
    qdRect = gi.getNaturalBounds();
    gid = quicktime.app.view.GraphicsImporterDrawer(gi);
    qip = quicktime.app.view.QTImageProducer(gid,java.awt.Dimension(qdRect.getWidth(),qdRect.getHeight()));
    awtImage = java.awt.Toolkit.getDefaultToolkit.createImage(qip);
    awtImage = getBufImage(awtImage);
end

function bufImage = getBufImage(clipboardContents)
    %Creates a rendered (buffered) image from an OSX image data flavor
    ww = clipboardContents.getWidth;
    hh = clipboardContents.getHeight;

    bufImage = java.awt.image.BufferedImage(ww,hh,java.awt.image.BufferedImage.TYPE_INT_RGB);

    g2 = bufImage.createGraphics;
    g2.setRenderingHint(java.awt.RenderingHints.KEY_INTERPOLATION,...
        java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2.drawImage(clipboardContents,0,0,ww,hh,[]);
    g2.dispose();
end

function tf = ismac
    %Detect if the computer is a Mac for versions before R2007a
    tf = strcmpi(computer,'mac');
end


% FT_POSTAMBLE_HASTOOLBOX is executed at the end of each FieldTrip
% function to remove other toolboxes that have been added automatically
% by FT_HASTOOLBOX during execution of the specific function.
%
% Use as
%   ft_postamble hastoolbox
%
% See also FT_PREAMBLE, FT_POSTAMBLE, FT_HASTOOLBOX

% Copyright (C) 2018, Robert Oostenveld, DCCN
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

global ft_default

if ~isempty(ft_default) && isfield(ft_default, 'toolbox') && isfield(ft_default.toolbox, 'cleanup')
  while ~isempty(ft_default.toolbox.cleanup)
    toolbox = ft_default.toolbox.cleanup{end};
    ft_warning('off','backtrace');
    ft_warning('removing %s toolbox from your MATLAB path', toolbox);
    ft_warning('on','backtrace');
    rmpath(genpath(toolbox));
    ft_default.toolbox.cleanup = ft_default.toolbox.cleanup(1:end-1);
  end
end


classdef GemProgressPanel < CoreProgressInterface
    % GemProgressPanel. A panel used to report progress informaton
    %
    %     GemProgressPanel implements the CoreProgressInterface, which is an
    %     interface used by applications that use CoreMat to report the progress of
    %     operations. This panel is displayed over the centre of the panel
    %     object whose handle is supplied in the constructor.
    %
    %
    %     Licence
    %     -------
    %     Part of GEM. https://github.com/tomdoel/gem
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    properties
        ShowDebuggingControls = false
    end

    properties (Access = private)

        % Handles to the GUI components
        Parent
        PanelHandle
        UiControlTitle
        UiControlText
        UiControlCancel
        UiControlQuit
        UiControlHide
        ProgressBarHandle

        IncrementThreshold = 5

        % Flags
        Hold = false;
        ShowProgressBar = false
        UserClickedCancel = false

        % The current values
        DialogText
        DialogTitle = ''
        ProgressValue = 0
        PanelVisibility = false;

        % The previous values
        CurrentlyDisplayedDialogTitle
        CurrentlyDisplayedDialogText
        CurrentlyDisplayedProgressValue
        CurrentlyDisplayedVisibility = false
        ProgressBarCurrentlyVisible = false;

        TimerRef
        MaxTimeBetweenUpdates = 0.25
        ChangePending
    end

    properties (GetAccess = private, Constant)
        OpacityLevel = 0.85
        Width = 500
        Height = 250
    end

    methods
        function obj = GemProgressPanel(parent)
            obj.ChangePending = false;
            obj.CurrentlyDisplayedDialogTitle = '';
            obj.CurrentlyDisplayedDialogText = '';
            obj.CurrentlyDisplayedProgressValue = [];

            obj.Parent = parent.GraphicalComponentHandle;

            set(obj.Parent, 'Units', 'Pixels');

            % Create the panel
            panel_background_colour = parent.StyleSheet.BackgroundColour;
            text_color = parent.StyleSheet.TextPrimaryColour;

            progress_position = obj.GetPanelPosition;
            obj.PanelHandle = uipanel('Parent', obj.Parent, 'Title', '', 'BorderType', 'etchedin', 'ForegroundColor', text_color, ...
                'BackgroundColor', panel_background_colour, 'Units', 'pixels', 'Position', progress_position, 'Visible', 'off' ...
            );

            title_position = [20, 165, 460, 55];
            text_position = [20, 115, 460, 50];
            cancel_position = [175, 20, 150, 40];
            quit_position = [370, 20, 80, 40];
            hide_position = [50, 20, 80, 40];
            progress_bar_position = [50, 90, 400, 18];

            obj.UiControlTitle = uicontrol('parent', obj.PanelHandle, 'style', 'text', 'units', 'pixel', 'Position', title_position, ...
                'string', 'Please wait', 'FontUnits', 'pixels', 'FontSize', 24, 'FontWeight', 'bold', 'Fore', text_color, 'Back', panel_background_colour, 'Visible', 'off');
            obj.UiControlText = uicontrol('parent', obj.PanelHandle, 'style', 'text', 'units', 'pixel', 'Position', text_position, ...
                'string', 'Please wait', 'FontUnits', 'pixels', 'FontSize', 16, 'Fore', text_color, 'Back', panel_background_colour, 'Visible', 'off');
            obj.UiControlCancel = uicontrol('parent', obj.PanelHandle, 'string', 'Cancel', ...
                'Position', cancel_position, 'FontUnits', 'pixels', 'Callback', @obj.CancelButton, 'Visible', 'off');
            obj.UiControlQuit = uicontrol('parent', obj.PanelHandle, 'string', 'Force Quit', ...
                'Position', quit_position, 'FontUnits', 'pixels', 'Callback', @obj.QuitButton, 'Visible', 'off');
            obj.UiControlHide = uicontrol('parent', obj.PanelHandle, 'string', 'Hide Dialog', ...
                'Position', hide_position, 'FontUnits', 'pixels', 'Callback', @obj.HideButton, 'Visible', 'off');

            [obj.ProgressBarHandle, ~] = javacomponent('javax.swing.JProgressBar', ...
                progress_bar_position, obj.PanelHandle);
            obj.ProgressBarHandle.setBackground(java.awt.Color(panel_background_colour(1), panel_background_colour(2), panel_background_colour(3)));
            set(obj.ProgressBarHandle, 'visible', 0);
        end

        function Resize(obj)
            set(obj.PanelHandle, 'Position', obj.GetPanelPosition);
        end

        function ShowAndHold(obj, text)
            if nargin < 2
                text = 'Please wait';
            end
            obj.DialogTitle = CoreTextUtilities.RemoveHtml(text);
            obj.DialogText = '';
            obj.ProgressValue = 0;
            obj.Hold = true;
            obj.UserClickedCancel = false;
            obj.PanelVisibility = true;
            obj.ShowProgressBar = false;
            obj.TimerRef = [];
            obj.Update();
        end

        function Hide(obj)
            obj.DialogTitle = 'Please wait';
            obj.Hold = false;
            obj.PanelVisibility = false;
            obj.ShowProgressBar = false;
            obj.Update();
        end

        function Complete(obj)
            % Call to complete a progress operaton, which will also hide the dialog
            % unless the dialog is being held

            obj.ShowProgressBar = false;
            obj.ProgressValue = 100;
            if ~obj.Hold
                obj.PanelVisibility = false;
            else
                obj.SetProgressText('');
            end
            obj.Update();
        end

        function SetProgressText(obj, text)
            if nargin < 2
               text = 'Please wait';
            end
            obj.DialogText = CoreTextUtilities.RemoveHtml(text);
            obj.PanelVisibility = true;
            obj.Update();
        end

        function SetProgressValue(obj, progress_value)
            obj.ShowProgressBar = true;
            obj.ProgressValue = progress_value;
            obj.PanelVisibility = true;
            obj.Update();
        end

        function SetProgressAndMessage(obj, progress_value, text)
            obj.ShowProgressBar = true;
            obj.DialogText = CoreTextUtilities.RemoveHtml(text);
            obj.ProgressValue = progress_value;
            obj.PanelVisibility = true;
            obj.Update();
        end

        function cancelled = CancelClicked(obj)
            cancelled = obj.UserClickedCancel;
            obj.UserClickedCancel = false;
        end
    end

    methods (Access = private)
        function changed = Update(obj)
            changed = false;
            changed = obj.UpdateDialogTitle || changed;
            changed = obj.UpdateDialogText || changed;
            changed = obj.UpdateProgressValue || changed;
            changed = obj.UpdateVisibility || changed;
            changed = obj.UpdateProgressBarVisibility || changed;

            if changed
                obj.ChangePending = true;
            end

            if obj.ChangePending
                if isempty(obj.TimerRef) || toc(obj.TimerRef) > obj.MaxTimeBetweenUpdates
                    obj.TimerRef = tic;
                    drawnow;
                    obj.ChangePending = false;
                end
            end

        end

        function changed = UpdateDialogTitle(obj)
            changed = false;
            if ~strcmp(obj.DialogTitle, obj.CurrentlyDisplayedDialogTitle)
                set(obj.UiControlTitle, 'String', obj.DialogTitle);
                obj.CurrentlyDisplayedDialogTitle = obj.DialogTitle;
                changed = true;
            end
        end

        function changed = UpdateDialogText(obj)
            changed = false;
            if ~strcmp(obj.DialogText, obj.CurrentlyDisplayedDialogText)
                set(obj.UiControlText, 'String', obj.DialogText);
                obj.CurrentlyDisplayedDialogText = obj.DialogText;
                changed = true;
            end
        end

        function changed = UpdateProgressValue(obj)
            changed = false;
            if isempty(obj.CurrentlyDisplayedProgressValue) || (obj.ProgressValue ~= obj.CurrentlyDisplayedProgressValue)
                obj.ProgressBarHandle.setValue(obj.ProgressValue);
                obj.CurrentlyDisplayedProgressValue = obj.ProgressValue;
                changed = true;
            end
        end

        function changed = UpdateProgressBarVisibility(obj)
            changed = false;
            if ~obj.ProgressBarCurrentlyVisible && obj.ShowProgressBar && obj.PanelVisibility
                set(obj.ProgressBarHandle, 'visible', 1);
                obj.ProgressBarCurrentlyVisible = true;
                changed = true;
            elseif obj.ProgressBarCurrentlyVisible && (~obj.ShowProgressBar || ~obj.PanelVisibility)
                set(obj.ProgressBarHandle, 'visible', 0);
                obj.ProgressBarCurrentlyVisible = false;
                changed = true;
            end
        end

        function changed = UpdateVisibility(obj)
            changed = false;
            if obj.PanelVisibility && ~obj.CurrentlyDisplayedVisibility
                set(obj.PanelHandle, 'Visible', 'on');
                set(obj.UiControlText, 'Visible', 'on');
                set(obj.UiControlTitle, 'Visible', 'on');
                if obj.ShowDebuggingControls
                    set(obj.UiControlQuit, 'Visible', 'on');
                    set(obj.UiControlHide, 'Visible', 'on');
                end
                set(obj.UiControlCancel, 'Visible', 'on');
                obj.CurrentlyDisplayedVisibility = true;
                changed = true;
            elseif ~obj.PanelVisibility && obj.CurrentlyDisplayedVisibility
                set(obj.UiControlText, 'Visible', 'off');
                set(obj.UiControlTitle, 'Visible', 'off');
                set(obj.UiControlQuit, 'Visible', 'off');
                set(obj.UiControlHide, 'Visible', 'off');
                set(obj.UiControlCancel, 'Visible', 'off');
                set(obj.ProgressBarHandle, 'visible', 0);
                set(obj.PanelHandle, 'Visible', 'off');
                obj.CurrentlyDisplayedVisibility = false;
                obj.ProgressBarCurrentlyVisible = false;
                changed = true;
            end
        end

        function CancelButton(obj, ~, ~)
            obj.UserClickedCancel = true;
            obj.PanelVisibility = false;
            obj.Hold = false;
            obj.Update();
        end

        function QuitButton(obj, ~, ~)
            obj.PanelVisibility = false;
            obj.Hold = false;
            obj.UpdateVisibility();
            throw(MException('GemProgressPanel:UserForceQuit', 'User forced plugin to quit'));
        end

        function HideButton(obj, ~, ~)
            obj.PanelVisibility = false;
            obj.Hold = false;
            obj.UpdateVisibility();
        end

        function progress_position = GetPanelPosition(obj)
            panel_position = get(obj.Parent, 'Position');

            window_width = panel_position(3);
            window_height = panel_position(4);
            progress_width = min(obj.Width, window_width);
            progress_height = min(obj.Height, window_height);
            progress_x = max(1, round((window_width - progress_width)/2));
            progress_y = max(1, (2/3)*round((window_height - progress_height)));
            progress_position = [progress_x, progress_y, progress_width, progress_height];
        end

    end
end


%GETHANDLEFG Framegrabber device gethandle function.
%
%SYNTAX devinfo = gethandlefg('alias')
%
%Description This function will return the handle of
%the framegrabber device when you lost the handle to
%the device.
%
%INPUT The alias (alias) of the framegrabber device.
%
%REMARKS It will be verified if the input is a string.
%If it's valid string, the function will  return the
%device information structure of the device.
%
%OUTPUT If the input isn't valid, some error message will
%be shown to the user. If everything's ok, the function
%will return the device information structure of the opened
%framegrabber device with the given alias.
%
%EXAMPLE To regain the handle to the framegrabber, type
%in the Matlab Command Window :

%m=gethandlefg('DT3155');

disp('Error: gethandlefg not found.')


function populateStationsCombo(handles, hRefStationsCombo)
    maData = getappdata(handles.ma_MainGUI,'ma_data');

    if(isfield(maData.spacecraft,'stations'))
        stations = maData.spacecraft.stations;
        if(isempty(stations))
            set(hRefStationsCombo, 'Enable','off');
            set(hRefStationsCombo,'String', 'None Available');
        else
            set(hRefStationsCombo, 'Enable','on');

            stnStr = cell(0,1);
            for(i=1:length(stations)) %#ok<*NO4LP>
                stnStr{end+1} = stations{i}.name; %#ok<AGROW>
            end
            set(hRefStationsCombo,'String',stnStr);
        end
    else
        set(hRefStationsCombo, 'Enable','off');
        set(hRefStationsCombo,'String', 'None Available');
    end
end


function dbName = response_demo_database

%RESPONSE_DEMO_DATABASE returns the absolute path to the demo database
%  DBNAME = RESPONSE_DEMO_DATABASE

file = which('response_cookbook');
path = fileparts(file);

if ~exist([path '/demo'])
	error('response_demo_database: demo database not found');
else
	dbName = [path '/demo/plutons'];
end


classdef plotlystream < handle
    % Interface to Plotly's real-time graphing API.
    % Initialize a Stream object with a stream_id found in
    % {plotly_domain}/settings. Real-time graphs are
    % initialized with a call to plotly that embeds your unique
    % `stream_id`s in each of the graph's traces. The plotlystream
    % class plots data to these traces, as identified with the unique
    % stream_id, in real-time. Every viewer of the graph sees
    % the same data at the same time.

    %----CLASS PROPERTIES----%
    properties
        Response
        Specs
    end

    properties (Access=private)
        URL
        ErrorURL
        Connection
        ErrorConnection
        Stream
        ErrorStream
    end

    %----CLASS METHODS----%
    methods

        %----CONSTRUCTOR---%
        function obj = plotlystream(request)

            %default stream settings
            obj.Specs.Token = '';

            %look for specified streaming domain
            try
                config = loadplotlyconfig;
                obj.Specs.Host  = config.plotly_streaming_domain;
            catch
                obj.Specs.Host = 'http://stream.plot.ly';
            end

            %check if ssl is enabled
            if any(strfind(obj.Specs.Host,'https://') == 1)
                obj.Specs.SSLEnabled = true;
            else
                obj.Specs.SSLEnabled = false;
            end

            %add http if not present on host
            if ~obj.Specs.SSLEnabled
                if ~any(strfind(obj.Specs.Host,'http://') == 1)
                    obj.Specs.Host = ['http://' obj.Specs.Host];
                end
            end

            %specify handler
            if obj.Specs.SSLEnabled
                obj.Specs.Handler = sun.net.www.protocol.https.Handler;
            else
                obj.Specs.Handler = sun.net.www.protocol.http.Handler;
            end

            %initialize connection settings
            obj.Specs.ReconnectOn = {'','200','408'};
            obj.Specs.Timeout = 500;
            obj.Specs.Chunklen = 14;
            obj.Specs.Closed = true;
            obj.Specs.ConnectAttempts = 0;
            obj.Specs.ConnectDelay = 1;
            obj.Specs.MaxConnectAttempts = 5;

            %initialize output response
            obj.Response = '';

            %check for correct input structure
            if nargin > 0

                if ischar(request)

                    obj.Specs.Token = request;

                elseif isstruct(request)

                    %check for tokens (required)
                    if (isfield(request,'token'))
                        obj.Specs.Token = request.token;
                    else
                        error(['Oops! You did not properly specify a stream token! Please check out the ', ....
                            'online documentation found @ plot.ly/matlab for more information or contact ',...
                            'chuck@plot.ly']);
                    end

                    if isfield(request,'host')
                        obj.Specs.Host = request.host;
                    end

                    if isfield(request,'timeout')
                        obj.Specs.Timeout = request.timeout;
                    end

                    if isfield(request,'handler')
                        obj.Specs.Handler= request.handler;
                    end

                    if isfield(request,'chunklen')
                        obj.Specs.Chunklen= request.chunklen;
                    end
                else
                    error(['Oops! It appears that the specified input argument used to ',...
                        'initialize the plotlystream object was not of type char or struct. ',...
                        'Please check out the online documentation found @ plot.ly/matlab ',...
                        'for more information or contact chuck@plot.ly']);
                end

            else
                error(['Oops! You did not properly specify a stream token! Please check out the ', ....
                    'online documentation found @ plot.ly/matlab for more information or contact ',...
                    'chuck@plot.ly']);
            end
        end

        %-----------OPEN STREAM-----------%
        function obj = open(obj)

            try obj.connect;

                %Connection successful!
                fprintf('\n[Connection Successful]\n\n');

                %update state
                obj.resetretries;
                obj.Specs.Closed = false;

            catch ME

                error(['Oops! The following error occured when trying to write to the stream: ',...
                    ME.message '. Please check the online documentation ', ...
                    'found @ plot.ly/matlab for more information or contact chuck@plot.ly']);
            end

        end

        %-----------CONNECT TO STREAM-----------%
        function obj = connect(obj)
            obj.URL = java.net.URL([],obj.Specs.Host,obj.Specs.Handler);

            % Get the proxy information using MathWorks facilities for unified proxy
            % preference settings.
            mwtcp = com.mathworks.net.transport.MWTransportClientPropertiesFactory.create();
            proxy = mwtcp.getProxy();

            % Open a connection to the URL.
            if isempty(proxy)
                obj.Connection = obj.URL.openConnection(); %throws an I/O exception
            else
                obj.Connection = obj.URL.openConnection(proxy); %throws an I/O exception
            end

            obj.Connection.setChunkedStreamingMode(obj.Specs.Chunklen)
            obj.Connection.setRequestMethod('POST');
            obj.Connection.setDoOutput(true);
            obj.Connection.setReadTimeout(obj.Specs.Timeout);
            obj.Connection.setRequestProperty('plotly-streamtoken', obj.Specs.Token);
            obj.Stream = obj.Connection.getOutputStream; %throws an I/O exception
        end

        %-----------WRITE STREAM-----------%
        function obj = write(obj,request)

            if nargin ~= 2
                error(['Oops! It appears that not enough input arguments were ',...
                    'specified to the write method of your plotlystream object. ',...
                    'Please check out the online documentation found @ plot.ly/matlab ',...
                    'for more information or contact chuck@plot.ly']);
            else
                if ~isstruct(request)
                    error(['Oops! It appears that the input argument to the write method ',...
                        'of your plotlystream object is not a structure array as required.  ',...
                        'Please check out the online documentation found @ plot.ly/matlab ',...
                        'for more information or contact chuck@plot.ly']);
                end

                body = request;

                %make sure we did not close the stream
                if(~obj.Specs.Closed)
                    try
                        %write to stream
                        obj.Stream.write(unicode2native(sprintf([m2json(body) '\n']),''));
                    catch ME

                        %error due to stream not being open (creation of Stream object)
                        if(strcmp(ME.message, 'Attempt to reference field of non-structure array.'))
                            error(['Oops! A connection has not yet been established. Please open',...
                                ' a connection by firsting calling the ''open'' method of your',...
                                ' plotlystream object.']);
                        else

                            %---reconnect---%
                            obj.getresponse;
                            if any(strcmp(obj.Specs.ReconnectOn,obj.Response))
                                if~strcmp(obj.Response,'')
                                    fprintf(['\n[Connection Failed due to HTTP error: ' obj.Response '] Reconnecting...\n\n']);
                                else
                                    fprintf('\n[Connection Failed] Reconnecting...\n\n');
                                end
                                obj.reconnect;

                                %add recursion call to not drop data
                                obj.write(body);
                            else
                                error(['Oops! The following error occured when trying to write to the stream: ',...
                                    ME.message '. No attempt to reconnect was made beacause the response code ',...
                                    'of: ' obj.Response ' did not match any of the response codes specified in ',...
                                    'the obj.Specs.ReconnectOn parameter. Please check out the online documentation ', ...
                                    'found @ plot.ly/matlab for more information or contact chuck@plot.ly']);
                            end
                        end
                    end
                else
                    error(['Oops! The connection is closed. Please open ',...
                        'a connection by calling the ''open'' method of your ',...
                        'plotlystream object.']);
                end
            end
        end

        %-----------CLOSE STREAM-----------%
        function obj = close(obj)
            try
                obj.Stream.close;
            catch ME
                if(strcmp(ME.message, 'Attempt to reference field of non-structure array.'))
                    error(['Oops! A connection has not yet been established. Please open',...
                        ' a connection by firsting calling the ''open'' method of your',...
                        ' plotlystream object.']);
                end
            end
            %update reconnect state
            obj.resetretries;
            obj.Specs.Closed = true;
        end

        %-----------RECONNECT-----------%
        function obj = reconnect(obj)
            try
                obj.Specs.ConnectAttempts = obj.Specs.ConnectAttempts + 1;

                %try to connect
                obj.connect;

                %Connection successful!
                fprintf('\n[Connection Successful]\n\n');

                %update state
                obj.resetretries;
                obj.Specs.Closed = false;
            catch
                if(obj.Specs.ConnectAttempts <= obj.Specs.MaxConnectAttempts)
                    fprintf(['\n[Connection Failed] Attempt:' num2str(obj.Specs.ConnectAttempts) ' to reconnect...'])
                    pause(obj.Specs.ConnectDelay);
                    obj.Specs.ConnectDelay = 2*obj.Specs.ConnectDelay; %delay grows by factor of 2
                    obj.reconnect;
                else
                    fprintf('\n');
                    error(['Oops! All attempts to reconnect were unsuccessful. ',...
                        'Please check out the online documentation found @ plot.ly/matlab ',...
                        'for more information or contact chuck@plot.ly']);
                end
            end
        end

        %-----------GET RESPONSE-----------%
        function obj = getresponse(obj)
            try
                obj.Response = num2str(obj.Connection.getResponseCode);
            catch ME
                if(strcmp(ME.message, 'Attempt to reference field of non-structure array.'))
                    error(['Oops! A connection has not yet been established. Please open',...
                        ' a connection by firsting calling the ''open'' method of your',...
                        ' plotlystream object.']);
                end
            end
        end

        %-----------RESET RETRIES-----------%
        function obj = resetretries(obj)
            %reset the connect counter and delay
            obj.Specs.ConnectAttempts = 0;
            obj.Specs.ConnectDelay = 1;
        end

    end
end


function hRD = plugin_rd_rxtx
% Reference design definition

%   Copyright 2014-2015 The MathWorks, Inc.

% Call the common reference design definition function
hRD = AnalogDevices.adrv9371x.common.plugin_rd('ZCU102', 'Rx & Tx');
AnalogDevices.adrv9371x.zcu102.add_io(hRD, 'Rx & Tx');


function tf = prtUtilIsMethodIncludeHidden(obj,methName)
% xxx Need Help xxx
% Internal

m = metaclass(obj);
tf = ismember(methName,cellfun(@(c)c.Name,m.Methods,'uniformoutput',false));


function varargout = ft_read_vol(varargin)

% This function is a backward compatibility wrapper for existing MATLAB scripts
% that call a function that is not part of the FieldTrip toolbox any more.
%
% Please update your code to make it future-proof.

oldname = mfilename;
newname = 'ft_read_headmodel';

ft_warning('%s is only a backward compatibility wrapper, which will soon be removed. Please call %s instead.', upper(oldname), upper(newname));

[varargout{1:nargout}] = feval(newname, varargin{:});