Skip to content
GUI.m 61.1 KiB
Newer Older
Colin Eles's avatar
Colin Eles committed
classdef GUI < handle
   
    
    properties
        % vertical grid
        Grid2 = [];
        
        % horizontal grid
        Grid1 = [];
        %output grid
        Grid0 = [];
        main_fig = [];
        frame = [];
        fig = [];
        scroll_v = [];
        edit_tog = [];
        save_pb = [];
        pvs_pb = [];
        close_pb = [];
        save_ext_pb = [];
        check_pb = [];
        input_pb = [];
        settings_pb = [];
Colin Eles's avatar
Colin Eles committed
        function_name_control = [];
        function_name_text = [];
        function_inputs_text = [];
        function_inputs_control = [];
        edit = 1;
        initialized = 0;
        block_handle = [];
        settings = [];
Colin Eles's avatar
Colin Eles committed
        % height of header where buttons and text is
        header_height = 100;
        % window size
Colin Eles's avatar
Colin Eles committed
        fig_width = 800;
        % space inbetween buttons in header
        pb_offset = 5;
        % width of push buttons in header
        pb_width = 80;
        % height of push buttons in header
        pb_height = 40;
        % width of text boxes
        text_width = 250;
        name_label = [];
        input_label = [];
Colin Eles's avatar
Colin Eles committed
        PVS = [];
Colin Eles's avatar
Colin Eles committed
        pvs_checked = [];
Colin Eles's avatar
Colin Eles committed
        mode = [];
Colin Eles's avatar
Colin Eles committed
        saved = [];
Colin Eles's avatar
Colin Eles committed
    end
    
    methods
        %% GUI
        %   constructor
        % inputs:
        %   h:double - handle to Tabular block in model
Colin Eles's avatar
Colin Eles committed
        %   mode:boolean - the mode of the gui, 1 for simuink, 0 for matlab
Colin Eles's avatar
Colin Eles committed
        % outputs;
Colin Eles's avatar
Colin Eles committed
        %   object:GUI - object that is created
        function object = GUI(h,mode)
            object.block_handle = h;
            object.mode = mode;
Colin Eles's avatar
Colin Eles committed
        end
        
Colin Eles's avatar
Colin Eles committed
        %% setData
        %   set the gui data object based on inputed data structure
        % inputs:
        %   obj:GUI - GUI object
        %   Data:Data - Data object
        % outputs;
        %   object:GUI - object that is created
        function [] = setData(object,Data)
            object.Data = Data;
            object.Grid0 = Data.Grid0;
            object.Grid1 = Data.Grid1;
            object.Grid2 = Data.Grid2;
            object.pvs_checked = Data.checked;
            object.function_name_text = Data.function_name;
            object.function_inputs_text = Data.function_inputs;
            object.settings = Data.settings;
Colin Eles's avatar
Colin Eles committed
        %% init
        %   initialize the gui
        % inputs:
        %   obj:GUI - GUI object
        % outputs;
        %   none
        function [] = init(object)
Colin Eles's avatar
Colin Eles committed
            
            % create the handles for the gui objects
            if object.mode == 1
                name = get_param(object.block_handle,'Name');
            elseif object.mode == 0
Colin Eles's avatar
Colin Eles committed
                name = 'Table Tool';
            end
Colin Eles's avatar
Colin Eles committed
            % main figure
            object.fig = figure('units','pixels',...
                'position',[0 0 object.fig_width object.fig_height],...
Colin Eles's avatar
Colin Eles committed
                'menubar','none',...
                'name','Table Tool',...
Colin Eles's avatar
Colin Eles committed
                'numbertitle','off',...
                'resize','on',...
Colin Eles's avatar
Colin Eles committed
                'Name',name,...
                'CloseRequestFcn',@(src,event)close_fig(object,src,event),...
                'ResizeFcn',@(src,event)resize_fig(object,src,event));
Colin Eles's avatar
Colin Eles committed
          
            
            % edit button
            object.edit_tog = uicontrol('style','toggle',...
Colin Eles's avatar
Colin Eles committed
                'units','pix',...
                'string','Edit',...
                'HorizontalAlign','left',...
                'Parent',object.fig,...
                'Value',object.edit,...
                'callback',@(src,event)edit_tog_call(object,src,event));
Colin Eles's avatar
Colin Eles committed
            
            % Save button
            object.save_pb = uicontrol('style','push',...
Colin Eles's avatar
Colin Eles committed
                'units','pix',...
                'string','Save',...
                'HorizontalAlign','left',...
                'Parent',object.fig,...
                'callback',@(src,event)save_call(object,src,event));
