Skip to content
GUI.m 66.6 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 = [];
        function_name_control = [];
        function_name_text = [];
        function_inputs_text = [];
        function_inputs_control = [];
        edit = 1;
        initialized = 0;
        block_handle = [];
        % height of header where buttons and text is
        header_height = 100;
        % window size
        fig_height = 500;
        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 = [];
        
        PVS = [];
        
    end
    
    methods
        %% GUI
        %   constructor
        % inputs:
        %   h:double - handle to Tabular block in model
        % outputs;
        %   obj:GUI - object that is created
        function obj = GUI(h)
            obj.block_handle = h;
        end
        
        %% init
        %   initialize the gui
        % inputs:
        %   obj:GUI - GUI object
        % outputs;
        %   none
        function [] = init(obj)
            
            % create the handles for the gui objects
            
            % main figure
            obj.fig = figure('units','pixels',...
                'position',[0 0 obj.fig_width obj.fig_height],...
                'menubar','none',...
                'name','GUI_1',...
                'numbertitle','off',...
                'resize','on',...
                'Name',get_param(obj.block_handle,'Name'),...
                'CloseRequestFcn',@(src,event)close_fig(obj,src,event),...
                'ResizeFcn',@(src,event)resize_fig(obj,src,event));
          
            
            % edit button
            obj.edit_tog = uicontrol('style','toggle',...
                'units','pix',...
                'string','Edit',...
                'HorizontalAlign','left',...
                'Parent',obj.fig,...
                'Value',obj.edit,...
                'callback',@(src,event)edit_tog_call(obj,src,event));
            
            % Save button
            obj.save_pb = uicontrol('style','push',...
                'units','pix',...
                'string','Save',...
                'HorizontalAlign','left',...
                'Parent',obj.fig,...
                'callback',@(src,event)save_call(obj,src,event));
            
            % Close button
            obj.close_pb = uicontrol('style','push',...
                'units','pix',...
                'string','Close',...
                'HorizontalAlign','left',...
                'Parent',obj.fig,...
                'callback',@(src,event)close_fig(obj,src,event));
            
            % Save external button
            obj.save_ext_pb = uicontrol('style','push',...
                'units','pix',...
                'string','Save Ext',...
                'HorizontalAlign','left',...
                'Parent',obj.fig,...
                'callback',@(src,event)save_ext_call(obj,src,event));
            
            % PVS button
            obj.pvs_pb = uicontrol('style','push',...
                'units','pix',...
                'string','PVS',...
                'HorizontalAlign','left',...
                'Parent',obj.fig,...
                'callback',@(src,event)pvs_ext_call(obj,src,event));
            
            % Check button
            obj.check_pb = uicontrol('style','push',...
                'units','pix',...
                'string','Check',...
                'HorizontalAlign','left',...
                'Parent',obj.fig,...
                'callback',@(src,event)check_call(obj,src,event));
            
            % Expression Name Label
            obj.name_label = uicontrol('style','text',...
                'string','Expression Name',...
                'HorizontalAlign','right',...
                'BackgroundColor',get(obj.fig,'Color'));
            
            % Expression Name Edit box
            obj.function_name_control = uicontrol('style','edit',...
                'units','pix',...
                'Parent',obj.fig,...
                'HorizontalAlign','center',...
                'FontWeight','bold',...
                'FontSize',12,...
                'Max',2.0,...
                'BackgroundColor',[1 1 1]);
            
            % input list label
            obj.input_label = uicontrol('style','text',...
                'string','Inputs',...
                'HorizontalAlign','right',...
                'BackgroundColor',get(obj.fig,'Color'));
            
            % input list edit box
            obj.function_inputs_control = uicontrol('style','edit',...
                'units','pix',...
                'Parent',obj.fig,...
                'HorizontalAlign','center',...
                'FontWeight','bold',...
                'Max',2.0,...
                'FontSize',12,...
                'BackgroundColor',[1 1 1]);
            
            % load the function name and inputs
            if (~isempty(obj.function_name_text))
                set(obj.function_name_control,'String',obj.function_name_text);
            end
            if (~isempty(obj.function_inputs_text))
                set(obj.function_inputs_control,'String',obj.function_inputs_text);
            end

            obj.PVS = PVS_checker(obj);
            
            obj.set_command_pos;
            obj.reset_wh();
            obj.draw_allgrids(1);
            obj.initialized = 1;
        end
        
        %% 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(obj)
            figpos = get(obj.fig,'Position')
            % figure out the height of the figure
            l_fig_height = figpos(4)
            set(obj.edit_tog,'Position',[obj.pb_offset l_fig_height-obj.pb_offset-obj.pb_height obj.pb_width obj.pb_height])
            set(obj.save_pb,'Position',[obj.pb_offset*2+obj.pb_width,l_fig_height-obj.pb_offset-obj.pb_height,obj.pb_width,obj.pb_height])
            set(obj.close_pb,'Position',[obj.pb_offset*3+obj.pb_width*2,l_fig_height-obj.pb_offset-obj.pb_height,obj.pb_width,obj.pb_height])
            set(obj.save_ext_pb,'Position',[obj.pb_offset*4+obj.pb_width*3,l_fig_height-obj.pb_offset-obj.pb_height,obj.pb_width,obj.pb_height])
            set(obj.check_pb,'Position',[obj.pb_offset*5+obj.pb_width*4,l_fig_height-obj.pb_offset-obj.pb_height,obj.pb_width,obj.pb_height])
            set(obj.pvs_pb,'Position',[obj.pb_offset*6+obj.pb_width*5,l_fig_height-obj.pb_offset-obj.pb_height,obj.pb_width,obj.pb_height])

            set(obj.name_label,'Position',[obj.pb_offset l_fig_height-obj.pb_offset*3-obj.pb_height-obj.pb_height obj.pb_width obj.pb_height]);
            set(obj.function_name_control,'Position',[obj.pb_offset*2+obj.pb_width l_fig_height-obj.pb_offset*3-obj.pb_height-obj.pb_height obj.text_width obj.pb_height]);
            set(obj.input_label,'Position',[obj.pb_offset*2+obj.pb_width+obj.text_width l_fig_height-obj.pb_offset*3-obj.pb_height-obj.pb_height obj.pb_width obj.pb_height]);
            set(obj.function_inputs_control,'Position',[obj.pb_offset*3+obj.pb_width*2+obj.text_width l_fig_height-obj.pb_offset*3-obj.pb_height-obj.pb_height obj.text_width obj.pb_height]);
        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)
            % 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)];
          
            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') '.data']
            save(filename,'object');
            fclose(fileid);
        end
        
        %% pvs_ext_call
        function [] = pvs_ext_call(object,src,event)
            error = object.check_call;
            if (~error)
                object.PVS.pvs_check;
            end
