function varargout = chebguiWindow(varargin)
%CHEBGUIWINDOW   Driver file for Chebfun's CHEBGUI
%   This m-file populates and controls Chebfun's CHEBGUI.
%
% See also CHEBGUI.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% DEVELOPER NOTE:
%  This method implements most callback method of CHEBGUI, i.e., methods that
%  get executed when the user interacts with the GUI figure. Many of these
%  methods are automatically generated by MATLAB, which explains why a lot of
%  them have input arguments that appear to be unused (but are needed for the
%  calling mechanism of MATLAB).
%
%  The more complicated methods of controlling the GUI layout live in the
%  @chebguiController folder.
%
%  The methods for actually solving problems using CHEBGUI live in the @chebgui/
%  folder.
%
%  The methods for dealing with exporting problems from the CHEBGUI figure to .m
%  files live in the @chebguiExporter folder, and its subclasses.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Suppress irritating MLINT warnings: 
%#ok<*INUSL,*DEFNU,*INUSD,*ST2NM,*MATCH2>

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @chebguiWindow_OpeningFcn, ...
    'gui_OutputFcn',  @chebguiWindow_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);

if ( nargin && ischar(varargin{1}) )
    gui_State.gui_Callback = str2func(varargin{1});
end

if ( nargout )
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    warnstate = warning('off', 'MATLAB:hg:uicontrol:ParameterValuesMustBeValid');
    try
        gui_mainfcn(gui_State, varargin{:});
        warning(warnstate);
    catch ME
        warning(warnstate)
        MEID = ME.identifier;
        if ( ~isempty(strfind(lower(MEID), 'chebgui:')) )
            % These are expected GUI errors. We only show the dialog
            errordlg(cleanErrorMsg(ME.message), 'Chebgui error', 'modal');
            uiwait
            resetComponents(varargin{4});
            
            % If in debug mode, we throw the error to the command window as well
            if ( get(varargin{4}.menu_debug, 'UserData') )
                rethrow(ME)
            end
        else
            % Show an error dialog:
            errordlg(cleanErrorMsg(ME.message), 'Chebgui error', 'modal');
            uiwait
            resetComponents(varargin{4});
            % If in debug mode, we throw the error to the command window as well
            if ( get(varargin{4}.menu_debug, 'UserData') )
                rethrow(ME)
            end
        end
    end
end
% End initialization code - DO NOT EDIT
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

end

% --- Executes just before chebguiWindow is made visible.
function chebguiWindow_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see Output(1-x^2)*exp(-30*(x+.5)^2)Fcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to chebguiWindow (see VARARGIN)

% The default fontsize of the panels.
handles.fontsizePanels = 12;

% Initialize fonts in the CHEBGUI window:
chebguiController.initalizeFields(handles);

% Choose default command line output for chebguiWindow
handles.output = hObject;

% Initialise the menus:
handles = chebguiController.initialiseMenus(handles);

% Set up the panels:
handles = chebguiController.setupPanels(handles);

% Initialise figures:
chebguiController.initialiseFigures(handles)

% Draw the Chebfun logo on the GUI:
handles = chebguiController.drawLogo(handles);

% Variable that determines whether a solution is available
handles.hasSolution = 0;

% Variable which stores the initial guess/condition
handles.init = [];

% Variable which stores imported variables from workspace
handles.importedVar = struct;

% Get the GUI object from the input argument
if ( ~isempty(varargin) )
    handles.guifile = varargin{1};
else
    handles.guifile = chebgui.demo(); % Load a random demo
end

% Create a new structure which contains information about the latest
% solution obtained
handles.latest = struct;

% Store the default length of pausing between plots for BVPs and the
% tolerance in the userdata field of relevant menu objects.
set(handles.menu_odeplottingpause, 'UserData', '0.5');
set(handles.menu_tolerance, 'UserData', '1e-10');

% Create UserData for the Fix-Y-axis options (so that we can display
% something if it gets called without selecting a demo).
set(handles.menu_pdefixon, 'UserData', {''});