Colin Eles's avatar
Colin Eles committed
            
            % Close button
            object.close_pb = uicontrol('style','push',...
Colin Eles's avatar
Colin Eles committed
                'units','pix',...
                'string','Close',...
                'HorizontalAlign','left',...
                'Parent',object.fig,...
                'callback',@(src,event)close_fig(object,src,event));
Colin Eles's avatar
Colin Eles committed
            
            % Save external button
            object.save_ext_pb = uicontrol('style','push',...
Colin Eles's avatar
Colin Eles committed
                'units','pix',...
                'string','Save Ext',...
                'HorizontalAlign','left',...
                'Parent',object.fig,...
                'callback',@(src,event)save_ext_call(object,src,event));
Colin Eles's avatar
Colin Eles committed
            
            % PVS button
            object.pvs_pb = uicontrol('style','push',...
Colin Eles's avatar
Colin Eles committed
                'units','pix',...
                'string','PVS',...
                'HorizontalAlign','left',...
                'Parent',object.fig,...
                'callback',@(src,event)pvs_ext_call(object,src,event));
Colin Eles's avatar
Colin Eles committed
            
            % Check button
            object.check_pb = uicontrol('style','push',...
Colin Eles's avatar
Colin Eles committed
                'units','pix',...
                'string','Check',...
                'HorizontalAlign','left',...
                'Parent',object.fig,...
                'callback',@(src,event)check_call(object,src,event));
Colin Eles's avatar
Colin Eles committed
            
            % Input/Output button
            object.input_pb = uicontrol('style','push',...
                'units','pix',...
                'string','Ports',...
                'HorizontalAlign','left',...
                'Parent',object.fig,...
                'callback',@(src,event)input_call(object,src,event));
            % Settings button
            object.settings_pb = uicontrol('style','push',...
                'units','pix',...
                'string','Settings',...
                'HorizontalAlign','left',...
                'Parent',object.fig,...
                'callback',@(src,event)settings_call(object,src,event));
Colin Eles's avatar
Colin Eles committed
            % Expression Name Label
            object.name_label = uicontrol('style','text',...
Colin Eles's avatar
Colin Eles committed
                'string','Expression Name',...
                'HorizontalAlign','right',...
                'BackgroundColor',get(object.fig,'Color'));
Colin Eles's avatar
Colin Eles committed
            
            % Expression Name Edit box
            object.function_name_control = uicontrol('style','edit',...
Colin Eles's avatar
Colin Eles committed
                'units','pix',...
                'Parent',object.fig,...
Colin Eles's avatar
Colin Eles committed
                'HorizontalAlign','center',...
                'FontWeight','bold',...
                'FontSize',12,...
                'Max',2.0,...
                'BackgroundColor',[1 1 1]);
            
            % input list label
            object.input_label = uicontrol('style','text',...
Colin Eles's avatar
Colin Eles committed
                'string','Inputs',...
                'HorizontalAlign','right',...
                'BackgroundColor',get(object.fig,'Color'));
Colin Eles's avatar
Colin Eles committed
            
            % input list edit box
            object.function_inputs_control = uicontrol('style','edit',...
Colin Eles's avatar
Colin Eles committed
                'units','pix',...
                'Parent',object.fig,...
Colin Eles's avatar
Colin Eles committed
                'HorizontalAlign','center',...
                'FontWeight','bold',...
                'Max',2.0,...
                'FontSize',12,...
                'BackgroundColor',[1 1 1]);
            
            % load the function name and inputs
            if (~isempty(object.function_name_text))
                set(object.function_name_control,'String',object.function_name_text);
Colin Eles's avatar
Colin Eles committed
            end
            if (~isempty(object.function_inputs_text))
                set(object.function_inputs_control,'String',object.function_inputs_text);
Colin Eles's avatar
Colin Eles committed
            end
            
            
            % Set up Menu
            filemenu = uimenu('Label','File');
            editmenu = uimenu('Label','Edit');
            pvsmenu = uimenu('Label','PVS');
            helpmenu = uimenu('Label','Help');
            uimenu(filemenu,'Label','New','Accelerator','n','Callback',@(src,event)new_call(object,src,event));
            uimenu(filemenu,'Label','Open...','Callback',@(src,event)open_call(object,src,event));
            uimenu(filemenu,'Label','Save to Block','Separator','on','Accelerator','s','Callback',@(src,event)save_call(object,src,event));
            uimenu(filemenu,'Label','Save to M-File','Callback',@(src,event)save_ext_call(object,src,event));
            uimenu(filemenu,'Label','Close','Accelerator','w','Separator','on','Callback',@(src,event)close_fig(object,src,event));     
            uimenu(editmenu,'Label','Show edit controls','Checked','on');
            uimenu(editmenu,'Label','Ports and Data Manager','Accelerator','p','Callback',@(src,event)input_call(object,src,event));
            uimenu(pvsmenu,'Label','Typecheck','Accelerator','t','Callback',@(src,event)pvs_ext_call(object,src,event));
            uimenu(pvsmenu,'Label','PVS Settings','Callback',@(src,event)settings_call(object,src,event));
            uimenu(pvsmenu,'Label','Check Status','Callback',@(src,event)prf_file_call(object,src,event));
            uimenu(pvsmenu,'Label','Generate PVS file','Callback',@(src,event)pvs_file_call(object,src,event));
            object.set_command_pos;
            object.reset_wh();
            object.draw_allgrids(1);