Colin Eles's avatar
Colin Eles committed

        end
        
        
        %% msgbox_scroll
        function [] = msgbox_scroll(obj,msg)
            fig = figure('units','pixels',...
                'position',[0 0 700 500],...
                'menubar','none',...
                'name','PVS Report',...       
                'numbertitle','off');
            
        uicontrol('style','edit',...
                'units','pix',...
                'Parent',fig,...
                'HorizontalAlign','center',...
                'FontWeight','bold',...
                'FontSize',12,...
                'Max',2.0,...
                'HorizontalAlign','left',...
                'String',msg,...
                'Position',[1 1 698 498],...
                'BackgroundColor',[1 1 1]);
            
        end
        
        %% 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 [] = save_call(object,src,event)
            load_system('simulink')
            % generate the code
            code = [];
            code = sprintf('function output = %s(%s)\noutput=0;\n',get(object.function_name_control,'String'),get(object.function_inputs_control,'String'))
            code = [code object.generate_code(object.Grid1,object.Grid2,0)];
            fprintf('%s',code);
            
            % unlink the block from the library, this is necessary if
            % we
            % want to change the subsystem of the block.
            set_param(object.block_handle,'LinkStatus','none')
            
            % determine if the name already exists in the model
            try
            set_param(object.block_handle,'Name',get(object.function_name_control,'String'));
            catch exception
                msgbox(exception.message);
            end
            
            % embedded matlab code block store code in stateflow states so
            % we need to get the root hande
            S = sfroot;
                
            % get the path of the code block
            code_block = sprintf('%s/code',getfullname(object.block_handle));

            % determine if code block already exists
            code_blocks = find_system(getfullname(object.block_handle),'BlockType','SubSystem','Name','code')
            
            % if the code block does not already exists we need to create a
            % new one
            if (isempty(code_blocks))
                add_block('simulink/User-Defined Functions/Embedded MATLAB Function',code_block);
            end
            
            % find the state of the code block and update it to the new
            % code
            myState = S.find('-isa','Stateflow.EMChart', '-and', 'Path', code_block); % find which one we want to edit
            
            if (~isempty(myState))
                myState.Script =  sprintf('%s',code);
            end
            
            % delete any lines that are unconnected and one end or both
            % code from
            % http://www.mathworks.com/matlabcentral/fileexchange/12352-delete-unconnected-lines
            % Copyright (c) 2009, Per-Anders Ekström
                % delete all the lines
                lines = find_system( getfullname(object.block_handle), ...
                'LookUnderMasks', 'all', ...
                'FindAll', 'on', ...
                'Type', 'line' ) ;


                % for each line, call delete_recursive if handle still exist
                for i=1:length( lines )
                    if ishandle( lines( i ) )
                        object.delete_recursive( lines( i ) )
                    end
                end
            % end copyright

            % we need to determine which of the inports and outports we
            % need to create and delete. Whenever we delete a port anything
            % connected with this port is unconnected, other blocks, scopes
            % etc. We would like to avoid this if possible because it can
            % be quite annoying.
            
            % First loop through all the inport blocks, if there does not
            % exists an inport in the code block of the same name then
            % delete the inport block
            inports = find_system(getfullname(object.block_handle),'BlockType','Inport');
            for i=1:size(inports,1)
                found = 0;
                in_handles=find_system(code_block, 'SearchDepth',1,'FindAll','On','FollowLinks','On','LookUnderMasks','All','BlockType','Inport');
            
                for j=1:size(in_handles,1)
                    if strcmp(get_param(inports(i),'Name'),get_param(in_handles(j),'Name'))
                        found = 1;
                    end
                end
                
                if (~found)
                    % old inport no longer exists
                    delete_block(inports(i));
                end
            end
            
            % now we loop through all the inports in the code block if
            % there is an inport block of the same name then connect them,
            % else create a new inport block and connect them
            in_handles=find_system(code_block, 'SearchDepth',1,'FindAll','On','FollowLinks','On','LookUnderMasks','All','BlockType','Inport');
            for j = 1:size(in_handles,1)
                found = 0;
                inports = find_system(getfullname(object.block_handle),'BlockType','Inport')
                for i = 1:size(inports,1)
                    if strcmp(get_param(inports(i),'Name'),get_param(in_handles(j),'Name'))
                        found = 1;
                        
                        % draw the line
                        new_port_num = sprintf('%s/1',get_param(in_handles(j),'Name'));
                        dest_port = sprintf('%s/%d','code',j);
                        try
                        add_line(getfullname(object.block_handle),new_port_num,dest_port);
                        end
                    end
                end
                if (~found)
                   new_port = sprintf('%s/%s',getfullname(object.block_handle),get_param(in_handles(j),'Name'))
                   add_block('simulink/Sources/In1',new_port)
                   new_port_num = sprintf('%s/1',get_param(in_handles(j),'Name'));
                dest_port = sprintf('%s/%d','code',j);
                % sometimes line will be created automatically
                try       
                add_line(getfullname(object.block_handle),new_port_num,dest_port);
                end
                end
                
                
            end
            
            
            % Next we do the same thing with the outputs
            outports = find_system(getfullname(object.block_handle),'BlockType','Outport')
            for i=1:size(outports,1)
                found = 0;
                out_handles=find_system(code_block, 'SearchDepth',1,'FindAll','On','FollowLinks','On','LookUnderMasks','All','BlockType','Outport');
            
                for j=1:size(out_handles,1)
                    if strcmp(get_param(outports(i),'Name'),get_param(out_handles(j),'Name'))
                        found = 1;
                    end
                end
                
                if (~found)
                    % old inport no longer exists
                    delete_block(outports(i));
                end
            end
            
            out_handles=find_system(code_block, 'SearchDepth',1,'FindAll','On','FollowLinks','On','LookUnderMasks','All','BlockType','Outport');
            for j = 1:size(out_handles,1)
                found = 0;
                outports = find_system(getfullname(object.block_handle),'BlockType','Outport')
                for i = 1:size(outports,1)
                    if strcmp(get_param(outports(i),'Name'),get_param(out_handles(j),'Name'))
                        found = 1;
                        
                        % draw the line
                        new_port_num = sprintf('%s/1',get_param(out_handles(j),'Name'));
                        dest_port = sprintf('%s/%d','code',j);
                        try
                        add_line(getfullname(object.block_handle),dest_port,new_port_num);
                        end
                    end
                end
                if (~found)
                   new_port = sprintf('%s/%s',getfullname(object.block_handle),get_param(out_handles(j),'Name'))
                   add_block('simulink/Sinks/Out1',new_port)
                   new_port_num = sprintf('%s/1',get_param(out_handles(j),'Name'));
                dest_port = sprintf('%s/%d','code',j);
                try       
                add_line(getfullname(object.block_handle),dest_port,new_port_num);
                end
                end
            end
            
            % delete any lines that are unconnected and one end or both
            % again sometimes extra lines are created
            % code from
            % http://www.mathworks.com/matlabcentral/fileexchange/12352-delete-unconnected-lines
            % Copyright (c) 2009, Per-Anders Ekström
                % delete all the lines 
                lines = find_system( getfullname(object.block_handle), ...
                    'LookUnderMasks', 'all', ...
                    'FindAll', 'on', ...
                    'Type', 'line' ) ;

                % for each line, call delete_recursive if handle still exist
                for i=1:length( lines )
                    if ishandle( lines( i ) )
                        object.delete_recursive( lines( i ) )
                    end
                end   
            % end copyright
          
            % save the text from each of the conditions and results text
            % boxes.
            save_conditions(object,object.Grid2);
            save_conditions(object,object.Grid1);
            save_results(object,object.Grid0);
            % save the function name and input text from the respective
            % edit boxes.
            object.function_name_text = get(object.function_name_control,'String')
            object.function_inputs_text = get(object.function_inputs_control,'String')
        end
        
        %% delete_recursive
        % delete any lines that are unconnected and one end or both
        % code from
        % http://www.mathworks.com/matlabcentral/fileexchange/12352-delete-unconnected-lines
        % Copyright (c) 2009, Per-Anders Ekström
            function delete_recursive( obj, line )
            %DELETE_RECURSIVE( LINE )  Delete line if:
            %   1) do not have any source-block
            %   2) do not have any line-children AND no destination-block
            %   otherwise go recursively through all eventual line-children

                if get( line, 'SrcPortHandle' ) < 0
                    delete_line( line ) ;
                    return
                end
                LineChildren = get( line, 'LineChildren' ) ;
                if isempty( LineChildren )
                    if get( line, 'DstPortHandle' ) < 0
                        delete_line( line ) ;
                    end
                else
                    for i=1:length( LineChildren )
                        obj.delete_recursive( LineChildren( i ) )
                    end
                end
            end
        % end copyright
        
        %% 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;
