classdef CrossGUI < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        CrossDialog   matlab.ui.Figure
        FileMenu      matlab.ui.container.Menu
        OpenFile      matlab.ui.container.Menu
        SaveFile      matlab.ui.container.Menu
        Exit          matlab.ui.container.Menu
        AboutMenu     matlab.ui.container.Menu
        MessagePanel  matlab.ui.container.Panel
        MessageText   matlab.ui.control.Label
        ControlRuler  matlab.ui.container.Panel
        DeleteSup     matlab.ui.control.StateButton
        InsertSup     matlab.ui.control.StateButton
        Precision     matlab.ui.control.DropDown
        GoThru        matlab.ui.control.Button
        Step          matlab.ui.control.Button
        Restart       matlab.ui.control.Button
        SupEnd        matlab.ui.control.Button
        SupInit       matlab.ui.control.Button
    end

    properties (Access = public)
        control       CrossControl
    end

    methods (Access = private)
        % Called when user attempts to close dialog
        function deleteCallback(app)
            choice = questdlg('Are you sure you want to exit?',...
            'Exit','Exit','Cancel','Cancel');
            switch choice
                case 'Cancel'
                    return
            end
            app.delete();
        end

        %------------------------------------------------------------------
        % Called when axes graphical component is resized
    end

    methods (Access = public)

        function updateTextMessage(app)
            if app.control.solver.moreStepsToGo()
                app.MessageText.Text = 'Moments are not balanced yet.';
            else
                app.MessageText.Text = 'Cross iterative solution completed.';
            end
        end

        function setTextMessage(app,msg)
            app.MessageText.Text = msg;
        end

        function updateSupInit(app,supinit)
            if supinit == 0
                app.SupInit.Icon = 'images/supinitfix.gif';
                app.SupInit.Tooltip = 'Change initial support to clamped';
            else
                app.SupInit.Icon = 'images/supinitrel.gif';
                app.SupInit.Tooltip = 'Change initial support to released';
            end
        end

        function updateSupEnd(app,supend)
            if supend == 0
                app.SupEnd.Icon = 'images/supendfix.gif';
                app.SupEnd.Tooltip = 'Change end support to clamped';
            else
                app.SupEnd.Icon = 'images/supendrel.gif';
                app.SupEnd.Tooltip = 'Change end support to released';
            end
        end

        function resetInsertSup(app)
            if app.InsertSup.Value
                app.InsertSup.Value = false;
%                app.control.insertSupMode(false);
            end
        end

        function resetDeleteSup(app)
            if app.DeleteSup.Value
                app.DeleteSup.Value = false;
%                app.control.deleteSupMode(false);
            end
        end
    end


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

        % Code that executes after component creation
        function startupFcn(app)
            % Create and initialize cross control object
            app.control = CrossControl(app);
            app.control.startup();

            % Set close app callback function
            app.CrossDialog.CloseRequestFcn = app.createCallbackFcn(@deleteCallback, false);

        end

        % Button pushed function: SupInit
        function SupInitButtonPushed(app, event)
            app.resetInsertSup();
            app.resetDeleteSup();
            app.control.toggleSupInit();
            app.updateSupInit(app.control.solver.supinit);
            app.updateTextMessage();
        end

        % Button pushed function: SupEnd
        function SupEndButtonPushed(app, event)
            app.resetInsertSup();
            app.resetDeleteSup();
            app.control.toggleSupEnd();
            app.updateSupEnd(app.control.solver.supend);
            app.updateTextMessage();
        end

        % Button pushed function: Restart
        function RestartButtonPushed(app, event)
            app.resetInsertSup();
            app.resetDeleteSup();
            app.control.restart();
            app.updateTextMessage();
        end

        % Button pushed function: Step
        function StepButtonPushed(app, event)
            app.resetInsertSup();
            app.resetDeleteSup();
            app.control.autoStep();
            app.updateTextMessage();
        end

        % Button pushed function: GoThru
        function GoThruButtonPushed(app, event)
            app.resetInsertSup();
            app.resetDeleteSup();
            app.control.goThru();
            app.updateTextMessage();
        end

        % Value changed function: InsertSup
        function InsertSupValueChanged(app, event)
            app.resetDeleteSup();
            value = app.InsertSup.Value;