Colin Eles's avatar
Colin Eles committed
            object.saved = 1;
            object.setPBenable;
            object.settings = Settings();
            if isfield(object.Data.settings,'set')
                object.settings.setvalues(object.Data.settings);
                object.settings.init();
Colin Eles's avatar
Colin Eles committed
                
            object.update_Statusbar;
            object.PVS = PVS_checker(object.Data);
            object.EMLGen = EMLGenerator(object.Data);
Colin Eles's avatar
Colin Eles committed
            
            object.initialized = 1;
            object.Data.open = 1;
            object.Data.fig = object.fig;
        %% update_Statusbar
        %   update the statusbar located at bottom of window based on
        %   current state of typecheckness
        % inputs:
        %   obj:GUI - GUI object
        % outputs;
        %   none
Colin Eles's avatar
Colin Eles committed
        function [] = update_Statusbar(object)
            
        warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame
            % statusbar depends on JavaFrame which may be obsolete in
            % future versions of Matlab, can still use in old versions
            try
                if (object.pvs_checked == 0)
                   sb = statusbar(object.fig, 'Status: Not Typechecked');
                   set(sb.TextPanel,'Foreground',[1,0,0]);
                elseif (object.pvs_checked == 1)
                  sb = statusbar(object.fig, 'Status: Typechecked');
                   set(sb.TextPanel,'Foreground',[0,1,0]);

                end
            catch exception
                % do nothing if exception found, may change in future.
Colin Eles's avatar
Colin Eles committed
        %% new_call
        %   callback for new button
        % inputs:
        %   obj:GUI - GUI objecto
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function [] = new_call(object,src,event)
            TableToolMatlab
        end
        
Colin Eles's avatar
Colin Eles committed
         
        %% pvs_file_call
        %   callback for the generate pvs file button, generates a pvs file
        %   for the table, does not attempt to prove, overwrites.
        % inputs:
        %   obj:GUI - GUI objecto
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
Colin Eles's avatar
Colin Eles committed
        function [] = pvs_file_call(object,src,event)
            object.save_data
             object.PVS.generate_pvs_file(object.Data.function_name);
            
            
        end
        
Colin Eles's avatar
Colin Eles committed
        %% prf_file_call
        %   callback for the check status menu option, this function will
        %   check the current status of the table, if the table has been
        %   proven it will alert the user and update the status, if it has
        %   not been proven it will alert the user.
        % inputs:
        %   obj:GUI - GUI objecto
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function [] = prf_file_call(object,src,event)
            object.save_data;
            % check if a pvs file exists
            if (~exist([object.Data.function_name '.pvs'],'file'))
                errordlg(['PVS theory file for this function does not exist' sprintf('\n') 'Nothing to check']);
                return;
            end
            % check if prf file exists
            if (~exist([object.Data.function_name '.prf'],'file'))
                errordlg(['PVS proof (.prf) file for this function does not exist' sprintf('\n') 'Nothing to check']);
                return;
            end
            % check if pvs file is different from current table
            temp_pvs = [object.Data.function_name '_temp'];
            object.PVS.generate_pvs_file(temp_pvs);

            % read pvs theory on file
            pvs1 = textread([object.Data.function_name '.pvs'], '%s', 'whitespace', '', 'bufsize', 268435456);
            pvs2 = textread([temp_pvs '.pvs'], '%s', 'whitespace', '', 'bufsize', 268435456);
            
            if(size(pvs1{1},2) ~= size(pvs2{1},2))
                errordlg(['pvs-theory file is different from the given graphical representation, ' sprintf('\n') ' you will need to reprove']);
                return;
            else
              
                    if ~all(pvs1{1} == pvs2{1})
                        errordlg(['pvs-theory file is different from the given graphical representation, ' sprintf('\n') ' you will need to reprove']);
                        return;
                    end
                    
                
            end
            delete([temp_pvs '.pvs']);
Colin Eles's avatar
Colin Eles committed

