classdef GUIDEAppMaintenanceOptions < matlab.apps.AppBase
    %GUIDEAPPMAINTENANCEOPTIONS Explore options for the maintenance of
    %GUIDE Apps after GUIDE is removed.
    %   Options for app maintenance include Export to a MATLAB File and
    %   Migrating to an App Designer app.
    %   
    %   Copyright 2020-2021 The MathWorks, Inc.

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                     matlab.ui.Figure
        TabGroup                     matlab.ui.container.TabGroup
        MigrateTab                   matlab.ui.container.Tab
        MigrateImage                 matlab.ui.control.Image
        MigrateHeader                matlab.ui.control.Label
        MigrateReasonsLabel          matlab.ui.control.Label
        MigrateHtmlBullets           matlab.ui.control.HTML
        ExportTab                    matlab.ui.container.Tab
        ExportImage                  matlab.ui.control.Image
        ExportHeader                 matlab.ui.control.Label
        ExportReasonsLabel           matlab.ui.control.Label
        ExportHtmlBullets            matlab.ui.control.HTML
        ExportChooseAppLabel         matlab.ui.control.Label
        ExportEditField              matlab.ui.control.EditField
        ExportBrowseButton           matlab.ui.control.Button
        ExportButton                 matlab.ui.control.Button
        MigrateChooseAppLabel        matlab.ui.control.Label
        MigrateEditField             matlab.ui.control.EditField
        MigrateBrowseButton          matlab.ui.control.Button
        MigrateButton                matlab.ui.control.Button
        WarningImageLarge            matlab.ui.control.Image
        InstallLabel_RegularText     matlab.ui.control.Label
        InstallLabel_ItalicsText     matlab.ui.control.Label
        InstallSupportPackageButton  matlab.ui.control.Button
        HelpButton                   matlab.ui.control.Button
        CancelButton                 matlab.ui.control.Button
    end


    properties (Access = private)
        ExportAppName
        ExportAppFullFileName
        MigrateAppName
        MigrateAppFullFileName
    end

    methods (Access = private)

        function  setupApp(app)
            
            import matlab.internal.lang.capability.Capability;
            
            % Move the UIFigure to the center of the screen.
            if Capability.isSupported(Capability.LocalClient)
                % movegui is not fully supported in MATLAB Online (g1946357)
                movegui(app.UIFigure, 'center');
            end

            app.ExportImage.ImageSource = '+guide/+internal/ExportToMATLAB.png';
            app.MigrateImage.ImageSource = '+guide/+internal/MigrateToAppDesigner.png';
            app.WarningImageLarge.ImageSource =  '+guide/+internal/info.svg';
            
            app.assignInternationalizedStrings();
            drawnow;

            % If the Migration AddOn is installed, setup components to give
            % users options to migrate.  If it is not installed, setup components
            % that prompt users to install it.
            if appdesservices.internal.appmigration.isGUIDEAppMigrationAddonInstalled()
                app.setupMigrateTabActionComponents();
            else
                app.setupMigrateTabInstallComponents();
            end

            % Set initial placeholder text in the export and migrate edit
            % fields.
            app.ExportEditField.Value = getString(message('MATLAB:guide:SelectFigFile'));
            app.MigrateEditField.Value = getString(message('MATLAB:guide:SelectFigFile'));    
        end
        
        function enableExportEditFieldAndActionButton(app)
            % Enable the export edit field and enable the export button.

            app.ExportEditField.Enable = 'on';
            app.ExportEditField.FontAngle = 'normal';
            app.ExportButton.Enable = 'on';
        end

        function disableExportEditFieldAndActionButton(app)
            % Disable the export edit field and disable the export button.

            app.ExportEditField.Enable = 'off';
            app.ExportEditField.Value = getString(message('MATLAB:guide:SelectFigFile'));
            app.ExportEditField.FontAngle = 'italic';
            app.ExportButton.Enable = 'off';
        end

        function enableMigrateEditFieldAndActionButton(app)
            % Enable the migrate edit field and enable the migrate button.

            app.MigrateEditField.Enable = 'on';
            app.MigrateEditField.FontAngle = 'normal';
            app.MigrateButton.Enable = 'on';
        end

        function disableMigrateEditFieldAndActionButton(app)
            % Disable the migrate edit field and disable the migrate button.

            app.MigrateEditField.Enable = 'off';
            app.MigrateEditField.Value = getString(message('MATLAB:guide:SelectFigFile'));
            app.MigrateEditField.FontAngle = 'italic';
            app.MigrateButton.Enable = 'off';
        end

        function  setupMigrateTabInstallComponents(app)
            % Setup the components that tell users that the support package
            % is not installed and prompt them to install it.

            % Reparent the appropriate components into the migrate tab.
            app.WarningImageLarge.Parent = app.MigrateTab;
            app.InstallSupportPackageButton.Parent = app.MigrateTab;
            app.InstallLabel_ItalicsText.Parent = app.MigrateTab;
            app.InstallLabel_RegularText.Parent = app.MigrateTab;

            % After components are reparented, a position shift is used in
            % order to properly align the components in the Migrate Tab.
            postionShift = [0,197,0,0];

            % Align the components in the tab.
            app.WarningImageLarge.Position = app.WarningImageLarge.Position + postionShift;
            app.InstallSupportPackageButton.Position = app.InstallSupportPackageButton.Position + postionShift;
            app.InstallLabel_ItalicsText.Position = app.InstallLabel_ItalicsText.Position + postionShift;
            app.InstallLabel_RegularText.Position = app.InstallLabel_RegularText.Position + postionShift;
        end

        function  setupMigrateTabActionComponents(app)
            % Setup the components that allow users to select a GUIDE
            % FIG file and to migrate that FIG file.

            % Reparent the appropriate components into the migrate tab.
            app.MigrateChooseAppLabel.Parent = app.MigrateTab;
            app.MigrateEditField.Parent = app.MigrateTab;
            app.MigrateBrowseButton.Parent = app.MigrateTab;
            app.MigrateButton.Parent = app.MigrateTab;

            % After components are reparented, a position shift is used in
            % order to properly align the components in the Migrate Tab.
            postionShift = [0,310,0,0];

            % Align the components in the tab.
            app.MigrateChooseAppLabel.Position = app.MigrateChooseAppLabel.Position + postionShift;
            app.MigrateEditField.Position = app.MigrateEditField.Position + postionShift;
            app.MigrateBrowseButton.Position = app.MigrateBrowseButton.Position + postionShift;
            app.MigrateButton.Position = app.MigrateButton.Position + postionShift;
        end
        
        function assignInternationalizedStrings(app)
            % This method is used to assign internationalized strings to
            % the text in the app.  See g2405656
            
            app.MigrateTab.Title = getString(message('MATLAB:guide:guideremovaloptions:MigrateTab'));
            app.ExportTab.Title = getString(message('MATLAB:guide:guideremovaloptions:ExportTab'));
            app.MigrateHeader.Text = getString(message('MATLAB:guide:guideremovaloptions:MigrateHeader'));
            app.ExportHeader.Text = getString(message('MATLAB:guide:guideremovaloptions:ExportHeader'));
            app.MigrateReasonsLabel.Text = getString(message('MATLAB:guide:guideremovaloptions:MigrateReasonsLabel'));
            app.ExportReasonsLabel.Text = getString(message('MATLAB:guide:guideremovaloptions:ExportReasonsLabel'));
            app.MigrateHtmlBullets.HTMLSource =['<ul style="font-size: 12px; font-family: Helvetica; padding-left: 18px;user-select: none;"><li>', ...
                getString(message('MATLAB:guide:guideremovaloptions:MigrateHtmlBullet1')),...
                '</li><li>',...
                getString(message('MATLAB:guide:guideremovaloptions:MigrateHtmlBullet2')),...
                '</li></ul>'];
            app.ExportHtmlBullets.HTMLSource =['<ul style="font-size: 12px; font-family: Helvetica; padding-left: 18px;user-select: none;"><li>', ...
                getString(message('MATLAB:guide:guideremovaloptions:ExportHtmlBullet1')),...
                '</li><li>',...
                getString(message('MATLAB:guide:guideremovaloptions:ExportHtmlBullet2')),...
                '</li></ul>'];
            app.ExportChooseAppLabel.Text = getString(message('MATLAB:guide:guideremovaloptions:ExportChooseAppLabel'));
            app.MigrateChooseAppLabel.Text = getString(message('MATLAB:guide:guideremovaloptions:MigrateChooseAppLabel'));
            app.InstallSupportPackageButton.Text = getString(message('MATLAB:guide:guideremovaloptions:InstallSupportPackageButton'));
            app.ExportEditField.Value = getString(message('MATLAB:guide:guideremovaloptions:EditFieldPlaceholderText'));
            app.MigrateEditField.Value = getString(message('MATLAB:guide:guideremovaloptions:EditFieldPlaceholderText'));
            app.ExportButton.Text = getString(message('MATLAB:guide:guideremovaloptions:ExportButton'));
            app.MigrateButton.Text = getString(message('MATLAB:guide:guideremovaloptions:MigrateButton'));
            app.ExportBrowseButton.Text = getString(message('MATLAB:guide:guideremovaloptions:BrowseButtonText'));
            app.MigrateBrowseButton.Text = getString(message('MATLAB:guide:guideremovaloptions:BrowseButtonText'));
            app.HelpButton.Text = getString(message('MATLAB:guide:guideremovaloptions:HelpButton'));
            app.CancelButton.Text = getString(message('MATLAB:guide:guideremovaloptions:CancelButton'));
            app.InstallLabel_RegularText.Text = getString(message('MATLAB:guide:guideremovaloptions:InstallLabel_RegularText'));
            app.InstallLabel_ItalicsText.Text = getString(message('MATLAB:guide:guideremovaloptions:InstallLabel_ItalicsText'));
            
        end
    end
    
    methods
        function configureApp(app, varargin)
            % Configures the selected tab and the edit field text based on
            % varargin.  This must be a public method so that the external
            % function launchGUIDEAppMaintenanceOptions.m can call this.
            
            % If a FIG file was inputted as an argument, then pre-populate 
            % the edit fields and enable the buttons.
            if nargin > 1 && ~isempty(varargin{1})
                figFullFileName = varargin{1};
                app.ExportEditField.Value = figFullFileName;
                app.MigrateEditField.Value = figFullFileName;
                app.enableExportEditFieldAndActionButton();
                app.enableMigrateEditFieldAndActionButton();
            end

            % The migrate tab should be selected by default.
            app.TabGroup.SelectedTab = app.MigrateTab;

            % A second input argument is used to specify which
            % tab is opened by default.  If a second argument was specified,
            % check if the input contains the phrase 'export' (this phrase covers
            % inputs of both 'export' or 'exportation').  If the input contains
            % the phrase, set the opened tab to the Export Tab.
            if nargin >2 && ~isempty(varargin{2}) && contains(varargin{2},'export','IgnoreCase',true)
                app.TabGroup.SelectedTab = app.ExportTab;
            end
        end
    end

    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app, varargin)
            % Turn UIFigure Visibility 'off' during setup and
            % configuration.
            app.UIFigure.Visible = 'off';

            setupApp(app)
            configureApp(app, varargin{:});
            
            % After setup and configuration, make the UIFigure Visible.
            app.UIFigure.Visible = 'on';
        end

        % Button pushed function: MigrateBrowseButton
        function MigrateBrowseButtonPushed(app, event)
            [filename, pathname] = uigetfile('*.fig', getString(message('MATLAB:guide:SelectFigFile')));

            % Workaround uigetfile focus issue (g1598963) by forcing focus back to app
            figure(app.UIFigure);

            fullFileName = fullfile(pathname, filename);

            if ~isequal(filename, 0)
                app.MigrateEditField.Value = fullFileName;
                app.enableMigrateEditFieldAndActionButton();
            end

            app.MigrateAppName = filename;
            app.MigrateAppFullFileName = fullFileName;
        end

        % Button pushed function: ExportBrowseButton
        function ExportBrowseButtonPushed(app, event)
            [filename, pathname] = uigetfile('*.fig', getString(message('MATLAB:guide:SelectFigFile')));

            % Workaround uigetfile focus issue (g1598963) by forcing focus back to app
            figure(app.UIFigure);

            fullFileName = fullfile(pathname, filename);
            if ~isequal(filename, 0)
                app.ExportEditField.Value = fullFileName;
                app.enableExportEditFieldAndActionButton();
            end

            app.ExportAppName = filename;
            app.ExportAppFullFileName = fullFileName;
        end

        % Button pushed function: ExportButton
        function ExportButtonPushed(app, event)

            % Check if user edited the file name after loading a file using browse
            editFieldValue = app.ExportEditField.Value;

            % Update app name and fullfilename with edit field value
            [~, fileName] = fileparts(editFieldValue);
            app.ExportAppName = fileName;
            app.ExportAppFullFileName = editFieldValue;

            try 
                % Export the GUIDE App
                export.internal.exportGUIDEApp(app.ExportAppFullFileName)
                
            catch exception
                knownExceptionIdentifiers = {'appmigration:appmigration:InvalidFileName',...
                    'appmigration:appmigration:InvalidCodeFileName',...
                    'appmigration:appmigration:NotGuideCreatedApp',...
                    'appmigration:appmigration:NotWritableLocation',...
                    'MATLAB:appdesigner:appdesigner:InvalidInput',...
                    'MATLAB:appdesigner:appdesigner:FileNameFailsIsKeyword',...
                    'MATLAB:appdesigner:appdesigner:FileNameFailsIsVarName',...
                    'MATLAB:appdesigner:appdesigner:InvalidGeneralFileExtension',...
                    'MATLAB:appdesigner:appdesigner:InvalidFilePath'};

                if any(strcmp(exception.identifier,knownExceptionIdentifiers))
                    title = getString(message('MATLAB:guide:guideremovaloptions:ExportAlertTitle'));
                    uialert(app.UIFigure,exception.message,title);
                    return;
                else
                    rethrow(exception);
                end
            end

        end

        % Button pushed function: MigrateButton
        function MigrateButtonPushed(app, event)

            % Check if user edited the file name after loading a file using browse
            editFieldValue = app.MigrateEditField.Value;

            % update app name and fullfilename with edit field value
            [~, fileName] = fileparts(editFieldValue);
            app.MigrateAppName = fileName;
            app.MigrateAppFullFileName = editFieldValue;

            try
                converter = appmigration.internal.GUIDEAppConverter(app.MigrateAppFullFileName);

                progressDialogMessage = getString(message('appmigration:appmigration:ProgressDialogMessage', converter.MLAPPFileName));
                progressDialog = uiprogressdlg(app.UIFigure, 'Message', progressDialogMessage, 'Indeterminate', 'on');

                conversionResults = converter.convert();

            catch exception
                knownExceptionIdentifiers = {'appmigration:appmigration:InvalidFileName',...
                    'appmigration:appmigration:InvalidCodeFileName',...
                    'appmigration:appmigration:NotGuideCreatedApp',...
                    'appmigration:appmigration:NotWritableLocation',...
                    'MATLAB:appdesigner:appdesigner:InvalidInput',...
                    'MATLAB:appdesigner:appdesigner:FileNameFailsIsKeyword',...
                    'MATLAB:appdesigner:appdesigner:FileNameFailsIsVarName',...
                    'MATLAB:appdesigner:appdesigner:InvalidGeneralFileExtension',...
                    'MATLAB:appdesigner:appdesigner:InvalidFilePath'};

                if any(strcmp(exception.identifier,knownExceptionIdentifiers))
                    title = getString(message('appmigration:appmigration:AppTitle'));
                    uialert(app.UIFigure,exception.message,title);
                    return;
                else
                    rethrow(exception);
                end
            end

            reportGenerator = appmigration.internal.AppConversionReportGenerator(converter.FigFullFileName, conversionResults);
            reportGenerator.generateHTMLReport();

            mlappFile = conversionResults.MLAPPFullFileName;

            % Open the app in App Designer
            appdesigner(mlappFile)

            delete(progressDialog);
        end

        % Value changed function: ExportEditField
        function ExportEditFieldValueChanged(app, event)
            value = app.ExportEditField.Value;

            if isempty(value)
                app.disableExportEditFieldAndActionButton();
                app.ExportAppName = '';
                app.ExportAppFullFileName = '';
            end
        end

        % Value changed function: MigrateEditField
        function MigrateEditFieldValueChanged(app, event)
            value = app.MigrateEditField.Value;

            if isempty(value)
                app.disableMigrateEditFieldAndActionButton();
                app.MigrateAppName = '';
                app.MigrateAppFullFileName = '';
            end
        end

        % Button pushed function: InstallSupportPackageButton
        function InstallSupportPackageButtonPushed(app, event)
            appdesservices.internal.appmigration.showAppMigrationAddon();

            delete(app);
        end

        % Button pushed function: HelpButton
        function HelpButtonPushed(app, event)
            helpview('matlab', 'diffappdguide');
        end

        % Button pushed function: CancelButton
        function CancelButtonPushed(app, event)
            delete(app)
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.AutoResizeChildren = 'off';
            app.UIFigure.Position = [100 100 764 351];
            app.UIFigure.Name = 'GUIDE Removal Options';
            app.UIFigure.Resize = 'off';

            % Create CancelButton
            app.CancelButton = uibutton(app.UIFigure, 'push');
            app.CancelButton.ButtonPushedFcn = createCallbackFcn(app, @CancelButtonPushed, true);
            app.CancelButton.Position = [671 19 65 22];
            app.CancelButton.Text = 'Cancel';

            % Create HelpButton
            app.HelpButton = uibutton(app.UIFigure, 'push');
            app.HelpButton.ButtonPushedFcn = createCallbackFcn(app, @HelpButtonPushed, true);
            app.HelpButton.Position = [29 19 64 22];
            app.HelpButton.Text = 'Help';

            % Create InstallSupportPackageButton
            app.InstallSupportPackageButton = uibutton(app.UIFigure, 'push');
            app.InstallSupportPackageButton.ButtonPushedFcn = createCallbackFcn(app, @InstallSupportPackageButtonPushed, true);
            app.InstallSupportPackageButton.Position = [264 -177 142 22];
            app.InstallSupportPackageButton.Text = 'Install Support Package';

            % Create InstallLabel_ItalicsText
            app.InstallLabel_ItalicsText = uilabel(app.UIFigure);
            app.InstallLabel_ItalicsText.VerticalAlignment = 'top';
            app.InstallLabel_ItalicsText.FontAngle = 'italic';
            app.InstallLabel_ItalicsText.Position = [126 -123 290 22];
            app.InstallLabel_ItalicsText.Text = '"GUIDE to App Designer Migration Tool for MATLAB"';

            % Create InstallLabel_RegularText
            app.InstallLabel_RegularText = uilabel(app.UIFigure);
            app.InstallLabel_RegularText.VerticalAlignment = 'top';
            app.InstallLabel_RegularText.WordWrap = 'on';
            app.InstallLabel_RegularText.Position = [72 -135 233 33];
            app.InstallLabel_RegularText.Text = {'Install the'; 'Support Package before migrating an app.'};

            % Create WarningImageLarge
            app.WarningImageLarge = uiimage(app.UIFigure);
            app.WarningImageLarge.Position = [21 -135 41 37];

            % Create MigrateButton
            app.MigrateButton = uibutton(app.UIFigure, 'push');
            app.MigrateButton.ButtonPushedFcn = createCallbackFcn(app, @MigrateButtonPushed, true);
            app.MigrateButton.Enable = 'off';
            app.MigrateButton.Position = [335 -291 83 22];
            app.MigrateButton.Text = 'Migrate';

            % Create MigrateBrowseButton
            app.MigrateBrowseButton = uibutton(app.UIFigure, 'push');
            app.MigrateBrowseButton.ButtonPushedFcn = createCallbackFcn(app, @MigrateBrowseButtonPushed, true);
            app.MigrateBrowseButton.Position = [335 -248 83 22];
            app.MigrateBrowseButton.Text = 'Browse...';

            % Create MigrateEditField
            app.MigrateEditField = uieditfield(app.UIFigure, 'text');
            app.MigrateEditField.ValueChangedFcn = createCallbackFcn(app, @MigrateEditFieldValueChanged, true);
            app.MigrateEditField.FontAngle = 'italic';
            app.MigrateEditField.Enable = 'off';
            app.MigrateEditField.Position = [20 -248 306 22];
            app.MigrateEditField.Value = 'Select a GUIDE .fig file';

            % Create MigrateChooseAppLabel
            app.MigrateChooseAppLabel = uilabel(app.UIFigure);
            app.MigrateChooseAppLabel.VerticalAlignment = 'top';
            app.MigrateChooseAppLabel.WordWrap = 'on';
            app.MigrateChooseAppLabel.FontWeight = 'bold';
            app.MigrateChooseAppLabel.Position = [20 -227 154 22];
            app.MigrateChooseAppLabel.Text = 'Choose an app to migrate:';

            % Create TabGroup
            app.TabGroup = uitabgroup(app.UIFigure);
            app.TabGroup.AutoResizeChildren = 'off';
            app.TabGroup.Position = [29 59 708 268];

            % Create MigrateTab
            app.MigrateTab = uitab(app.TabGroup);
            app.MigrateTab.AutoResizeChildren = 'off';
            app.MigrateTab.Title = 'Migrate to App Designer';

            % Create MigrateHtmlBullets
            app.MigrateHtmlBullets = uihtml(app.MigrateTab);
            app.MigrateHtmlBullets.HTMLSource = '<ul style="font-size: 12px; font-family: Helvetica; padding-left: 18px;user-select: none;">  <li>Interactive editing of your app is desired or necessary</li><li>The app is actively being developed​</li></ul>';
            app.MigrateHtmlBullets.Position = [19 112 349 62];

            % Create MigrateReasonsLabel
            app.MigrateReasonsLabel = uilabel(app.MigrateTab);
            app.MigrateReasonsLabel.FontWeight = 'bold';
            app.MigrateReasonsLabel.Position = [19 174 282 22];
            app.MigrateReasonsLabel.Text = 'Migrating your app is recommended when:';

            % Create MigrateHeader
            app.MigrateHeader = uilabel(app.MigrateTab);
            app.MigrateHeader.VerticalAlignment = 'top';
            app.MigrateHeader.WordWrap = 'on';
            app.MigrateHeader.Position = [19 204 349 22];
            app.MigrateHeader.Text = 'Migration converts your GUIDE app to a new App Designer app.';

            % Create MigrateImage
            app.MigrateImage = uiimage(app.MigrateTab);
            app.MigrateImage.Position = [417 6 288 234];

            % Create ExportTab
            app.ExportTab = uitab(app.TabGroup);
            app.ExportTab.AutoResizeChildren = 'off';
            app.ExportTab.Title = 'Export to MATLAB Code';

            % Create ExportButton
            app.ExportButton = uibutton(app.ExportTab, 'push');
            app.ExportButton.ButtonPushedFcn = createCallbackFcn(app, @ExportButtonPushed, true);
            app.ExportButton.Enable = 'off';
            app.ExportButton.Position = [335 19 83 22];
            app.ExportButton.Text = 'Export';

            % Create ExportBrowseButton
            app.ExportBrowseButton = uibutton(app.ExportTab, 'push');
            app.ExportBrowseButton.ButtonPushedFcn = createCallbackFcn(app, @ExportBrowseButtonPushed, true);
            app.ExportBrowseButton.Position = [335 62 83 22];
            app.ExportBrowseButton.Text = 'Browse...';

            % Create ExportEditField
            app.ExportEditField = uieditfield(app.ExportTab, 'text');
            app.ExportEditField.ValueChangedFcn = createCallbackFcn(app, @ExportEditFieldValueChanged, true);
            app.ExportEditField.FontAngle = 'italic';
            app.ExportEditField.Enable = 'off';
            app.ExportEditField.Position = [20 62 306 22];
            app.ExportEditField.Value = 'Select a GUIDE .fig file';

            % Create ExportChooseAppLabel
            app.ExportChooseAppLabel = uilabel(app.ExportTab);
            app.ExportChooseAppLabel.VerticalAlignment = 'top';
            app.ExportChooseAppLabel.WordWrap = 'on';
            app.ExportChooseAppLabel.FontWeight = 'bold';
            app.ExportChooseAppLabel.Position = [20 83 154 22];
            app.ExportChooseAppLabel.Text = 'Choose an app to export:';

            % Create ExportHtmlBullets
            app.ExportHtmlBullets = uihtml(app.ExportTab);
            app.ExportHtmlBullets.HTMLSource = '<ul style="font-size: 12px; font-family: Helvetica; padding-left: 18px;user-select: none;"><li>Minor app maintenance is required​</li><li>Interactive editing of your app is not critical</li></ul>';
            app.ExportHtmlBullets.Position = [20 133 298 41];

            % Create ExportReasonsLabel
            app.ExportReasonsLabel = uilabel(app.ExportTab);
            app.ExportReasonsLabel.FontWeight = 'bold';
            app.ExportReasonsLabel.Position = [19 174 282 22];
            app.ExportReasonsLabel.Text = 'Exporting your app is recommended when:';

            % Create ExportHeader
            app.ExportHeader = uilabel(app.ExportTab);
            app.ExportHeader.VerticalAlignment = 'top';
            app.ExportHeader.WordWrap = 'on';
            app.ExportHeader.Position = [19 204 307 22];
            app.ExportHeader.Text = 'Export converts your GUIDE app to a new MATLAB file.';

            % Create ExportImage
            app.ExportImage = uiimage(app.ExportTab);
            app.ExportImage.Position = [442 24 239 199];

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = GUIDEAppMaintenanceOptions(varargin)

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            % Execute the startup function
            runStartupFcn(app, @(app)startupFcn(app, varargin{:}))

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end