Skip to content
GUI.m 76.5 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
        mode = [];
        
Colin Eles's avatar
Colin Eles committed
    end
    
    methods
        %% GUI
        %   constructor
        % inputs:
        %   h:double - handle to Tabular block in model
        % outputs;
        %   obj:GUI - object that is created
Colin Eles's avatar
Colin Eles committed
        function obj = GUI(h,mode)
Colin Eles's avatar
Colin Eles committed
            obj.block_handle = h;
Colin Eles's avatar
Colin Eles committed
            obj.mode = mode;
Colin Eles's avatar
Colin Eles committed
        end
        
        function [] = setData(obj,Data)
            obj.Data = Data;
            obj.Grid0 = Data.Grid0;
            obj.Grid1 = Data.Grid1;
            obj.Grid2 = Data.Grid2;
            obj.function_name_text = Data.function_name;
            obj.function_inputs_text = Data.function_inputs;
Colin Eles's avatar
Colin Eles committed
            obj.settings = Data.settings;
Colin Eles's avatar
Colin Eles committed
        %% init
        %   initialize the gui
        % inputs:
        %   obj:GUI - GUI object
        % outputs;
        %   none
        function [] = init(obj)
            
            % create the handles for the gui objects
Colin Eles's avatar
Colin Eles committed
            if obj.mode == 1
                name = get_param(obj.block_handle,'Name');
            elseif obj.mode == 0
                name = 'Table Tool';
            end
Colin Eles's avatar
Colin Eles committed
            % main figure
            obj.fig = figure('units','pixels',...
                'position',[0 0 obj.fig_width obj.fig_height],...
                '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,...
Colin Eles's avatar
Colin Eles committed
                '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));
            
            % Input/Output button
            obj.input_pb = uicontrol('style','push',...
                'units','pix',...
                'string','Ports',...
                'HorizontalAlign','left',...
                'Parent',obj.fig,...
                'callback',@(src,event)input_call(obj,src,event));
            
            % Input/Output button
            obj.settings_pb = uicontrol('style','push',...
                'units','pix',...
                'string','Settings',...
                'HorizontalAlign','left',...
                'Parent',obj.fig,...
                'callback',@(src,event)settings_call(obj,src,event));
            
Colin Eles's avatar
Colin Eles committed
            % 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
            
            
            % Set up Menu
            filemenu = uimenu('Label','File');
            editmenu = uimenu('Label','Edit');
            pvsmenu = uimenu('Label','PVS');
            uimenu(filemenu,'Label','New','Accelerator','n');
            uimenu(filemenu,'Label','Open...');
            uimenu(filemenu,'Label','Save to Block','Separator','on');
            uimenu(filemenu,'Label','Save to M-File');
                       
Colin Eles's avatar
Colin Eles committed

            uimenu(editmenu,'Label','Show edit controls','Checked','on');
            uimenu(pvsmenu,'Label','Typecheck');
            uimenu(pvsmenu,'Label','PVS Settings');
Colin Eles's avatar
Colin Eles committed
            
Colin Eles's avatar
Colin Eles committed
            obj.set_command_pos;
            obj.reset_wh();
            obj.draw_allgrids(1);
            
            obj.settings = Settings();
            if isfield(obj.Data.settings,'set')
                obj.settings.setvalues(obj.Data.settings);
            else
                obj.settings.init();
Colin Eles's avatar
Colin Eles committed
                
Colin Eles's avatar
Colin Eles committed
            obj.PVS = PVS_checker(obj,obj.settings);
            
Colin Eles's avatar
Colin Eles committed
            obj.initialized = 1;
Colin Eles's avatar
Colin Eles committed
        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');
Colin Eles's avatar
Colin Eles committed
            % figure out the height of the figure
            l_fig_height = figpos(4);
Colin Eles's avatar
Colin Eles committed
            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.input_pb,'Position',[obj.pb_offset*7+obj.pb_width*6,l_fig_height-obj.pb_offset-obj.pb_height,obj.pb_width,obj.pb_height])
            set(obj.settings_pb,'Position',[obj.pb_offset*8+obj.pb_width*7,l_fig_height-obj.pb_offset-obj.pb_height,obj.pb_width,obj.pb_height])
Colin Eles's avatar
Colin Eles committed

            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');
Colin Eles's avatar
Colin Eles committed
            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'];
Colin Eles's avatar
Colin Eles committed
            %save(filename,'object');
            object.save_settings;
Colin Eles's avatar
Colin Eles committed
            object.Data.save;