Colin Eles's avatar
Colin Eles committed
            status = object.PVS.check_status;
            if (status ~= object.pvs_checked)

                object.pvs_checked = status;
                object.update_Statusbar;
                if (object.mode == 1)
                    TableBlock.set_block_display(object.block_handle,object.pvs_checked)
Colin Eles's avatar
Colin Eles committed

            end

            if (status == 1)
                    msgbox('Table has been proven');
                else
                    msgbox('Table has not been proven');
            end

Colin Eles's avatar
Colin Eles committed
        %% open_call
        %   callback for the open option, will show a file picker and
        %   attempt to load the file into a new window.
        % inputs:
        %   obj:GUI - GUI objecto
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function [] = open_call(object,src,event)
               [FileName, PathName, FilterIndex] = uigetfile('*.table','Select pvs files');
Colin Eles's avatar
Colin Eles committed
               if ~isempty(FileName)
                TTdiag('Load',[PathName FileName]);
               end
Colin Eles's avatar
Colin Eles committed
        %% set_command_pos
        %    sets the location of all the command buttons, labels and edit
        %    boxes, places objects at the top of the figure which it
        %    determines by looking at the height of the figure handle
        % inputs:
        %   obj:GUI - current GUI object
        % outputs;
        %   none
        function [] = set_command_pos(object)
            figpos = get(object.fig,'Position');
Colin Eles's avatar
Colin Eles committed
            % figure out the height of the figure
            l_fig_height = figpos(4);
            set(object.edit_tog,'Position',[object.pb_offset l_fig_height-object.pb_offset-object.pb_height object.pb_width object.pb_height])
            set(object.save_pb,'Position',[object.pb_offset*2+object.pb_width,l_fig_height-object.pb_offset-object.pb_height,object.pb_width,object.pb_height])
            set(object.close_pb,'Position',[object.pb_offset*3+object.pb_width*2,l_fig_height-object.pb_offset-object.pb_height,object.pb_width,object.pb_height])
            set(object.save_ext_pb,'Position',[object.pb_offset*4+object.pb_width*3,l_fig_height-object.pb_offset-object.pb_height,object.pb_width,object.pb_height])
            set(object.check_pb,'Position',[object.pb_offset*5+object.pb_width*4,l_fig_height-object.pb_offset-object.pb_height,object.pb_width,object.pb_height])
            set(object.pvs_pb,'Position',[object.pb_offset*6+object.pb_width*5,l_fig_height-object.pb_offset-object.pb_height,object.pb_width,object.pb_height])
            set(object.input_pb,'Position',[object.pb_offset*7+object.pb_width*6,l_fig_height-object.pb_offset-object.pb_height,object.pb_width,object.pb_height])
            set(object.settings_pb,'Position',[object.pb_offset*8+object.pb_width*7,l_fig_height-object.pb_offset-object.pb_height,object.pb_width,object.pb_height])
Colin Eles's avatar
Colin Eles committed

            set(object.name_label,'Position',[object.pb_offset l_fig_height-object.pb_offset*3-object.pb_height-object.pb_height object.pb_width object.pb_height]);
            set(object.function_name_control,'Position',[object.pb_offset*2+object.pb_width l_fig_height-object.pb_offset*3-object.pb_height-object.pb_height object.text_width object.pb_height]);
            set(object.input_label,'Position',[object.pb_offset*2+object.pb_width+object.text_width l_fig_height-object.pb_offset*3-object.pb_height-object.pb_height object.pb_width object.pb_height]);
            set(object.function_inputs_control,'Position',[object.pb_offset*3+object.pb_width*2+object.text_width l_fig_height-object.pb_offset*3-object.pb_height-object.pb_height object.text_width object.pb_height]);
Colin Eles's avatar
Colin Eles committed
        end
        
        %% resize_fig
        %    callback function that is called whenever the main figure is
        %    resized. Ensures that the commands remain at the top of the
        %    screen and the grid below them.
        % inputs:
        %   object:GUI - current GUI object
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function [] = resize_fig(object,src,event)
            if(object.initialized == 1)
                object.draw_allgrids(0);
                object.set_command_pos;
            end
        end
        
        %% save_ext_call
        %    callback function that is called whenever the save ext button
        %    is pressed. This function will generate the code for the table
        %    and output it to an external embedded matlab file which can
        %    then be used in other functions. Filename of new file will be
        %    the same as the expression name, currently this function will
        %    overwrite an existing file of the same name.
        % inputs:
        %   object:GUI - current GUI object
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function [] = save_ext_call(object,src,event)
            object.save_data;
Colin Eles's avatar
Colin Eles committed
            % file name will be expression_name.m
            fileid = fopen([get(object.function_name_control,'String') '.m'],'w');
            %code = [];
            %code = sprintf('function output = %s(%s)\n%s\noutput=0;\n',get(object.function_name_control,'String'),get(object.function_inputs_control,'String'),'%%#eml');
            %code = [code object.generate_code(object.Grid1,object.Grid2,0)];
            code = object.EMLGen.generate_eml_code;