Colin Eles's avatar
Colin Eles committed
            msg = object.check_grid_condition(object.Grid2);
            msg = [msg object.check_grid_condition(object.Grid1)];
            msg = [msg object.check_grid_result(object.Grid0)];
            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'
                    end
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')]
                    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)
                error = ''
                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'
                    end
                end
Colin Eles's avatar
Colin Eles committed
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
                if ~isempty(error)
                     msg = [msg sprintf('\n')];                    

                    msg = [msg 'Result -> ' char(string) sprintf('\n')]
                    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(obj,string,result)
           % split the list of inputs to get inputs seperatly
           inputs = get(obj.function_inputs_control,'String');
           inputs = regexp(inputs,',','split');
           check_string = [];
           % initialize inputs to zero
           % functions are assumed to be total, so 0 is just for 
           % convienence
           for i=1:size(inputs,2)
                % set to zero
                check_string = [check_string sprintf('%s=0\n',char(inputs(i)))];
                
                   
           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')];
           else
               % the string is an output statement we can just evaulate the
               % string on its own.
               check_string = [check_string string sprintf('\n')];
           end
           % attempt to evaluate the string catch the error.
           try
               eval(check_string);
               error = [];
           catch exception
               error = exception.message
                % 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
        
        
                 %NEEDS TO BE CLEANED UP!
        %% generate_code
        %   this function will generate a string that represents the
        %   embedded matlab code. code will have proper syntax
        %   indentations.
        % inputs:
        %   obj:GUI - current GUI object
        %   g1:Grid - the grid on the top
        %   g2:Grid - the grid on the left
        %   depth:integer - the depth of the current call, incremented
        %      every recursive call, initial value should be 0. used for
        %      indenting the code.
        % outputs;
        %   error:string - string containing the error message, empty if
        %   there is no error
        function code = generate_code(obj,g1,g2,depth)
            space = '';
            % space is equal to 2 * depth number of ' '
            for i=1:depth
                space = [space sprintf('  ')];
            end
            code = [];
            g1cond1 = get(g1.cells(1).cond,'String')
            g2cond1 = get(g2.cells(1).cond,'String')
           
            % 1D horizontal table
            if (isempty(g2cond1) && ~isempty(g1cond1))
                found = 0;
                elsecell = [];
                for j=1:size(g1.cells,2)
                    g1cond = get(g1.cells(j).cond,'String');
                    % condition string of otherwise corresponds to an else
                    % statement, we allow this statement to be in any order
                    % in the cells of the grid, so we need to find where it
                    % is, if it exists.
                    if (strcmp(g1cond,'otherwise'))
                        elsecell = g1.cells(j);
                        found = 1;
                        continue
                    end
                    if (j == 1 || (j==2 && found == 1))
                        code = [code sprintf('%sif(%s)\n',space,strtrim(char(get(g1.cells(j).cond,'String'))))];
                    else
                        code = [code sprintf('%selseif(%s)\n',space,strtrim(char(get(g1.cells(j).cond,'String'))))];
                    end
                    
                    cell = obj.Grid0.search_return(g1.cells(j),g2.cells(1));
                    if(~isempty(cell))
                        depth = depth + 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                        code = [code sprintf('%soutput = %s;\n',space,strtrim(char(get(cell.result,'String'))))]
                        depth = depth - 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                    else
                        depth = depth + 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                        code = [code sprintf('%smissing!!!\n',space)]
                        depth = depth - 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                    end
                    
                end
                if (~isempty(elsecell))
                    code = [code sprintf('%selse\n',space)];

                    cell = obj.Grid0.search_return(elsecell,g2.cells(1))
                    if(~isempty(cell))
                        depth = depth + 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                        code = [code sprintf('%soutput = %s;\n',space,strtrim(char(get(cell.result,'String'))))]
                        depth = depth - 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                    else
                        depth = depth + 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                        code = [code sprintf('%smissing!!!\n',space)]
                        depth = depth - 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                    end
                end
                code = [code sprintf('%send\n',space)];

            %either 2D table, 1D vertical table or empty table    
            else
                found = 0;
                elsecell = [];
                for i=1:size(g2.cells,2)
                    g2cond = get(g2.cells(i).cond,'String')
                    if (strcmp(g2cond,'otherwise'))
                        elsecell = g2.cells(i)
                        elseindex = i;
                        found = 1
                        continue
                    end

                    if (i == 1 || (i == 2 && found == 1))
                        code = [code sprintf('%sif(%s)\n',space,strtrim(char(get(g2.cells(i).cond,'String'))))];
                    else
                        code = [code sprintf('%selseif(%s)\n',space,strtrim(char(get(g2.cells(i).cond,'String'))))];
                    end
                    
                    if (~isempty(g2.cells(i).subgrid))
                        code = [code obj.generate_code(g1,g2.cells(i).subgrid,depth+1)];
                    else
                        depth = depth + 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                        found1 = 0;
                        elsecell1 = [];
                        for j=1:size(g1.cells,2)
                             g1cond = get(g1.cells(j).cond,'String')
                            if (strcmp(g1cond,'otherwise'))
                                elsecell1 = g1.cells(j)
                                found1 = 1
                                continue
                            end
                            
                            if(~isempty(g1.cells(j).subgrid))
                                %%TODO if add more dimensions to grid1
                            else
                                if (~isempty(g1cond1))
                                    if (j == 1 || (j==2 && found1 == 1))
                                        code = [code sprintf('%sif(%s)\n',space,strtrim(char(get(g1.cells(j).cond,'String'))))];
                                    else
                                        code = [code sprintf('%selseif(%s)\n',space,strtrim(char(get(g1.cells(j).cond,'String'))))];
                                    end
                                end
                                
                                cell = obj.Grid0.search_return(g1.cells(j),g2.cells(i))
                                if(~isempty(cell))
                                    depth = depth + 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                    code = [code sprintf('%soutput = %s;\n',space,strtrim(char(get(cell.result,'String'))))]
                                    depth = depth - 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                else
                                    depth = depth + 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                    code = [code sprintf('%smissing!!!\n',space)]
                                    depth = depth - 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                end
                                
                            end
                        end
                        if(~isempty(g1cond1))
                            if(size(g1.cells,2)>0)
                                if (~isempty(elsecell1))
                                    code = [code sprintf('%selse\n',space)];

                                    cell = obj.Grid0.search_return(elsecell1,g2.cells(i))
                                    if(~isempty(cell))
                                        depth = depth + 1;
                                        space = [];
                                        for k=1:depth
                                            space = [space sprintf('  ')];
                                        end
                                        code = [code sprintf('%soutput = %s;\n',space,strtrim(char(get(cell.result,'String'))))]
                                        depth = depth - 1;
                                        space = [];
                                        for k=1:depth
                                            space = [space sprintf('  ')];
                                        end
                                    else
                                        depth = depth + 1;
                                        space = [];
                                        for k=1:depth
                                            space = [space sprintf('  ')];
                                        end
                                        code = [code sprintf('%smissing!!!\n',space)]
                                        depth = depth - 1;
                                        space = [];
                                        for k=1:depth
                                            space = [space sprintf('  ')];
                                        end
                                    end
                                end
                                code = [code sprintf('%send\n',space)];
                            end
                        end
                        depth = depth - 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                    end
                    
                end
                
                if(~isempty(elsecell))
                    code = [code sprintf('%selse\n',space)];
                    if (~isempty(g2.cells(elseindex).subgrid))
                        code = [code obj.generate_code(g1,g2.cells(elseindex).subgrid,depth+1)];
                    else
                        depth = depth + 1;
                        space = [];
                        for k=1:depth
                            space = [space sprintf('  ')];
                        end
                        found1 = 0;
                        for j=1:size(g1.cells,2)
                             g1cond = get(g1.cells(j).cond,'String')
                            if (strcmp(g1cond,'otherwise'))
                                elsecell1 = g1.cells(j)
                                found1 = 1
                                continue
                            end
                            
                            if(~isempty(g1.cells(j).subgrid))
                                %%TODO if add more dimensions to grid1
                            else
                                if (~isempty(g1cond1))
                                    if (j == 1 || (j==2 && found1 == 1))
                                        code = [code sprintf('%sif(%s)\n',space,strtrim(char(get(g1.cells(j).cond,'String'))))];
                                    else
                                        code = [code sprintf('%selseif(%s)\n',space,strtrim(char(get(g1.cells(j).cond,'String'))))];
                                    end
                                end
                                
                                cell = obj.Grid0.search_return(g1.cells(j),g2.cells(elseindex))
                                if(~isempty(cell))
                                    depth = depth + 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                    code = [code sprintf('%soutput = %s;\n',space,strtrim(char(get(cell.result,'String'))))]
                                    depth = depth - 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                else
                                    depth = depth + 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                    code = [code sprintf('%smissing!!!\n',space)]
                                    depth = depth - 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                end
                                
                            end
                        end
                        if(~isempty(g1cond1))
                            if(size(g1.cells,2)>0)
                                if (~isempty(elsecell1))
                                    code = [code sprintf('%selse\n',space)];

                                    cell = obj.Grid0.search_return(elsecell1,g2.cells(elseindex))
                                    if(~isempty(cell))
                                        depth = depth + 1;
                                        space = [];
                                        for k=1:depth
                                            space = [space sprintf('  ')];
                                        end
                                        code = [code sprintf('%soutput = %s;\n',space,strtrim(char(get(cell.result,'String'))))]
                                        depth = depth - 1;
                                        space = [];
                                        for k=1:depth
                                            space = [space sprintf('  ')];
                                        end