%            app.control.insertSupMode(value);
            app.MessageText.Text = 'Insert an internal support with mouse pointer.';
        end

        % Value changed function: DeleteSup
        function DeleteSupValueChanged(app, event)
            app.resetInsertSup();
            value = app.DeleteSup.Value;
%            app.control.deleteSupMode(value);
            app.MessageText.Text = 'Select an internal support for deletion with mouse pointer.';
        end

        % Value changed function: Precision
        function PrecisionValueChanged(app, event)
            app.resetInsertSup();
            app.resetDeleteSup();
            value = app.Precision.Value;
            if strcmp(value,'1 kNm')
                decplc = 0;
            elseif strcmp(value,'0.1 kNm')
                decplc = 1;
            else
                decplc = 2;
            end
            app.control.setPrecision(decplc);
            app.updateTextMessage();
        end

        % Menu selected function: Exit
        function ExitMenuSelected(app, event)
            app.deleteCallback();
        end

        % Menu selected function: OpenFile
        function OpenFileMenuSelected(app, event)
            app.resetInsertSup();
            app.resetDeleteSup();
            filterspec = {'*.crs'};
            [filename,pathname] = uigetfile(filterspec,'Cross Program - Input file');
            if ~isequal(filename,0)
                fullname = strcat(pathname,filename);
                app.control.openFile(fullname);
            end
            app.updateTextMessage();
        end

        % Menu selected function: SaveFile
        function SaveFileMenuSelected(app, event)
            app.resetInsertSup();
            app.resetDeleteSup();
            filterspec = {'*.crs'};
            [filename,pathname] = uiputfile(filterspec,'Cross Program - Output file');
            if ~isequal(filename,0)
                fullname = strcat(pathname,filename);
                app.control.saveFile(fullname);
            end
        end

        % Menu selected function: AboutMenu
        function AboutMenuSelected(app, event)
            msgbox({ 'PUC-Rio - CIV2801 - Fundamentos de Computação Gráfica Aplicada - 2026.2'; ' '; ...
                      'Program to demonstrate the Cross process applied to a continuous beam.' }, 'About Cross program');
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create CrossDialog and hide until all components are created
            app.CrossDialog = uifigure('Visible', 'off');
            app.CrossDialog.Position = [100 100 900 70];
            app.CrossDialog.Name = 'Cross process of continuous beam';
            app.CrossDialog.Scrollable = 'on';

            % Create FileMenu
            app.FileMenu = uimenu(app.CrossDialog);
            app.FileMenu.Text = 'File';

            % Create OpenFile
            app.OpenFile = uimenu(app.FileMenu);
            app.OpenFile.MenuSelectedFcn = createCallbackFcn(app, @OpenFileMenuSelected, true);
            app.OpenFile.Text = 'Open';

            % Create SaveFile
            app.SaveFile = uimenu(app.FileMenu);
            app.SaveFile.MenuSelectedFcn = createCallbackFcn(app, @SaveFileMenuSelected, true);
            app.SaveFile.Text = 'Save as ...';

            % Create Exit
            app.Exit = uimenu(app.FileMenu);
            app.Exit.MenuSelectedFcn = createCallbackFcn(app, @ExitMenuSelected, true);
            app.Exit.Text = 'Exit ...';

            % Create AboutMenu
            app.AboutMenu = uimenu(app.CrossDialog);
            app.AboutMenu.MenuSelectedFcn = createCallbackFcn(app, @AboutMenuSelected, true);
            app.AboutMenu.Text = 'About';

            % Create ControlRuler
            app.ControlRuler = uipanel(app.CrossDialog);
            app.ControlRuler.Position = [2 41 898 30];

            % Create SupInit
            app.SupInit = uibutton(app.ControlRuler, 'push');
            app.SupInit.ButtonPushedFcn = createCallbackFcn(app, @SupInitButtonPushed, true);
            app.SupInit.Icon = 'supinitfix.gif';
            app.SupInit.IconAlignment = 'center';
            app.SupInit.Tooltip = {'Change initial support to clamped'};
            app.SupInit.Position = [0 5 21 22];
            app.SupInit.Text = '';

            % Create SupEnd
            app.SupEnd = uibutton(app.ControlRuler, 'push');
            app.SupEnd.ButtonPushedFcn = createCallbackFcn(app, @SupEndButtonPushed, true);
            app.SupEnd.Icon = 'supendrel.gif';
            app.SupEnd.IconAlignment = 'center';
            app.SupEnd.Tooltip = {'Change initial support to released'};
            app.SupEnd.Position = [61 5 21 22];
            app.SupEnd.Text = '';

            % Create Restart
            app.Restart = uibutton(app.ControlRuler, 'push');
            app.Restart.ButtonPushedFcn = createCallbackFcn(app, @RestartButtonPushed, true);
            app.Restart.Icon = 'restart.gif';
            app.Restart.IconAlignment = 'center';
            app.Restart.Tooltip = {'Initialize interative solution of Cross process'};
            app.Restart.Position = [125 5 21 22];
            app.Restart.Text = '';

            % Create Step
            app.Step = uibutton(app.ControlRuler, 'push');
            app.Step.ButtonPushedFcn = createCallbackFcn(app, @StepButtonPushed, true);
            app.Step.Icon = 'step.gif';
            app.Step.IconAlignment = 'center';
            app.Step.Tooltip = {'Process one step of iterative solution '};
            app.Step.Position = [145 5 21 22];
            app.Step.Text = '';

            % Create GoThru
            app.GoThru = uibutton(app.ControlRuler, 'push');
            app.GoThru.ButtonPushedFcn = createCallbackFcn(app, @GoThruButtonPushed, true);
            app.GoThru.Icon = 'gothru.gif';
            app.GoThru.IconAlignment = 'center';
            app.GoThru.Tooltip = {'Go through: process all steps of iterative solution'};
            app.GoThru.Position = [165 5 21 22];
            app.GoThru.Text = '';

            % Create Precision
            app.Precision = uidropdown(app.ControlRuler);
            app.Precision.Items = {'1 kNm', '0.1 kNm', '0.01 kNm'};
            app.Precision.ValueChangedFcn = createCallbackFcn(app, @PrecisionValueChanged, true);
            app.Precision.Tooltip = {'Set bending moment precision of iterative solution'};
            app.Precision.Position = [185 5 84 22];
            app.Precision.Value = '0.1 kNm';

            % Create InsertSup
            app.InsertSup = uibutton(app.ControlRuler, 'state');
            app.InsertSup.ValueChangedFcn = createCallbackFcn(app, @InsertSupValueChanged, true);
            app.InsertSup.Tooltip = {'Insert internal support'};
            app.InsertSup.Icon = 'supinsert.gif';
            app.InsertSup.Text = '';
            app.InsertSup.Position = [21 5 21 22];

            % Create DeleteSup
            app.DeleteSup = uibutton(app.ControlRuler, 'state');
            app.DeleteSup.ValueChangedFcn = createCallbackFcn(app, @DeleteSupValueChanged, true);
            app.DeleteSup.Tooltip = {'Delete internal support'};
            app.DeleteSup.Icon = 'supdelete.gif';
            app.DeleteSup.Text = '';
            app.DeleteSup.Position = [41 5 21 22];

            % Create MessagePanel
            app.MessagePanel = uipanel(app.CrossDialog);
            app.MessagePanel.Position = [2 10 898 30];

            % Create MessageText
            app.MessageText = uilabel(app.MessagePanel);
            app.MessageText.Position = [4 4 893 22];
            app.MessageText.Text = 'Moments are not balanced yet.';

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

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = CrossGUI

            % Create UIFigure and components
            createComponents(app)

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

            % Execute the startup function
            runStartupFcn(app, @startupFcn)

            if nargout == 0
                clear app
            end
        end

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

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