Colin Eles's avatar
Colin Eles committed
            fprintf(fileid,code);
            % save an extra file called expression_name.data which
            % contains a binary representation of the current gui object.
            filename = [get(object.function_name_control,'String') '.table'];
Colin Eles's avatar
Colin Eles committed
            %save(filename,'object');
            object.save_data;

            object.save_settings;
Colin Eles's avatar
Colin Eles committed
            object.Data.save;
Colin Eles's avatar
Colin Eles committed
            fclose(fileid);
        end
        
Colin Eles's avatar
Colin Eles committed
        %% input_call
        %   function will open up the ports and data management window if
        %   in simulink mode.
        % inputs:
        %   obj:GUI - GUI objecto
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function [] = input_call(object,src,event)
Colin Eles's avatar
Colin Eles committed
            % make sure in simulink mode.
            if object.mode == 1
                eml_handle = object.save_call([],[]);
               currentDir = pwd;
                cd([matlabroot filesep 'toolbox' filesep 'stateflow' filesep 'stateflow' filesep 'private']);
                fHandle = @eml_man;
                cd(currentDir);
                fHandle('edit_data_ports', sf('get', get_param(char(eml_handle),'UserData'), '.chart')) 
            end
Colin Eles's avatar
Colin Eles committed
        %% input_call
        %   open up the settings window
        % inputs:
        %   obj:GUI - GUI objecto
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function [] = settings_call(object,src,event)
            object.settings.show;
            
        end
Colin Eles's avatar
Colin Eles committed
        
Colin Eles's avatar
Colin Eles committed
        %% pvs_ext_call
Colin Eles's avatar
Colin Eles committed
        %   function will initiate the typechecking procedure for the table
        % inputs:
        %   obj:GUI - GUI objecto
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
Colin Eles's avatar
Colin Eles committed
        function [] = pvs_ext_call(object,src,event)
            error = object.check_call;
Colin Eles's avatar
Colin Eles committed
                if (check == 1)
                       msgbox('table is valid')
                else
                    Valid_Report = ValidationReport(object);
                    Valid_Report.set_results(result);
                    Valid_Report.init();
Colin Eles's avatar
Colin Eles committed
                end
                object.pvs_checked = check;
                object.update_Statusbar;
                TableBlock.set_block_display(object.block_handle,object.pvs_checked)
Colin Eles's avatar
Colin Eles committed
        %% output_data_type
        %   this function will determine what the desired output type of
        %   the function is, based on what the user has selected using the
        %   ports and datamanagement window. if the user has selected an
        %   unconvertable type, (inheret, fixed pt. etc.) it will return
        %   the empty string
        % inputs:
        %   object:GUI - GUI objecto
        % outputs;
        %   type:string - string representation of the output type.
        function type = output_data_type(object)
            if (object.mode == 1)
                S = sfroot;
                code_block = sprintf('%s/code',getfullname(object.block_handle));
Colin Eles's avatar
Colin Eles committed
                code_blocks = find_system(getfullname(object.block_handle),'LookUnderMasks','all','BlockType','SubSystem','Name','code');
                if ~isempty(code_blocks)
                    myState = S.find('-isa','Stateflow.EMChart', '-and', 'Path', code_block); % find which one we want to edit
                    if strncmp(myState.Outputs.DataType,'Inherit',7);
                    elseif strncmp(myState.Outputs.DataType,'boolean',7);
                        type = 'logical';
                    else
                        type = myState.Outputs.DataType;
                    end
                else
                    type = '';
                end
Colin Eles's avatar
Colin Eles committed
        %% save_call
        %    callback function that is called whenever the save button is
        %    pressed. This function will generate code and store it in the
        %    embedded matlab block, it will then generate the corresponding
        %    input and output ports and connect them to the embedded matlab
        %    block.
        % inputs:
        %   object:GUI - current GUI object
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function eml_handle = save_call(object,src,event)
             if(object.check_call([],[]) == 1)
                 return;
             end
            if object.mode == 0
                model = gcs;
                %make sure we are not looking at the library model
                %if (strcmp(model,'eml_lib') || strcmp(model,'simulink'))
                    %create a new model
Colin Eles's avatar
Colin Eles committed
                    found = any(ismember(find_system('type', 'block_diagram'),'Table'))
                    if found == 0
                       
                   
                        new_system('Table','Model')

                    end
                    model = 'Table'
                %end
                open_system(model);
                load_system('TableLibrary');
                new_block = add_block('TableLibrary/Tabular Expression',[model '/' get(object.function_name_control,'String')]);
                set_param(new_block,'UserData',object.Data)
                set_param(new_block, 'UserDataPersistent', 'on');
                object.mode = 1;
                object.block_handle = new_block;
                object.save_call([],[]);
            elseif object.mode == 1
