classdef PatientsTreeAppExample < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        PatientsMedicalSurveyUIFigure  matlab.ui.Figure
        GridLayout                     matlab.ui.container.GridLayout
        LeftPanel                      matlab.ui.container.Panel
        Tree                           matlab.ui.container.Tree
        CountyGeneralHospitalNode      matlab.ui.container.TreeNode
        StMarysMedicalCenterNode       matlab.ui.container.TreeNode
        VAHospitalNode                 matlab.ui.container.TreeNode
        SelectPatientbyLocationLabel   matlab.ui.control.Label
        RightPanel                     matlab.ui.container.Panel
        PatientInformationLabel        matlab.ui.control.Label
        DemographicsPanel              matlab.ui.container.Panel
        NameEditFieldLabel             matlab.ui.control.Label
        NameEditField                  matlab.ui.control.EditField
        AgeEditFieldLabel              matlab.ui.control.Label
        AgeEditField                   matlab.ui.control.NumericEditField
        GenderDropDownLabel            matlab.ui.control.Label
        GenderDropDown                 matlab.ui.control.DropDown
        SelfAssessmentPanel            matlab.ui.container.Panel
        HealthStatusDropDownLabel      matlab.ui.control.Label
        HealthStatusDropDown           matlab.ui.control.DropDown
        SmokerCheckBox                 matlab.ui.control.CheckBox
    end

    % Properties that correspond to apps with auto-reflow
    properties (Access = private)
        onePanelWidth = 576;
    end

    
    properties (Access = private)
        Data % Patient data
    end
    
    methods (Access = private)
        
        function enableForm(app)
            % Enable form elements
            app.NameEditField.Enable = 'on';
            app.AgeEditField.Enable = 'on';
            app.GenderDropDown.Enable = 'on';
            app.HealthStatusDropDown.Enable = 'on';
            app.SmokerCheckBox.Enable = 'on';

           app.NameEditFieldLabel.Enable = 'on';            
            app.AgeEditFieldLabel.Enable = 'on';
           app.GenderDropDownLabel.Enable = 'on';
            app.HealthStatusDropDownLabel.Enable = 'on';
        end
        
        function disableForm(app)
            % Set form fields to default values
            app.NameEditField.Value = '';
            app.AgeEditField.Value = 0;
            app.GenderDropDown.Value = 'Male';
            app.HealthStatusDropDown.Value = 'Excellent';
            app.SmokerCheckBox.Value = false;
            
            % Disable form fields
            app.NameEditField.Enable = 'off';
            app.AgeEditField.Enable = 'off';
            app.GenderDropDown.Enable = 'off';
            app.HealthStatusDropDown.Enable = 'off';
            app.SmokerCheckBox.Enable = 'off'; 
                        
            app.NameEditFieldLabel.Enable = 'off';            
            app.AgeEditFieldLabel.Enable = 'off';
            app.GenderDropDownLabel.Enable = 'off';
            app.HealthStatusDropDownLabel.Enable = 'off';
        end
    
    end
    

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

        % Code that executes after component creation
        function startupFcn(app)
            
            % Read patient data from a spreadsheet
            t = readtable('patients.xls');
            
            % Create patient nodes for County General Hospital
            patients = t(strcmp(t.Location,app.CountyGeneralHospitalNode.Text) & t.Smoker & t.Age > 44,'LastName');
            for j = 1:size(patients,1)
               lastname = char(patients{j,'LastName'});
               uitreenode(app.CountyGeneralHospitalNode,'Text',lastname);
            end
            
            % Create patient nodes for St. Mary's Medical Center
            patients = t(strcmp(t.Location,app.StMarysMedicalCenterNode.Text) & t.Smoker & t.Age > 44,'LastName');
            for j = 1:size(patients,1)
               lastname = char(patients{j,'LastName'});
               uitreenode(app.StMarysMedicalCenterNode,'Text',lastname);
            end
            
            % Create patient nodes for VA Hospital
            patients = t(strcmp(t.Location,app.VAHospitalNode.Text) & t.Smoker & t.Age > 44,'LastName');
            for j = 1:size(patients,1)
               lastname = char(patients{j,'LastName'});
               uitreenode(app.VAHospitalNode,'Text',lastname);
            end
            
            % Set table row names to last names
            t.Properties.RowNames = t.LastName;
            
            % Add the data to the app
            app.Data = t;
            
        end

        % Changes arrangement of the app based on UIFigure width
        function updateAppLayout(app, event)
            currentFigureWidth = app.PatientsMedicalSurveyUIFigure.Position(3);
            if(currentFigureWidth <= app.onePanelWidth)
                % Change to a 2x1 grid
                app.GridLayout.RowHeight = {383, 383};
                app.GridLayout.ColumnWidth = {'1x'};
                app.RightPanel.Layout.Row = 2;
                app.RightPanel.Layout.Column = 1;
            else
                % Change to a 1x2 grid
                app.GridLayout.RowHeight = {'1x'};
                app.GridLayout.ColumnWidth = {278, '1x'};
                app.RightPanel.Layout.Row = 1;
                app.RightPanel.Layout.Column = 2;
            end
        end

        % Selection changed function: Tree
        function TreeSelectionChanged(app, event)
            selectedNode = app.Tree.SelectedNodes;
            
            % Enable form only when a patient is selected
            hospitals = {'County General Hospital','St. Mary''s Medical Center','VA Hospital'};
            if ~isempty(find(strcmp(selectedNode.Text,hospitals),1))
                % disable form fields
                disableForm(app);
            else
                % enable form fields
                enableForm(app);
            end
   
            % Get patient's name from node text.
            patientName = selectedNode.Text;
            
            % Extract this patient's data from app.Data.
            if isempty(selectedNode.Children)
                data = app.Data(patientName,:);
                
                % Update the fields with the appropriate data when the patient name is selected.
                if ~isempty(data)
                    app.NameEditField.Value = patientName;
                    app.AgeEditField.Value = data.Age;
                    app.SmokerCheckBox.Value = data.Smoker;
                    app.GenderDropDown.Value = char(data.Gender);
                    app.HealthStatusDropDown.Value = char(data.SelfAssessedHealthStatus);
                end
                
            end
            
        end

        % Value changed function: AgeEditField
        function AgeEditFieldValueChanged(app, event)
            % Update stored data with changed value
            patientName = app.Tree.SelectedNodes.Text;
            app.Data.Age(patientName) = app.AgeEditField.Value;
        end

        % Value changed function: SmokerCheckBox
        function SmokerCheckBoxValueChanged(app, event)
            % Update stored data with changed value
            patientName = app.Tree.SelectedNodes.Text;
            app.Data.Smoker(patientName) = app.SmokerCheckBox.Value;
        end

        % Value changed function: HealthStatusDropDown
        function HealthStatusDropDownValueChanged(app, event)
            % Update stored data with changed value
            patientName = app.Tree.SelectedNodes.Text;
            app.Data.SelfAssessedHealthStatus(patientName) = {app.HealthStatusDropDown.Value};
        end

        % Value changed function: GenderDropDown
        function GenderDropDownValueChanged(app, event)
            % Update stored data with changed value
            patientName = app.Tree.SelectedNodes.Text;
            app.Data.Gender(patientName) = {app.GenderDropDown.Value};
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create PatientsMedicalSurveyUIFigure and hide until all components are created
            app.PatientsMedicalSurveyUIFigure = uifigure('Visible', 'off');
            app.PatientsMedicalSurveyUIFigure.AutoResizeChildren = 'off';
            app.PatientsMedicalSurveyUIFigure.Position = [100 100 626 383];
            app.PatientsMedicalSurveyUIFigure.Name = 'Patient Medical Survey';
            app.PatientsMedicalSurveyUIFigure.SizeChangedFcn = createCallbackFcn(app, @updateAppLayout, true);

            % Create GridLayout
            app.GridLayout = uigridlayout(app.PatientsMedicalSurveyUIFigure);
            app.GridLayout.ColumnWidth = {278, '1x'};
            app.GridLayout.RowHeight = {'1x'};
            app.GridLayout.ColumnSpacing = 0;
            app.GridLayout.RowSpacing = 0;
            app.GridLayout.Padding = [0 0 0 0];
            app.GridLayout.Scrollable = 'on';

            % Create LeftPanel
            app.LeftPanel = uipanel(app.GridLayout);
            app.LeftPanel.Layout.Row = 1;
            app.LeftPanel.Layout.Column = 1;
            app.LeftPanel.Scrollable = 'on';

            % Create Tree
            app.Tree = uitree(app.LeftPanel);
            app.Tree.SelectionChangedFcn = createCallbackFcn(app, @TreeSelectionChanged, true);
            app.Tree.Position = [26 42 227 280];

            % Create CountyGeneralHospitalNode
            app.CountyGeneralHospitalNode = uitreenode(app.Tree);
            app.CountyGeneralHospitalNode.Text = 'County General Hospital';

            % Create StMarysMedicalCenterNode
            app.StMarysMedicalCenterNode = uitreenode(app.Tree);
            app.StMarysMedicalCenterNode.Text = 'St. Mary''s Medical Center';

            % Create VAHospitalNode
            app.VAHospitalNode = uitreenode(app.Tree);
            app.VAHospitalNode.Text = 'VA Hospital';

            % Create SelectPatientbyLocationLabel
            app.SelectPatientbyLocationLabel = uilabel(app.LeftPanel);
            app.SelectPatientbyLocationLabel.HorizontalAlignment = 'center';
            app.SelectPatientbyLocationLabel.FontSize = 16;
            app.SelectPatientbyLocationLabel.Position = [26 337 227 22];
            app.SelectPatientbyLocationLabel.Text = 'Select Patient by Location';

            % Create RightPanel
            app.RightPanel = uipanel(app.GridLayout);
            app.RightPanel.Layout.Row = 1;
            app.RightPanel.Layout.Column = 2;
            app.RightPanel.Scrollable = 'on';

            % Create PatientInformationLabel
            app.PatientInformationLabel = uilabel(app.RightPanel);
            app.PatientInformationLabel.HorizontalAlignment = 'center';
            app.PatientInformationLabel.FontSize = 16;
            app.PatientInformationLabel.Position = [26 337 297 22];
            app.PatientInformationLabel.Text = 'Patient Information';

            % Create DemographicsPanel
            app.DemographicsPanel = uipanel(app.RightPanel);
            app.DemographicsPanel.Title = 'Demographics';
            app.DemographicsPanel.Position = [26 166 297 156];

            % Create NameEditFieldLabel
            app.NameEditFieldLabel = uilabel(app.DemographicsPanel);
            app.NameEditFieldLabel.HorizontalAlignment = 'right';
            app.NameEditFieldLabel.Enable = 'off';
            app.NameEditFieldLabel.Position = [13 91 38 22];
            app.NameEditFieldLabel.Text = 'Name';

            % Create NameEditField
            app.NameEditField = uieditfield(app.DemographicsPanel, 'text');
            app.NameEditField.Editable = 'off';
            app.NameEditField.Enable = 'off';
            app.NameEditField.Position = [66 91 225 22];

            % Create AgeEditFieldLabel
            app.AgeEditFieldLabel = uilabel(app.DemographicsPanel);
            app.AgeEditFieldLabel.HorizontalAlignment = 'right';
            app.AgeEditFieldLabel.Enable = 'off';
            app.AgeEditFieldLabel.Position = [24 55 27 22];
            app.AgeEditFieldLabel.Text = 'Age';

            % Create AgeEditField
            app.AgeEditField = uieditfield(app.DemographicsPanel, 'numeric');
            app.AgeEditField.ValueChangedFcn = createCallbackFcn(app, @AgeEditFieldValueChanged, true);
            app.AgeEditField.HorizontalAlignment = 'left';
            app.AgeEditField.Enable = 'off';
            app.AgeEditField.Position = [66 55 225 22];

            % Create GenderDropDownLabel
            app.GenderDropDownLabel = uilabel(app.DemographicsPanel);
            app.GenderDropDownLabel.HorizontalAlignment = 'right';
            app.GenderDropDownLabel.Enable = 'off';
            app.GenderDropDownLabel.Position = [5 20 46 22];
            app.GenderDropDownLabel.Text = 'Gender';

            % Create GenderDropDown
            app.GenderDropDown = uidropdown(app.DemographicsPanel);
            app.GenderDropDown.Items = {'Male', 'Female', 'Other'};
            app.GenderDropDown.ValueChangedFcn = createCallbackFcn(app, @GenderDropDownValueChanged, true);
            app.GenderDropDown.Enable = 'off';
            app.GenderDropDown.Position = [66 20 225 22];
            app.GenderDropDown.Value = 'Male';

            % Create SelfAssessmentPanel
            app.SelfAssessmentPanel = uipanel(app.RightPanel);
            app.SelfAssessmentPanel.Title = 'Self-Assessment';
            app.SelfAssessmentPanel.Position = [26 42 297 112];

            % Create HealthStatusDropDownLabel
            app.HealthStatusDropDownLabel = uilabel(app.SelfAssessmentPanel);
            app.HealthStatusDropDownLabel.HorizontalAlignment = 'right';
            app.HealthStatusDropDownLabel.Enable = 'off';
            app.HealthStatusDropDownLabel.Position = [6 60 78 22];
            app.HealthStatusDropDownLabel.Text = 'Health Status';

            % Create HealthStatusDropDown
            app.HealthStatusDropDown = uidropdown(app.SelfAssessmentPanel);
            app.HealthStatusDropDown.Items = {'Excellent', 'Good', 'Fair', 'Poor'};
            app.HealthStatusDropDown.ValueChangedFcn = createCallbackFcn(app, @HealthStatusDropDownValueChanged, true);
            app.HealthStatusDropDown.Enable = 'off';
            app.HealthStatusDropDown.Position = [99 60 192 22];
            app.HealthStatusDropDown.Value = 'Excellent';

            % Create SmokerCheckBox
            app.SmokerCheckBox = uicheckbox(app.SelfAssessmentPanel);
            app.SmokerCheckBox.ValueChangedFcn = createCallbackFcn(app, @SmokerCheckBoxValueChanged, true);
            app.SmokerCheckBox.Enable = 'off';
            app.SmokerCheckBox.Text = 'Smoker';
            app.SmokerCheckBox.Position = [14 25 63 22];

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

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = PatientsTreeAppExample

            % Create UIFigure and components
            createComponents(app)

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

            % 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.PatientsMedicalSurveyUIFigure)
        end
    end
end