% Populate the Demos menu, but only once (i.e. if user calls chebgui again, 
% don't reload the examples).
if ( ~isfield(handles,'demosLoaded') )
    chebguiController.loadDemoMenu(handles);
    handles.demosLoaded = 1;
end

% Make sure the GUI starts in the correct mode:
chebguiController.switchMode(handles, handles.guifile.type);

% Load the input fields:
chebguiController.populate(hObject, handles, handles.guifile);

% Get the system font size and store in handles
s = char(com.mathworks.services.FontPrefs.getCodeFont);
if ( s(end-2) == '=' )
    fs = round(3/4*str2num(s(end-1)));
else
    fs = round(3/4*str2num(s(end-2:end-1)));
end
set(handles.tempedit, 'FontSize', fs);

% Set the solve button to green
set(handles.button_solve, 'String', 'Solve');
set(handles.button_solve, 'BackgroundColor', [43 129 86]/256);

% Ensure that we have a medium-grey colour in background
set(handles.mainWindow, 'BackgroundColor', .8*ones(1,3));

% Default discretization is chebcolloc2
handles.guifile.options.discretization = 'collocation';

% Default IVP solver is ode113:
handles.guifile.options.ivpSolver = 'ode113';

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes chebguiWindow wait for user response (see UIRESUME)
% uiwait(handles.chebguimainwindow);

end

% --- Outputs from this function are returned to the command line.
function varargout = chebguiWindow_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
if ( nargout > 0 )
    varargout{1} = handles.output;
end

% If nargout == 2, return the fll set of handles
if ( nargout > 1 )
    varargout{2} = handles;
end

end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ------------- Callback functions for the objects of the GUI -----------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ------------------ Functions which call chebgui methods ----------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function button_clear_Callback(hObject, eventdata, handles)
% Clear the GUI figure. This button also represents the 'Pause' button on the
% figure while problems are being solved.

if ( strcmp(get(handles.button_clear, 'String'), 'Clear all') )
    handles = chebguiController.clear(handles);
    % Clear information from the guifile as well
    handles.guifile = chebgui('type', handles.guifile.type);
    guidata(hObject, handles);
elseif strcmp(get(handles.button_clear, 'String'), 'Pause')
    set(handles.button_clear, 'String', 'Continue');
    set(handles.button_clear, 'BackgroundColor', [43 129 86]/256);
    % Re-enable figure button
    set(handles.button_figsol, 'Enable', 'on');
else
    % Disable figure button
    set(handles.button_figsol, 'Enable', 'off');
    set(handles.button_clear, 'String', 'Pause');
    set(handles.button_clear, 'BackgroundColor', [255 179 0]/256);
end

end

function button_solve_Callback(hObject, eventdata, handles)
handles = solveGUI(handles.guifile, handles);
guidata(hObject, handles);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ----------- Functions which do their work without chebgui methods ------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function dom_left_Callback(hObject, eventdata, handles)
% Store the contents of input1_editText as a string. if the string is not a
% number then input will be empty
input = str2num(get(hObject, 'String'));

% Checks to see if input is not numeric or empty. If so, default left end
% of the domain is taken to be -1.
if ( isempty(input) || isnan(input) )
    warndlg('Left endpoint of domain unrecognized, default value -1 used.')
    set(hObject, 'String', '-1')
end

set(handles.input_GUESS, 'Enable', 'on');
set(handles.toggle_useLatest, 'Value', 0);
set(handles.toggle_useLatest, 'Enable', 'off');

handles.guifile.DomLeft = get(hObject, 'String');
guidata(hObject, handles);

end


function dom_right_Callback(hObject, eventdata, handles)
input = str2num(get(hObject, 'String'));

% Checks to see if input is not numeric or empty. If so, default right end
% of the domain is taken to be 1.
if ( isempty(input) || isnan(input) )
    warndlg('Right endpoint of domain unrecognized, default value 1 used.')
    set(hObject, 'String', '1')
end

set(handles.input_GUESS, 'Enable', 'on');
set(handles.toggle_useLatest, 'Value', 0);
set(handles.toggle_useLatest, 'Enable', 'off');

handles.guifile.DomRight = get(hObject, 'String');
guidata(hObject, handles);

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% -------- Functions which do their work in a couple of lines of code ----------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


function str = removeTabs(str)
% Remove tabs from inputs
for k = 1:numel(str)
    idx = 1;
    strk = str{k};
    while ( ~isempty(idx) )
        idx = strfind(strk, double(9));
        strk(idx) = [];
    end
    str{k} = strk;
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ----------------------------- Keypresses -------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% These methods go from one input box to another when the user presses the 'tab'
% button.

function popupmenu_sigma_KeyPressFcn(hObject, eventdata, handles)
if ( strcmp(eventdata.Key, 'tab') )
    if ( strcmp(eventdata.Modifier, 'shift') )
        uicontrol(handles.edit_eigN); 
    else
        uicontrol(handles.button_solve); 
    end
end
end

function button_solve_KeyPressFcn(hObject, eventdata, handles)
if ( strcmp(eventdata.Key, 'tab') )
    if ( strcmp(eventdata.Modifier, 'shift') )
        if ( get(handles.button_eig, 'value') )
            uicontrol(handles.input_BC); 
        else
            uicontrol(handles.input_GUESS); 
        end
    else
        uicontrol(handles.button_clear); 
    end
elseif ( strcmp(eventdata.Key, 'return') )
    button_solve_Callback(hObject, eventdata, handles);
end
end

function button_clear_KeyPressFcn(hObject, eventdata, handles)
if ( strcmp(eventdata.Key, 'tab') )
    if ( strcmp(eventdata.Modifier, 'shift') )
        uicontrol(handles.button_solve); 
    else
        uicontrol(handles.button_export); 
    end
elseif ( strcmp(eventdata.Key, 'return') )
    button_clear_Callback(hObject, eventdata, handles);
end
end

function button_export_KeyPressFcn(hObject, eventdata, handles)
if ( strcmp(eventdata.Key, 'tab') )
    if ( strcmp(eventdata.Modifier, 'shift') )
        uicontrol(handles.button_clear); 
    elseif ( get(handles.button_exportsoln, 'enabled') )
        uicontrol(handles.button_exportsoln);
    else 
        uicontrol(handles.input_domain);
    end
elseif ( strcmp(eventdata.Key, 'return') )
    button_export_Callback(hObject, eventdata, handles);
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ------------------------- Unsorted functions  --------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function button_figsol_Callback(hObject, eventdata, handles)
% Executed when the user wants to show figures in new window.

if ( get(handles.button_bvp, 'Value') || get(handles.button_ivp, 'Value') )
    % We're in ODE mode.
    
    % Plot the latest solution obtained:
    figure
    latestSolution = handles.latest.solution;
    plot(latestSolution, 'Linewidth', 2)
    title('Solution')
    xlabel(handles.indVarName);

    varnames = handles.varnames;
    if ( numel(varnames) == 1 )
        ylabel(varnames)
    end

    % Turn on grid
    if ( handles.guifile.options.grid )
        grid on
    end

    if ( numel(handles.varnames) > 1 )
        legend(handles.varnames)
    end
    
    % Also open the bottom figure in now window. This is either going to be the
    % PLOTCOEFFS, or a plot showing the norm of the updates during the Newton
    % iteration:
    figure
    
    plotType = get(handles.popupmenu_bottomFig, 'Value');
    
    if ( plotType == 1 ) % Show the norm plot
        latestNorms = handles.latest.normDelta;
        semilogy(latestNorms, '-*', 'Linewidth', 2)
        title('Norm of updates')
        xlabel('Number of iteration')
        
        if ( length(latestNorms) > 1 )
            skip = max(floor(length(latestNorms) / 5), 1);
            XTickVec = 1:skip:length(latestNorms);
            set(gca, 'XTick',  XTickVec)
            xlim([1 length(latestNorms)])
            grid on
        else % Don't display fractions on iteration plots
            set(gca, 'XTick',  1)
        end
        
    else % Show PLOTCOEFFS
        plotcoeffs(latestSolution, 'linewidth', 2)
        set(handles.popupmenu_bottomFig, 'Value', 2);
    end
    
elseif ( get(handles.button_pde, 'Value') )
    % We're in PDE mode.
    
    % Obtain solution and time range.
    u = handles.latest.solution;
    tt = handles.latest.solutionT;
    
    % Find out what our variables were called.
    varnames = handles.varnames;
    xLab = handles.indVarName{1};
    tLab = handles.indVarName{2};
    
    titleStr = sprintf('Solution at final time, %s = %f', tLab, tt(end));
    figure
    if ( ~iscell(u) )
        plot(u(:, end), 'Linewidth', 2)
        xlabel(xLab);
        ylabel(varnames);
        title(titleStr)
    else
        v = chebfun;
        for k = 1:numel(u)
            uk = u{k};
            v(:, k) = uk(:, end);
        end
        plot(v, 'Linewidth', 2);
        xlabel(xLab);
        legend(varnames);
        title(titleStr)
    end
    
    % Turn on grid
    if ( handles.guifile.options.grid )
        grid on
    end
    
    % Turn on fixed y-limits
    if ( ~isempty(handles.guifile.options.fixYaxisLower) )
        ylim([str2num(handles.guifile.options.fixYaxisLower) ...
            str2num(handles.guifile.options.fixYaxisUpper)]);
    end
    
    % Plot waterfall plots of the solution:
    if ( ~isa(u, 'chebmatrix') )
        figure
        waterfall(u, tt, 'simple')
        xlabel(xLab);
        ylabel(tLab);
        zlabel(varnames{1});
    else
        figure
        for k = 1:size(u, 1)
            subplot(1, size(u, 1), k);
            waterfall(u(k, :), tt)
            xlabel(xLab)
            ylabel(tLab)
            zlabel(varnames{k})
            title(varnames{k})
        end
        
        figure
        cols = get(0, 'DefaultAxesColorOrder');
        % Dummy plot to get legends right:
        for k = 1:size(u, 1)
            plot(0, NaN, 'linewidth', 2, 'color', cols(k, :))
            hold on
        end
        legend(varnames{:});
        % CHEBMATRIX/WATERFALL()
        waterfall(u, tt, 'edgecolors', cols)
        % Much pretty. Wow.
        view([322.5 30])
        box off
        grid on
    end
else
    figure
    h1 = gca;
    if ( strcmp(handles.latest.type, 'eig') )
        selection = get(handles.iter_list, 'Value');
        chebguiController.plotEigenmodes(handles, selection, h1, []);
    end
    
end

end

% --- Executes when chebguimainwindow is resized.
function chebguimainwindow_ResizeFcn(hObject, eventdata, handles)
% hObject    handle to chebguimainwindow (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
end

% --- Executes on button press in button_pde.
function button_pde_Callback(hObject, eventdata, handles)
% Switch to PDE mode.
handles = chebguiController.switchMode(handles, 'pde');
guidata(hObject, handles);

end

% --- Executes on button press in button_pde.
function button_eig_Callback(hObject, eventdata, handles)
% Switch to EIG mode.
handles = chebguiController.switchMode(handles, 'eig');
guidata(hObject,  handles);

end

% --- Executes on selection change in iter_list.
function iter_list_Callback(hObject, eventdata, handles)
% Called when user selects an eigenvalue from the list after solving.

% Developer note:
%   contents = cellstr(get(hObject, 'String')) returns iter_list contents as
%    cell array
%   contents{get(hObject, 'Value')} returns selected item from iter_list

% Selecting from the list only does something when we are in EIG mode. Display
% corresponding eigenfunctions when clicking on eigenvalues.

if ( strcmp(handles.latest.type, 'eig') )
    selection = get(handles.iter_list, 'Value');
    chebguiController.plotEigenmodes(handles, selection);
end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ------------------------- Other subfunctions ---------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ----------------------All CreateFcn are stored here --------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% DEVELOPER NOTE: Most of these are automatically created by MATLAB.

function dom_left_CreateFcn(hObject, eventdata, handles)
bgColorIsDefault = isequal(get(hObject, 'BackgroundColor'),  ...
    get(0, 'defaultUicontrolBackgroundColor'));
if ( ispc && bgColorIsDefault )
    set(hObject, 'BackgroundColor', 'white');
end
end

function dom_right_CreateFcn(hObject, eventdata, handles)
bgColorIsDefault = isequal(get(hObject, 'BackgroundColor'),  ...
    get(0, 'defaultUicontrolBackgroundColor'));
if ( ispc && bgColorIsDefault )
    set(hObject, 'BackgroundColor', 'white');
end
end

function iter_list_CreateFcn(hObject, eventdata, handles)
bgColorIsDefault = isequal(get(hObject, 'BackgroundColor'),  ...
    get(0, 'defaultUicontrolBackgroundColor'));
if ( ispc && bgColorIsDefault )
    set(hObject, 'BackgroundColor', 'white');
end
end

function tempedit_CreateFcn(hObject, eventdata, handles)
end

function ylim1_CreateFcn(hObject, eventdata, handles)
end

function ylim1_Callback(hObject, eventdata, handles)
end

function ylim2_CreateFcn(hObject, eventdata, handles)
end

function ylim2_Callback(hObject, eventdata, handles)
end

function button_solve_ButtonDownFcn(hObject, eventdata, handles)
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ---------------------- Right-clicking functions ------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% DEVELOPER NOTE: These methods will open the CHEBGUIEDIT sub-GUI


function editfontsize_CreateFcn(hObject, eventdata, handles)

bgColorIsDefault = isequal(get(hObject, 'BackgroundColor'),  ...
    get(0, 'defaultUicontrolBackgroundColor'));
if ( ispc && bgColorIsDefault )
    set(hObject, 'BackgroundColor', 'white');
end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ----------------------- Callbacks for menu items  ----------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



function menu_ivpSolver_Callback(hObject, eventdata, handles)
end

function menu_ivpGlobal_Callback(hObject, eventdata, handles)
end

function menu_ivpTimestepping_Callback(hObject, eventdata, handles)
end

function menu_ivpODE113_Callback(hObject, eventdata, handles)
set(handles.menu_ivpODE113, 'checked', 'on');
set(handles.menu_ivpODE15s, 'checked', 'off');
set(handles.menu_ivpODE45, 'checked', 'off');
set(handles.menu_ivpValues, 'checked', 'off');
set(handles.menu_ivpCoefficients, 'checked', 'off');
handles.guifile.options.ivpSolver = 'ode113';
set(handles.panel_IVPsolver,'SelectedObject', handles.button_timestepping)
set(handles.panel_initialGuess, 'Visible', 'off')
guidata(hObject, handles);
end

function menu_ivpODE15s_Callback(hObject, eventdata, handles)
set(handles.menu_ivpODE113, 'checked', 'off');
set(handles.menu_ivpODE15s, 'checked', 'on');
set(handles.menu_ivpODE45, 'checked', 'off');
set(handles.menu_ivpValues, 'checked', 'off');
set(handles.menu_ivpCoefficients, 'checked', 'off');
handles.guifile.options.ivpSolver = 'ode15s';
set(handles.panel_IVPsolver,'SelectedObject', handles.button_timestepping)
set(handles.panel_initialGuess, 'Visible', 'off')
guidata(hObject, handles);
end

function menu_ivpODE45_Callback(hObject, eventdata, handles)
set(handles.menu_ivpODE113, 'checked', 'off');
set(handles.menu_ivpODE15s, 'checked', 'off');
set(handles.menu_ivpODE45, 'checked', 'on');
set(handles.menu_ivpValues, 'checked', 'off');
set(handles.menu_ivpCoefficients, 'checked', 'off');
handles.guifile.options.ivpSolver = 'ode45';
set(handles.panel_IVPsolver,'SelectedObject', handles.button_timestepping)
set(handles.panel_initialGuess, 'Visible', 'off')
guidata(hObject, handles);
end

function menu_ivpValues_Callback(hObject, eventdata, handles)
set(handles.menu_ivpODE113, 'checked', 'off');
set(handles.menu_ivpODE15s, 'checked', 'off');
set(handles.menu_ivpODE45, 'checked', 'off');
set(handles.menu_ivpValues, 'checked', 'on');
set(handles.menu_ivpCoefficients, 'checked', 'off');
handles.guifile.options.ivpSolver = 'values';
set(handles.panel_IVPsolver,'SelectedObject', handles.button_global)
set(handles.panel_initialGuess, 'Visible', 'on')
guidata(hObject, handles);
end

function menu_ivpCoefficients_Callback(hObject, eventdata, handles)
set(handles.menu_ivpODE113, 'checked', 'off');
set(handles.menu_ivpODE15s, 'checked', 'off');
set(handles.menu_ivpODE45, 'checked', 'off');
set(handles.menu_ivpValues, 'checked', 'off');
set(handles.menu_ivpCoefficients, 'checked', 'on');
handles.guifile.options.ivpSolver = 'coeffs';
set(handles.panel_IVPsolver,'SelectedObject', handles.button_global)
set(handles.panel_initialGuess, 'Visible', 'on')
guidata(hObject, handles);
end

function menu_file_Callback(hObject, eventdata, handles)
end

function menu_opengui_Callback(hObject, eventdata, handles)
% Open a .guifile in the GUI

[filename, pathname, filterindex] = uigetfile('*.guifile', 'Pick a file');
if ( ~filterindex )
    return
end

cgTemp = chebgui(fullfile(pathname, filename));
chebguiController.populate(hObject, handles, cgTemp)
handles.guifile = cgTemp;
if ( ~isempty(cgTemp.type) )
    handles = chebguiController.switchMode(handles, cgTemp.type);
end

guidata(hObject, handles);

end


function menu_savegui_Callback(hObject, eventdata, handles)
% Save the current state of the GUI to a .guifile.

[filename, pathname, filterindex] = uiputfile('*.guifile', 'Pick a file');

if ( ~filterindex )
    return
end

% name = input('What would you like to name this GUI file? ');
name = '';

if ( get(handles.button_bvp, 'value') )
    demotype = 'bvp';
elseif ( get(handles.button_pde, 'value') )
    demotype = 'pde';
else
    demotype = 'eig';
end

% Extract all the needed info:
dom = get(handles.input_domain, 'string');
t = get(handles.input_timedomain, 'string');
DE = get(handles.input_DE, 'string');
BC = get(handles.input_BC, 'string');
LBC = get(handles.input_LBC, 'string');
RBC = get(handles.input_RBC, 'string');
init = get(handles.input_GUESS, 'string');
tol = '';
damping = '';
plotting = '';

DE = mycell2str(DE);
BC = mycell2str(BC);
LBC = mycell2str(LBC);
RBC = mycell2str(RBC);
init = mycell2str(init);

if ( strcmp(demotype, 'pde') )
    s = sprintf(['''%s''\n', ...
            'type = ''%s'';\n', ... 
            'domain = ''%s'';\n', ...
            't = ''%s'';\n', ...
            'DE = %s;\n', ...
            'LBC = %s;\n', ...
            'RBC = %s;\n', ...
            'init = %s;\n', ...
            'tol = ''%s'';\n', ...
            'damping = ''%s'';\n', ...
            'plotting = ''%s'';'], ...
    name, demotype, dom, t, DE, LBC, RBC, init, tol, damping, plotting);
else
    s = sprintf(['''%s''\n', ...
            'type = ''%s'';\n', ... 
            'domain = ''%s'';\n', ...
            'DE = %s;\n', ...
            'BC = %s;\n', ...
            'init = %s;\n', ...
            'tol = ''%s'';\n', ...
            'damping = ''%s'';\n', ...
            'plotting = ''%s'';'], ...
    name, demotype, dom, DE, BC, init, tol, damping, plotting);
end

% Write to a file:
fid = fopen(fullfile(pathname, filename), 'w+');
fprintf(fid, s);
fclose(fid);

end

function out = mycell2str(in)
% MYCELL2STR String manipulation, so that we can save to a .guifile.
isc = iscell(in);
if ( ~isc )
    in = {in};
    out = '';
else
    out = '{';
end

for k = 1:numel(in)
    if ( k > 1 )
        out = [out ' ; ']; %#ok<AGROW>
    end
    out = [out '''' strrep(in{k}, '''', '''''') '''']; %#ok<AGROW>
end

if ( isc )
    out = [out '}'];
end

end

function menu_demos_Callback(hObject, eventdata, handles)
end

function menu_help_Callback(hObject, eventdata, handles)
end

function menu_openhelp_Callback(hObject, eventdata, handles)
doc('chebgui')
end

function Untitled_9_Callback(hObject, eventdata, handles)
end

function menu_export_Callback(hObject, eventdata, handles)

% Offer more options if a solution exists.
if ( handles.hasSolution )
    set(handles.menu_exportmatfile, 'Enable', 'on')
    set(handles.menu_exportworkspace, 'Enable', 'on')
else
    set(handles.menu_exportmatfile, 'Enable', 'off')
    set(handles.menu_exportworkspace, 'Enable', 'off')
end

end

function menu_exportmfile_Callback(hObject, eventdata, handles)
% Call the button_export callback method to ensure they both do the same.
button_export_Callback(hObject, eventdata, handles)
end

function menu_exportchebgui_Callback(hObject, eventdata, handles)
% Call the export method of the CHEBGUIEXPORTER class:
chebguiExporter.toChebgui(handles.guifile)
end

function menu_exportworkspace_Callback(hObject, eventdata, handles)
% Create a CHEBGUIEXPORTER object of the correct type:
exporter = chebguiExporter.constructor(handles.guifile.type);
% Export the solution to the workspace
exporter.toWorkspace(handles);
end

function menu_exportmatfile_Callback(hObject, eventdata, handles)
% Create a CHEBGUIEXPORTER object of the correct type:
exporter = chebguiExporter.constructor(handles.guifile.type);
% Export the solution to the workspace
exporter.toMat(handles);
end

function menu_options_Callback(hObject, eventdata, handles)
end

function menu_close_Callback(hObject, eventdata, handles)
delete(handles.chebguimainwindow)
end

function mainWindow_DeleteFcn(hObject, eventdata, handles)
end

function tempedit_Callback(hObject, eventdata, handles)
end

function menu_odedampednewton_Callback(hObject, eventdata, handles)
end

function menu_odedampednewtonon_Callback(hObject, eventdata, handles)
% Turn on damped Newton iteration.
handles.guifile.options.damping = '1';
set(handles.menu_odedampednewtonon, 'checked', 'on');
set(handles.menu_odedampednewtonoff, 'checked', 'off');
guidata(hObject, handles);
end

function menu_odedampednewtonoff_Callback(hObject, eventdata, handles)
% Turn off damped Newton iteration.
handles.guifile.options.damping = '0';
set(handles.menu_odedampednewtonon, 'checked', 'off');
set(handles.menu_odedampednewtonoff, 'checked', 'on');
guidata(hObject, handles);
end

function menu_odeplotting_Callback(hObject, eventdata, handles)
end

function menu_pdeSolver_Callback(hObject, eventdata, handles)
end

function menu_pdeSolver_pde15s_Callback(hObject, eventdata, handles)
handles.guifile.options.pdeSolver = 'pde15s';
set(handles.menu_pdeSolver_pde15s, 'checked', 'on');
set(handles.menu_pdeSolver_pde23t, 'checked', 'off');
guidata(hObject, handles);
end

function menu_pdeSolver_pde23t_Callback(hObject, eventdata, handles)
handles.guifile.options.pdeSolver = 'pde23t';
set(handles.menu_pdeSolver_pde15s, 'checked', 'off');
set(handles.menu_pdeSolver_pde23t, 'checked', 'on');
guidata(hObject, handles);
end

function menu_pdeplotting_Callback(hObject, eventdata, handles)
end

function menu_odeplottingon_Callback(hObject, eventdata, handles)
% Turn on plotting.
handles.guifile.options.plotting = get(handles.menu_odeplottingpause, ...
    'UserData'); % Obtain length of pause from handles
set(handles.menu_odeplottingon, 'checked', 'on');
set(handles.menu_odeplottingoff, 'checked', 'off');
guidata(hObject, handles);
end

function menu_odeplottingoff_Callback(hObject, eventdata, handles)
% Turn off plotting.
handles.guifile.options.plotting = 'off'; % Should store plotting length
set(handles.menu_odeplottingon, 'checked', 'off');
set(handles.menu_odeplottingoff, 'checked', 'on');
guidata(hObject, handles)
end

function menu_odeplottingpause_Callback(hObject, eventdata, handles)
% Control the pause between plots during Newton iteration.
options.WindowStyle = 'modal';
valid = 0;
while ( ~valid )
    pauseInput = inputdlg('Length of pause between plots:', ...
        'Set pause length', 1, {get(hObject, 'UserData')}, options);
    if ( isempty(pauseInput) ) % User pressed cancel
        break
    elseif ( ~isempty(str2num(pauseInput{1})) ) % Valid input
        valid = 1;
        % Store new value in the UserData of the object
        set(hObject, 'UserData', pauseInput{1});
        % Update length of pause in the chebgui object
        handles.guifile.options.plotting = pauseInput{1};
        % Change the marking of the options
        set(handles.menu_odeplottingon, 'checked', 'on');
        set(handles.menu_odeplottingoff, 'checked', 'off');
    else
        f = errordlg('Invalid input.', 'Chebgui error', 'modal');
        uiwait(f); 
    end
end
guidata(hObject, handles)
end

function menu_plotOpt_Callback(hObject, eventdata, handles)
end

function menu_showgrid_Callback(hObject, eventdata, handles)
end

function menu_pdeholdplot_Callback(hObject, eventdata, handles)
end

function menu_pdefix_Callback(hObject, eventdata, handles)
end

function menu_pdeplotfield_Callback(hObject, eventdata, handles)
end

function menu_pdeholdploton_Callback(hObject, eventdata, handles)
% Turn on holding on of previous solutions while solving PDEs.
handles.guifile.options.pdeholdplot = 1; % Turn holding off
set(handles.menu_pdeholdploton, 'checked', 'on');
set(handles.menu_pdeholdplotoff, 'checked', 'off');
guidata(hObject, handles);
end

function menu_pdeholdplotoff_Callback(hObject, eventdata, handles)
% Turn off holding on of previous solutions while solving PDEs.
handles.guifile.options.pdeholdplot = 0; % Turn holding off
set(handles.menu_pdeholdploton, 'checked', 'off');
set(handles.menu_pdeholdplotoff, 'checked', 'on');
guidata(hObject, handles);
end

function menu_pdeplottingon_Callback(hObject, eventdata, handles)
handles.guifile.options.plotting = 'on'; % Obtain length of pause from handles
set(handles.menu_pdeplottingon, 'checked', 'on');
set(handles.menu_pdeplottingoff, 'checked', 'off');
guidata(hObject, handles);
end

function menu_pdeplottingoff_Callback(hObject, eventdata, handles)
handles.guifile.options.plotting = 'off'; % Obtain length of pause from handles
set(handles.menu_pdeplottingon, 'checked', 'off');
set(handles.menu_pdeplottingoff, 'checked', 'on');
guidata(hObject, handles);
end

function menu_tolerance_Callback(hObject, eventdata, handles)
% Called when the user inputs tolerance.
options.WindowStyle = 'modal';
valid = 0;
while ( ~valid )
    tolInput = inputdlg('Tolerance for solution:', 'Set tolerance', ...
        1, {get(hObject, 'UserData')}, options);
    if ( isempty(tolInput) ) % User pressed cancel
        break
    elseif ( ~isempty(str2num(tolInput{1})) ) % Valid input
        valid = 1;
        % Store new value in the UserData of the object
        set(hObject, 'UserData', tolInput{1});
        % Update the chebgui object
        handles.guifile.tol = tolInput{1};
    else
        f = errordlg('Invalid input.', 'Chebgui error', 'modal');
        uiwait(f); 
    end
end
guidata(hObject, handles)
end

function check_uselatest_Callback(hObject, eventdata, handles)
end

function menu_showgridon_Callback(hObject, eventdata, handles)
% Show grid on figures.
handles.guifile.options.grid = 1; % Turn grid on
set(handles.menu_showgridon, 'checked', 'on');
set(handles.menu_showgridoff, 'checked', 'off');
axes(handles.fig_sol);
grid on
axes(handles.fig_norm);
grid on
guidata(hObject, handles);
end

function menu_showgridoff_Callback(hObject, eventdata, handles)
% Don't show grid on figures.
handles.guifile.options.grid = 0; % Turn grid off
set(handles.menu_showgridon, 'checked', 'off');
set(handles.menu_showgridoff, 'checked', 'on');
axes(handles.fig_sol);
grid off
axes(handles.fig_norm);
grid off
guidata(hObject, handles);
end

function menu_fixN_Callback(hObject, eventdata, handles)
end

function menu_annotateplots_Callback(hObject, eventdata, handles)
end

function menu_pdefixon_Callback(hObject, eventdata, handles)
% Fix lower and upper y-lims of plot when solving PDEs.
options.WindowStyle = 'modal';
valid = 0;
defaultAnswer = {handles.guifile.options.fixYaxisLower, ...
    handles.guifile.options.fixYaxisUpper};
while ( ~valid )
    fixInput = inputdlg({'Lower y-limit:', 'Upper y-limit:'}, 'Fix y-axis', ...
        1, defaultAnswer, options);
    if ( isempty(fixInput) ) % User pressed cancel
        break
    elseif ( ~isempty(str2num(fixInput{1})) && ...
             ~isempty(str2num(fixInput{2})) ) % Valid input
        valid = 1;
        % Store new value in the UserData of the object
        set(hObject, 'UserData', fixInput);
        % Update the chebgui object
        handles.guifile.options.fixYaxisLower = fixInput{1};
        handles.guifile.options.fixYaxisUpper = fixInput{2};
    else
        f = errordlg('Invalid input.', 'Chebgui error', 'modal');
        uiwait(f); 
    end
end

% Change checking
set(handles.menu_pdefixon, 'checked', 'on');
set(handles.menu_pdefixoff, 'checked', 'off');
guidata(hObject, handles);

end

function menu_pdefixoff_Callback(hObject, eventdata, handles)
% Don't fix y-lims when solving PDEs.
% Clear out fix information
handles.guifile.options.fixYaxisLower = '';
handles.guifile.options.fixYaxisUpper = '';
% Change checking
set(handles.menu_pdefixon, 'checked', 'off');
set(handles.menu_pdefixoff, 'checked', 'on');
guidata(hObject, handles);
end

function sigma_Callback(hObject, eventdata, handles)
end

function sigma_CreateFcn(hObject, eventdata, handles)
bgColorIsDefault = isequal(get(hObject, 'BackgroundColor'), ...
    get(0, 'defaultUicontrolBackgroundColor'));
if ( ispc && bgColorIsDefault )
    set(hObject, 'BackgroundColor', 'white');
end
end

function button_export_Callback(hObject, eventdata, handles)

    % What discretization do we want to use?
    if ( get(handles.button_discretization_values, 'Value') )
        handles.guifile.options.discretization = 'values';
    else
        handles.guifile.options.discretization = 'coeffs';
    end

    % Create a CHEBGUIEXPORTER object of the correct type:
    exporter = chebguiExporter.constructor(handles.guifile.type);    
    % Call the export method of the E object:
    try
        [fileName, pathName] = uiputfile( ...
            {'*.m', 'M-files (*.m)'; '*.*',  'All Files (*.*)'}, ...
            'Save as', exporter.defaultFileName);
        if ( fileName ~= 0 )     % User did not press cancel
            toFile(exporter, handles.guifile, fileName, pathName)
            
            % Open the new file in the editor
            open([pathName, fileName])
        end

    catch ME
        % TODO: Which error do we want to throw?
        error('CHEBFUN:chebguiWindow:export', ...
            ['Error in exporting to .m file. Please make ' ...
            'sure there are no syntax errors.']);
    end
end

function button_realplot_Callback(hObject, eventdata, handles)
% We want to show the real part of eigenfunctions.
set(handles.button_realplot, 'Value', 1)
set(handles.button_imagplot, 'Value', 0)
selection = get(handles.iter_list, 'Value');
chebguiController.plotEigenmodes(handles, selection)
end

function button_imagplot_Callback(hObject, eventdata, handles)
% We want to show the imaginary part of eigenfunctions.
set(handles.button_realplot, 'Value', 0)
set(handles.button_imagplot, 'Value', 1)
selection = get(handles.iter_list, 'Value');
chebguiController.plotEigenmodes(handles, selection)
end

function menu_fixNon_Callback(hObject, eventdata, handles)
% Fix spatial discretization when solving PDEs.
options.WindowStyle = 'modal';
valid = 0;
defaultAnswer = {handles.guifile.options.fixN};
while ( ~valid )
    fixInput = inputdlg({'Number of gridpoints:'}, ...
        'Fix space discretisation', 1, defaultAnswer, options);
    if ( isempty(fixInput) ) % User pressed cancel
        break
    elseif ( ~mod(str2num(fixInput{1}), 1) ) % Only allow integers
        valid = 1;
        % Store new value in the UserData of the object
        set(hObject, 'UserData', fixInput);
        % Update the chebgui object
        handles.guifile.options.fixN = fixInput{1};
    else
        f = errordlg('Invalid input.', 'Chebgui error', 'modal');
        uiwait(f); 
    end
end
% Change checking
set(handles.menu_fixNon, 'checked', 'on');
set(handles.menu_fixNoff, 'checked', 'off');
guidata(hObject, handles);
end

function menu_fixNoff_Callback(hObject, eventdata, handles)
% Don't fix spatical discretizations when solving PDEs.
handles.guifile.options.fixN = '';
% Change checking
set(handles.menu_fixNon, 'checked', 'off');
set(handles.menu_fixNoff, 'checked', 'on');
guidata(hObject, handles);
end

function menu_import_Callback(hObject, eventdata, handles)
% Import variables from the workspace to the scope of CHEBGUI

% Obtain a 'whos' list from the base workspace
variables =  evalin('base', 'whos');
baseVarNames = {variables.name};

% Create a list dialog
[selection, OK] = listdlg('PromptString', 'Select variable(s) to import:', ...
    'ListString', baseVarNames, 'Name', 'Import variables to GUI', ...
    'OKString', 'Import', 'ListSize', [160 200], 'ListString', baseVarNames);

if ( ~OK ) % User pressed cancel
    return
end

% Store all the selected variables in the handles
for selCounter = 1:length(selection)
    handles.importedVar.(baseVarNames{selection(selCounter)}) = ...
        evalin('base', baseVarNames{selection(selCounter)});
end

guidata(hObject, handles);

end

function menu_eigssystem_Callback(hObject, eventdata, handles)
end

% Executes on key press with focus on chebguimainwindow and none of its controls.
function chebguimainwindow_KeyPressFcn(hObject, eventdata, handles)
% hObject    handle to chebguimainwindow (see GCBO)
% eventdata  structure with the following fields (see FIGURE)
%	Key: name of the key that was pressed, in lower case
%	Character: character interpretation of the key(s) that was pressed
%	Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed
% handles    structure with handles and user data (see GUIDATA)
edata = eventdata;
if ( ~isempty(edata.Modifier) && strcmp(edata.Modifier{1}, 'control') )
    switch ( edata.Key )
        case 'return'
            button_solve_Callback(hObject, eventdata, handles);
        case 'e'
            button_export_Callback(hObject, eventdata, handles);
        case {'+', 'equal'}
            button_fontinc_Callback(hObject, eventdata, handles);
        case {'-', 'hyphen'}
            button_fontdec_Callback(hObject, eventdata, handles);
        case 'p'
            if ( any(strcmp(get(handles.button_clear, 'String'), ...
                    {'Pause', 'Continue'})) )
                button_clear_Callback(hObject, eventdata, handles);
            end
    end
end
% PressedKeyNo = double(get(gcbo, 'CurrentCharacter'))
end

function edit37_CreateFcn(hObject, eventdata, handles)
bgColorIsDefault = isequal(get(hObject, 'BackgroundColor'),  ...
    get(0, 'defaultUicontrolBackgroundColor'));
if ( ispc && bgColorIsDefault )
    set(hObject, 'BackgroundColor', 'white');
end
end

function edit37_Callback(hObject, eventdata, handles)
in = get(handles.edit_eigN, 'String');
if ( ~isempty(in) && isempty(str2num(in)) )
    errordlg('Invalid input.', 'Chebgui error', 'modal');
else
    handles.guifile.options.numeigs = in;
end
guidata(hObject, handles);
end

function menu_annotateon_Callback(hObject, eventdata, handles)
end

function menu_annotateoff_Callback(hObject, eventdata, handles)
end

function menu_about_Callback(hObject, eventdata, handles)
% The about information display.
aboutWindow = dialog('WindowStyle', 'normal', 'Name', 'About chebgui', ...
    'Position', [500 500 200 200]);
aboutString = sprintf(['Chebgui was developed by Asgeir Birkisson and Nick ' ...
    'Hale as an interface to the differential equations in Chebfun.']);
uicontrol(aboutWindow, ... % Text
             'Style', 'text', ...
             'String', aboutString, ...
             'position', [0 -90 200 200])
uicontrol(aboutWindow, ... % Close button
             'Style', 'pushbutton', 'String', 'Close', 'position', ...
             [65 10 75 20], 'callback', @(a, b, c) delete(aboutWindow))

hPlotAxes = axes(...       % Axes for plotting the selected plot
                 'Parent', aboutWindow, ...
                 'Units', 'normalized', ...
                 'HandleVisibility', 'callback', 'position', [0.1 0.6 .8 .25]);

% Plot the logo
f = chebpoly(10);
xx = linspace(-1, .957, 1000);
plot(hPlotAxes, xx, f(xx), 'linewidth', 3)
t = -cos(pi*(2:8)'/10) *0.99;  % cheb extrema (tweaked)
y = 0*t;
h = text(t, y, num2cell(transpose('chebgui')), ...
    'fontsize', 16, 'hor', 'cen', 'vert', 'mid', 'parent', hPlotAxes);
flist = listfonts;
k = strmatch('Rockwell', flist);        % 1st choice
k = [k; strmatch('Luxi Serif', flist)]; % 2nd choice
k = [k; strmatch('luxiserif', flist)];  % 2.5th choice
k = [k; strmatch('Times', flist)];      % 3rd choice

if ( ~isempty(k) )
    set(h, 'fontname', flist{k(1)})
end

axis(hPlotAxes, 'off')

end

function menu_shortcuts_Callback(hObject, eventdata, handles)
% hObject    handle to menu_shortcuts (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
aboutWindow = dialog('WindowStyle', 'normal', 'Name', 'About chebgui', ...
    'Position', [500 500 200 275]);
aboutString = sprintf(['The following keyboard shortcuts are supported ' ...
    '(case insensitive):\n', ...
    'Ctrl + Return = Solve\n', ...
    'Ctrl + P = Pause\n', ...
    'Ctrl + E = Export to .m file\n', ...
    'Ctrl + + = Increase font-size\n', ...
    'Ctrl + - = Decrease font-size',    ]);
uicontrol(aboutWindow, ... % Text
             'Style', 'text', ...
             'String', aboutString, ...
             'position', [0 -40 200 200])
uicontrol(aboutWindow, ... % Close button
             'Style', 'pushbutton', 'String',  'Close', 'position', ...
             [65 10 75 20], 'callback', @(a, b, c) delete(aboutWindow))

hPlotAxes = axes(...       % Axes for plotting the selected plot
                 'Parent', aboutWindow, ...
                 'Units', 'normalized', ...
                 'HandleVisibility', 'callback', 'position', [0.1 0.6 .8 .25]);

% Plot the logo
f = chebpoly(10);
xx = linspace(-1, .957, 1000);
plot(hPlotAxes, xx, f(xx), 'linewidth', 3)
t = -cos(pi*(2:8)'/10) *0.99;  % cheb extrema (tweaked)
y = 0*t;
h = text(t, y, num2cell(transpose('chebgui')), ...
    'fontsize', 16, 'hor', 'cen', 'vert', 'mid', 'parent', hPlotAxes);
flist = listfonts;
k = strmatch('Rockwell', flist);  % 1st choice
k = [k; strmatch('Luxi Serif', flist)];  % 2nd choice
k = [k; strmatch('luxiserif', flist)];  % 2.5th choice
k = [k; strmatch('Times', flist)];  % 3rd choice

if ( ~isempty(k) )
    set(h, 'fontname', flist{k(1)})
end

axis(hPlotAxes, 'off')

end

function msg = cleanErrorMsg(msg)
errUsingLoc = strfind(msg, sprintf('Error using'));
if ( errUsingLoc )
    % Trim everything before this
    msg = msg(errUsingLoc:end);
    % Look for first two line breaks (char(10))
    idx = find(msg == char(10), 1);
    % Take only what's after the 2nd
    msg = msg(idx+1:end);
end
end

function button_exportsoln_Callback(hObject, eventdata, handles)
% Create a CHEBGUIEXPORTER object of the correct type:
exporter = chebguiExporter.constructor(handles.guifile.type);
% Export the solution to the workspace
exporter.toWorkspaceSolutionOnly(handles);
end

function button_fontinc_Callback(hObject, eventdata, handles)
handles = chebguiController.changeFontsize(handles, 1);
guidata(hObject, handles);
end

function button_fontdec_Callback(hObject, eventdata, handles)
handles = chebguiController.changeFontsize(handles, -1);
guidata(hObject, handles);
end

function keypress(hObject, eventdata, handles)
newString = cellstr(get(hObject, 'String'));
newString = removeTabs(newString); % Remove tabs
set(hObject, 'String', newString);
handles = chebguiController.callbackBCs(handles,  newString, 'rbc');
handles.guifile.RBC = newString;
guidata(hObject, handles);
end

function menu_test_Callback(hObject, eventdata, handles)
% Try running all CHEBGUI demos.
T = 0;
folders = {'bvpdemos', 'pdedemos', 'eigdemos'};
for k = 1:numel(folders)
    subdir = fullfile(chebfunroot(), '@chebgui', 'private', folders{k});
    subdirlist = dir(subdir);
    subdirnames = { subdirlist.name };
    fprintf([folders{k}(1:3) , '\n']);

    for j = 1:length(subdirnames)
        if ( subdirlist(j).isdir )
            continue;
        end

        file = fullfile(subdir, subdirnames{j});
        cgTemp = chebgui(file);
        chebguiController.populate(hObject, handles, cgTemp)
        handles.guifile = cgTemp;
        if ( ~isempty(cgTemp.type) )
            handles = chebguiController.switchMode(handles, cgTemp.type);
        end    

        handles.hasSolution = 0;
        name = subdirnames{j};
        name = strrep(name, '.guifile', '');
        fprintf(['  ' , name]);
        try 
            tic
            handles = solveGUI(handles.guifile, handles);
            t = toc;
            guidata(hObject, handles);
            T = T + t;
            if ( ~handles.hasSolution )
                try
                   close('Chebgui error')
                catch
                    %
                end
                error('CHEBFUN:chebguiWindow:noSol', 'No solution returned.');
            end
            fprintf('  passed in %4.4f seconds.\n', t);
        catch ME
            try
                close('Chebgui error')
            catch
                %
            end
            fprintf('  FAILED.\n');
        end
    end
end

fprintf('TOTAL TIME = %4.4f.\n', T);

end

function menu_debug_Callback(hObject, eventdata, handles)
% hObject    handle to menu_debug (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
if ( strcmp(get(handles.menu_debug, 'checked'), 'on') )
    set(handles.menu_debug, 'checked', 'off');
    set(handles.menu_debug, 'UserData', 0);
else
    set(handles.menu_debug, 'checked', 'on');
    set(handles.menu_debug, 'UserData', 1);
end
guidata(hObject, handles);
end

function resetComponents(handles)
% Enable buttons, figures, etc. Set button to 'solve' again
set(handles.button_solve, 'String', 'Solve');
set(handles.button_solve, 'BackgroundColor', [43 129 86]/256);
set(handles.button_clear, 'String', 'Clear all');
set(handles.button_clear, 'BackgroundColor', ...
    get(handles.button_export, 'BackgroundColor'));
set(handles.button_figsol, 'Enable', 'on');
set(handles.button_exportsoln, 'Enable', 'off');
set(handles.menu_demos, 'Enable', 'on');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function popupmenu_bottomFig_Callback(hObject, eventdata, handles)
% hObject    handle to popupmenu_bottomFig (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% DEVELOPER NOTE:
%   contents = cellstr(get(hObject, 'String')) returns popupmenu_bottomFig 
%       contents as cell array
%   contents{get(hObject, 'Value')} returns selected item from
%       popupmenu_bottomFig

% We should not be able to call this method without solution being available, 
% but let's be on the safe side.
if ( ~handles.hasSolution )
    return
end

newVal = get(hObject, 'Value');
axes(handles.fig_norm)            
switch ( newVal )
    case 1
        % User wants to see a plot showing the convergence of the Newton
        % iteration.
        normDelta = handles.latest.normDelta;

        % If normDelta is empty, we actually had a linear problem! So don't
        % do anything.
        if ( isempty(normDelta) )
            warndlg(['Problem was linear. Convergence information for' ...
                ' Newton iteration is not available.'], 'Linear problem');
            set(handles.popupmenu_bottomFig, 'Value', 2);
            return
        end

        semilogy(normDelta, '-*', 'Linewidth', 2)
        set(handles.panel_figNorm, 'title', 'Norm of updates');

        if ( length(normDelta) > 1 )
            step = max(floor(length(normDelta)/5), 1);
            XTickVec = 1:step:length(normDelta);
            set(gca, 'XTick', XTickVec)
            xlim([1 length(normDelta)])
            grid on
        else % Don't display fractions on iteration plots
            set(gca, 'XTick',  1)
        end
        
    case 2
        % User wants to see a PLOTCOEFFS plot..
        plotcoeffs(handles.latest.solution, 'linewidth', 2);
        plotCoeffsTitle = get(get(handles.fig_norm, 'title'), 'String');
        set(handles.panel_figNorm, 'title', plotCoeffsTitle);
        title('');
        % Hide the automatic y-label as it causes issues when fontsize is too big
        ylabel('');
        xlabel('');
end

end

function popupmenu_bottomFig_CreateFcn(hObject, eventdata, handles)
% hObject    handle to popupmenu_bottomFig (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
bgColorIsDefault = isequal(get(hObject, 'BackgroundColor'), ...
    get(0, 'defaultUicontrolBackgroundColor'));
if ( ispc && bgColorIsDefault )
    set(hObject, 'BackgroundColor', 'white');
end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FIN %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