Colin Eles's avatar
Colin Eles committed
                
                load_system('simulink')
                % generate the code
                object.EMLGen.set_datatype(object.output_data_type);
                code = object.EMLGen.generate_eml_code;
                
                %code = [code object.generate_code(object.Grid1,object.Grid2,0)];
                %fprintf('%s',code);
Colin Eles's avatar
Colin Eles committed

Colin Eles's avatar
Colin Eles committed
               eml_handle = TableBlock.set_code(object.block_handle,code,object.Data.function_name);
Colin Eles's avatar
Colin Eles committed

                    TableBlock.set_block_display(object.block_handle,object.pvs_checked);
Colin Eles's avatar
Colin Eles committed
            end
Colin Eles's avatar
Colin Eles committed
        end
        
Colin Eles's avatar
Colin Eles committed
        
        %% check_call
        %   callback function for check pushbutton. compiles a message of
        %   the errors that were detected in each of the grids. outputs the
        %   message to users via a msgbox.
        % inputs:
        %   object:GUI - current GUI object
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs;
        %   none
        function error = check_call(object,src,event)
            error = 0;
            
            msg = object.check_inputs;
            if (isempty(msg))
                set(object.function_inputs_control,'BackgroundColor',[1 1 1])
                msg = object.check_grid_condition(object.Grid2);
                msg = [msg object.check_grid_condition(object.Grid1)];
                msg = [msg object.check_grid_result(object.Grid0)];
            else
                set(object.function_inputs_control,'BackgroundColor',[0.92 0.65 0.65])
            end
            
Colin Eles's avatar
Colin Eles committed
            if ~isempty(msg)
                msgbox(msg);
Colin Eles's avatar
Colin Eles committed
            end
Colin Eles's avatar
Colin Eles committed
        end
        
        %% check_grid
        %    check_grid will recursively loop through all the cells of a
        %    grid and call the check_matlab_syntax function for each of the
        %    strings in the cells. if there is an error the cell will
        %    change colours to alert the user where the problem is.
        % inputs:
        %   object:GUI - current GUI object
        %   grid:Grid - Grid object being checked
        % outputs;
        %   none
        function msg = check_grid_condition(object,grid)
            msg = [];
            for i = 1:size(grid.cells,2)
                
Colin Eles's avatar
Colin Eles committed
                string = get(grid.cells(i).cond,'String');
                
                if ( strcmp(string,'') || isempty(string)) && i == 1 && isempty(grid.parent_grid) && size(grid.cells,2) == 1
                    break
                end
                
Colin Eles's avatar
Colin Eles committed
                % if the string is empty indicating that the table is 1
                % dimensional or the string is "otherwise" skip the syntax
                % checking.
                if(~isempty(string) && ~strcmp(string,'otherwise'))
                    error = object.check_matlab_syntax_condition(char(string),0);
                end
                 if isempty(error)
                    if (strcmp(string,'') || isempty(string))
                    error = 'Cell is empty';
Colin Eles's avatar
Colin Eles committed
                end
                if ~isempty(error)
                    % generate the message string
                    msg = [msg sprintf('\n')];                    

                    msg = [msg 'Condtion -> ' char(string) sprintf('\n')];
Colin Eles's avatar
Colin Eles committed
                    msg = [msg error sprintf('\n')];

                   % set tooltip string of cell to error msg
                    set(grid.cells(i).cond,'TooltipString',error)
                     % change background colour
                    grid.cells(i).flag_cell(1);
                else
                    % reset tooltip and colour if no error found
                    set(grid.cells(i).cond,'TooltipString','')
                    grid.cells(i).flag_cell(0);
                    %if (~isempty(grid.cells(i).color))
                    %    set(grid.cells(i).cond,'BackgroundColor',grid.cells(i).color)
                    %else
                    %   set(grid.cells(i).cond,'BackgroundColor',[1 1 1])
                    %end

                end
                % recurse through subgrid
                if(~isempty(grid.cells(i).subgrid))
                    msg = [msg object.check_grid_condition(grid.cells(i).subgrid)];
                end

                   
            end
        end
        %% check_grid_result
        %   Similar to above function check_grid_result, will loop through
        % the cells of the output grid, unline check_grid, does not need to
        % recurse.
        % inputs:
        %   object:GUI - current GUI object
        %   grid:RGrid - RGrid object to be checked
        % outputs;
        %   none
        function msg = check_grid_result(object,grid)
            msg = [];
            for i = 1:size(grid.Cells,2)
                string = get(grid.Cells(i).result,'String');
                