Colin Eles's avatar
Colin Eles committed
            fclose(fileid);
        end
        
        %%
        function [] = input_call(object,src,event)
            %da = DAStudio.ModelExplorer
            %dataddg
            modelddg(object.block_handle)
                
            %da.show;
            %da = DAStudio.DiagnosticViewer('test');
        end
        
         %%
        function [] = settings_call(object,src,event)
            object.settings.show;
            
        end
Colin Eles's avatar
Colin Eles committed
        %% 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)
Colin Eles's avatar
Colin Eles committed
            if object.mode == 1
                
                load_system('simulink')
                % generate the code
                code = [];
Colin Eles's avatar
Colin Eles committed
                %generate input list
                parsed_input = object.parse_inputs(get(object.function_inputs_control,'string'));
                input = [];
                for i= 1:size(parsed_input,2)
                    input = [input char(parsed_input{i}(1)) ','];
Colin Eles's avatar
Colin Eles committed
                code = sprintf('function output = %s(%s)\n',get(object.function_name_control,'String'),input);
                % simulink forces you to have an output for all execution paths
                % since it can't compute completness and disjointness we need
                % to have a default value, if the user builds the table
                % properly the default value will never be used. since
                % different types might have a different default value, the
                % temporary solution is just to use one of the outputs from our
                % table, we will use the first cell because it is guaranteed to
                % be filled in, regardless of the dimensionality of the table.
                code = [code sprintf('output=%s;\n',get(object.Grid0.Cells(1).result,'String'))];
                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
                % 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

                if (~strcmp(get(object.block_handle,'Name'),get(object.function_name_control,'String')))
                    try
                    set_param(object.block_handle,'Name',get(object.function_name_control,'String'));
                    catch exception
                        msgbox(exception.message);
Colin Eles's avatar
Colin Eles committed
                    end
                end

Colin Eles's avatar
Colin Eles committed
                % 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);
Colin Eles's avatar
Colin Eles committed
                end
Colin Eles's avatar
Colin Eles committed

                % 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);
Colin Eles's avatar
Colin Eles committed
                end
Colin Eles's avatar
Colin Eles committed

                % 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');
Colin Eles's avatar
Colin Eles committed
                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;
Colin Eles's avatar
Colin Eles committed
                        end
                    end
Colin Eles's avatar
Colin Eles committed

                    if (~found)
                        % old inport no longer exists
                        delete_block(inports(i));
Colin Eles's avatar
Colin Eles committed
                    end
                end
Colin Eles's avatar
Colin Eles committed

                % 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


Colin Eles's avatar
Colin Eles committed
                end
Colin Eles's avatar
Colin Eles committed


                % Next we do the same thing with the outputs
                outports = find_system(getfullname(object.block_handle),'BlockType','Outport');
Colin Eles's avatar
Colin Eles committed
                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;
Colin Eles's avatar
Colin Eles committed
                        end
                    end
Colin Eles's avatar
Colin Eles committed

                    if (~found)
                        % old inport no longer exists
                        delete_block(outports(i));
                    end
Colin Eles's avatar
Colin Eles committed
                end

Colin Eles's avatar
Colin Eles committed
                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
Colin Eles's avatar
Colin Eles committed
                    end
Colin Eles's avatar
Colin Eles committed
                    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
Colin Eles's avatar
Colin Eles committed
        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;
            
            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(obj,string,result)
           % split the list of inputs to get inputs seperatly
           parsed_input = obj.parse_inputs(get(obj.function_inputs_control,'string'));
           %inputs = get(obj.function_inputs_control,'String');
           %inputs = regexp(inputs,',','split');
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
        
        
                 %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');
Colin Eles's avatar
Colin Eles committed
           
            % 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'))))];
Colin Eles's avatar
Colin Eles committed
                        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)];
Colin Eles's avatar
Colin Eles committed
                        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));
Colin Eles's avatar
Colin Eles committed
                    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'))))];
Colin Eles's avatar
Colin Eles committed
                        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)];
Colin Eles's avatar
Colin Eles committed
                        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');
Colin Eles's avatar
Colin Eles committed
                    if (strcmp(g2cond,'otherwise'))
                        elsecell = g2.cells(i);
Colin Eles's avatar
Colin Eles committed
                        elseindex = i;
Colin Eles's avatar
Colin Eles committed
                        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');
Colin Eles's avatar
Colin Eles committed
                            if (strcmp(g1cond,'otherwise'))
                                elsecell1 = g1.cells(j);
                                found1 = 1;
Colin Eles's avatar
Colin Eles committed
                                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'))))];
Colin Eles's avatar
Colin Eles committed
                                    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)];
Colin Eles's avatar
Colin Eles committed
                                    depth = depth - 1;
                                    space = [];
                                    for k=1:depth
                                        space = [space sprintf('  ')];
                                    end
                                end
                                
                            end
                        end
                        if(~isempty(g1cond1))