Colin Eles's avatar
Colin Eles committed

                error = object.check_matlab_syntax_condition(char(string),1);
                if isempty(error)
                    if (strcmp(string,'') || isempty(string))
                    error = 'Cell is empty';
Colin Eles's avatar
Colin Eles committed
                if ~isempty(error)
                     msg = [msg sprintf('\n')];                    

                    msg = [msg 'Result -> ' char(string) sprintf('\n')];
Colin Eles's avatar
Colin Eles committed
                    msg = [msg error sprintf('\n')];


                    set(grid.Cells(i).result,'TooltipString',error)
                    grid.Cells(i).flag_cell(1)
                else
                    set(grid.Cells(i).result,'TooltipString','')
                    grid.Cells(i).flag_cell(0)
                end
                
            end
        end
        
        %% check_matlab_syntax
        %   this function will check that a string is valid matlab syntax
        %   for the context that it is in. we need to build up the
        %   expression which involves initiallizeing the input variables to
        %   a dummy value and wraping an if statement around conditionals
        % inputs:
        %   object:GUI - current GUI object
        %   string:string - string to be checked
        %   result:boolean - false if the string is a conditoin true if
        %       the string is an output statement
        % outputs;
        %   error:string - string containing the error message, empty if
        %   there is no error
        function error = check_matlab_syntax_condition(object,string,result)
Colin Eles's avatar
Colin Eles committed
           % split the list of inputs to get inputs seperatly
           parsed_input = EMLGenerator.parse_inputs(get(object.function_inputs_control,'string'));
Colin Eles's avatar
Colin Eles committed
           check_string = [];
Colin Eles's avatar
Colin Eles committed
           % initialize inputs to zero
           % functions are assumed to be total, so 0 is just for 
           % convienence
Colin Eles's avatar
Colin Eles committed
                % set to zero
                check_string = [check_string sprintf('%s=0;\n',char(parsed_input{i}(1)))];
Colin Eles's avatar
Colin Eles committed
                
                   
           end
           if ~result
                % the string is a condition we need to evaulate it as it
                % will be used in the code, as in order for an if statement
                % to be valid the condition must evaulate to a numeric
                % value not a structure or something else. we need to have
                % the 1 in there as a dummy output, which is necesary for
                % an if statement to be valid in matlab.
                check_string = [check_string 'if (' string sprintf(')\n1;\nend')];
Colin Eles's avatar
Colin Eles committed
           else
               % the string is an output statement we can just evaulate the
               % string on its own.
               check_string = [check_string string ';' sprintf('\n')];
Colin Eles's avatar
Colin Eles committed
           end
           % attempt to evaluate the string catch the error.
           try
               eval(check_string);
               error = [];
           catch exception
               error = exception.message;
Colin Eles's avatar
Colin Eles committed
                % attempt to make one of the common errors slightly less
                % cryptic.
               if(strcmp(exception.identifier,'MATLAB:m_invalid_lhs_of_assignment'))
                   error = [error sprintf('\nTo check equality use ==')];
               end
           end
        end
        
        
Colin Eles's avatar
Colin Eles committed
        
        %% save_conditions
        % this function is used to save the strings that are in each of the
        % condition edit boxes string field. We do this because when we
        % want to reopen the gui we want to repopulate these fields but the
        % handles to the edit boxes will disappear when we close the gui,
        % so we need to save the strings into variables in each of the Cell
        % objects. function is recursive.
        % inputs:
        %   obj:GUI - current GUI object
        %   grid:Grid - grid to be saved.
        % outputs;
        %   none
        function [] = save_conditions(object,grid)
Colin Eles's avatar
Colin Eles committed
            for i=1:size(grid.cells,2)
                if ~isempty(grid.cells(i).subgrid)
                    object.save_conditions(grid.cells(i).subgrid);
Colin Eles's avatar
Colin Eles committed
                end
                grid.cells(i).cond_text = get(grid.cells(i).cond,'String');
            end
        end
        
        %% save_results
        %   Save as save_conditions but for the results grid, since not a
        %   recursive datatype we do not need to recurse.
        % inputs:
        %   obj:GUI - current GUI object
        %   grid:RGrid - results grid to be saved.
        % outputs;
        %   none
        function [] = save_results(object,grid)
Colin Eles's avatar
Colin Eles committed
            for i=1:size(grid.Cells,2)
                grid.Cells(i).result_text = get(grid.Cells(i).result,'String');
            end
        end
        
        %% close_fig
        %    callback function that is called whenever the close button is
        %    pressed. 
        % inputs:
        %   object - current GUI object
        %   src - source of the callback calling
        %   event - event that triggered the callback
        % outputs;
        %   none
        function [] = close_fig(object,src,event)
            object.save_data;
Colin Eles's avatar
Colin Eles committed
            object.Data.open = 0;
            object.Data.fig = [];
            delete(object.fig);
            % remove reference to the old figure.
            object.fig = [];
        end
Colin Eles's avatar
Colin Eles committed
            
        %% save_data
        %    save the current state of the table to the data object so that
        %    it can be saved either in a block or in a binary file
        % inputs:
        %   object:GUI - current GUI object
        % outputs;
        %   none
        function [] = save_data(object)
Colin Eles's avatar
Colin Eles committed
            save_conditions(object,object.Grid2);
            save_conditions(object,object.Grid1);
            save_results(object,object.Grid0);
            object.function_name_text = get(object.function_name_control,'String');
            object.function_inputs_text = get(object.function_inputs_control,'String');
            object.Data.function_name = get(object.function_name_control,'String');
            object.Data.function_inputs = get(object.function_inputs_control,'String');
Colin Eles's avatar
Colin Eles committed
            object.Data.checked = object.pvs_checked;
Colin Eles's avatar
Colin Eles committed
            %object.Data.open = 0;
            %object.Data.fig = [];
            set.set = 1;
            set.inputs = object.settings.pvs_includes;
            set.count = object.settings.counter_trials;
            set.range = object.settings.counter_range;
            object.Data.settings = set;
Colin Eles's avatar
Colin Eles committed
        end
        
Colin Eles's avatar
Colin Eles committed
        %% save_settings
        %    save just the settings to the data object
        % inputs:
        %   object:GUI - current GUI object
        % outputs;
        %   none
        function [] = save_settings(object)
            set.set = 1;
            set.inputs = object.settings.pvs_includes;
            set.count = object.settings.counter_trials;
            set.range = object.settings.counter_range;
            object.Data.settings = set;
            object.Data.function_name = get(object.function_name_control,'String');
            object.Data.function_inputs = get(object.function_inputs_control,'String');
        end
        
Colin Eles's avatar
Colin Eles committed
        %% edit_tog_call
        %    callback function for when the edit button is clicked. when
        %    edit is toggled we want to redraw the table with the edit
        %    button visible or not visible
        % inputs:
        %   object - current GUI object
        %   src - source of the callback calling
        %   event - event that triggered the callback
        % outputs;
        %   none
        function [] = edit_tog_call(object,src,event)
            % save the value of the edit toggle
            value = get(src,'Value');
            object.edit = value;
            % reset the widths and heights of the grid then redraw all the
            % grids.
            object.reset_wh;
            object.draw_allgrids(0);
            
        end
        
        %% set_grid
        %    allows accessing objects to set the grid variables to the
        %    inputed objects
        % inputs:
        %   obj:GUI - current GUI object
        %   grid2:Grid - Grid on the left
        %   grid1:Grid - Grid on the top
        %   grid0:RGrid - Results grid
        % outputs;
        %   none
        function [] = set_grid(object,grid2,grid1,grid0)
            object.Grid2 = grid2;
            object.Grid1 = grid1;
            object.Grid0 = grid0;
Colin Eles's avatar
Colin Eles committed
        end
        
        %% draw_grid2
        %    Draws the grid on the left onto the figure.
        % inputs:
        %   obj:GUI - current GUI object
        %   grid:Grid - grid to be drawn, should be grid on left.
        %   load:boolean - 0 if grid is being refreshed, 1 if grid is being
        %       loaded for the firs time.
        % outputs;
        %   none
        function [] = draw_grid2(object,grid,load)
Colin Eles's avatar
Colin Eles committed
            if (~isempty(grid))
                % generate a random pastel colour for the background, each
                % grid has a different colour to help with readability
                grid_color = [0.9+0.1*rand(1) 0.9+0.1*rand(1) 0.9+0.1*rand(1)];
                for i=1:size(grid.cells,2)
                    % check if the grid is the root grid
                    if (~isempty(grid.parent_cell))
                        % grid is not the root grid location is derived
                        % from its parent.
                        parent_pos = grid.parent_cell.get_pos;
                        if i == 1
                            % if we are at the first cell, location is the
                            % same as the parent but shifted to the right
                            % by one cell
                            pos(3) = grid.cells(i).width * grid.cells(i).condition_text_width;
                            pos(4) = grid.cells(i).height * grid.cells(i).condition_text_height;
                            pos(1) = parent_pos(1) + parent_pos(3);
                            pos(2) = parent_pos(2) + parent_pos(4) - pos(4);
                        else
                            % if we are not at the first cell, location is
                            % the same as the previous cell but we shift