Newer
Older
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 = [];
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
Colin Eles
committed
fig_height = 600;
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
committed
Data = [];
end
methods
%% GUI
% constructor
% inputs:
% h:double - handle to Tabular block in model
% outputs;
% obj:GUI - object that is created
Colin Eles
committed
function [] = setData(obj,Data)
obj.Data = Data;
obj.Grid0 = Data.Grid0;
obj.Grid1 = Data.Grid1;
obj.Grid2 = Data.Grid2;
Colin Eles
committed
obj.function_name_text = Data.function_name;
obj.function_inputs_text = Data.function_inputs;
Colin Eles
committed
end
%% init
% initialize the gui
% inputs:
% obj:GUI - GUI object
% outputs;
% none
function [] = init(obj)
% create the handles for the gui objects
if obj.mode == 1
name = get_param(obj.block_handle,'Name');
elseif obj.mode == 0
name = 'Table Tool';
end
% main figure
obj.fig = figure('units','pixels',...
'position',[0 0 obj.fig_width obj.fig_height],...
'menubar','none',...
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
'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));
obj.settings_pb = uicontrol('style','push',...
'units','pix',...
'string','Settings',...
'HorizontalAlign','left',...
'Parent',obj.fig,...
'callback',@(src,event)settings_call(obj,src,event));
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
% 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','Callback',@(src,event)new_call(obj,src,event));
uimenu(filemenu,'Label','Open...','Callback',@(src,event)open_call(obj,src,event));
uimenu(filemenu,'Label','Save to Block','Separator','on','Accelerator','s','Callback',@(src,event)save_call(obj,src,event));
uimenu(filemenu,'Label','Save to M-File','Callback',@(src,event)save_ext_call(obj,src,event));
uimenu(filemenu,'Label','Close','Accelerator','w','Separator','on','Callback',@(src,event)close_fig(obj,src,event));
uimenu(editmenu,'Label','Show edit controls','Checked','on');
uimenu(editmenu,'Label','Ports and Data Manager','Accelerator','p','Callback',@(src,event)input_call(obj,src,event));
uimenu(pvsmenu,'Label','Typecheck','Accelerator','t','Callback',@(src,event)pvs_ext_call(obj,src,event));
uimenu(pvsmenu,'Label','PVS Settings','Callback',@(src,event)settings_call(obj,src,event));
obj.set_command_pos;
obj.reset_wh();
obj.draw_allgrids(1);
Colin Eles
committed
obj.setPBenable;
if isfield(obj.Data.settings,'set')
obj.settings.setvalues(obj.Data.settings);
else
obj.settings.init();
Colin Eles
committed
obj.Data.open = 1;
obj.Data.fig = obj.fig;
function [] = update_Statusbar(object)
warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame
% statusbar depends on JavaFrame which may be obsolete in
% future versions of Matlab, can still use in old versions
try
if (object.pvs_checked == 0)
sb = statusbar(object.fig, 'Status: Not Typechecked');
set(sb.TextPanel,'Foreground',[1,0,0]);
elseif (object.pvs_checked == 1)
sb = statusbar(object.fig, 'Status: Typechecked');
set(sb.TextPanel,'Foreground',[0,1,0]);
end
catch exception
end
end
function [] = new_call(object,src,event)
TableToolMatlab
end
function [] = open_call(object,src,event)
[FileName, PathName, FilterIndex] = uigetfile('*.table','Select pvs files');
if ~isempty(FileName)
TTdiag('Load',[PathName FileName]);
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');
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.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])
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
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') '.table'];
%%
function [] = input_call(object,src,event)
eml_handle = object.save_call([],[]);
currentDir = pwd;
cd([matlabroot filesep 'toolbox' filesep 'stateflow' filesep 'stateflow' filesep 'private']);
fHandle = @eml_man;
cd(currentDir);
fHandle('edit_data_ports', sf('get', get_param(char(eml_handle),'UserData'), '.chart'))
end
%%
function [] = settings_call(object,src,event)
object.settings.show;
end
%% pvs_ext_call
function [] = pvs_ext_call(object,src,event)
error = object.check_call;
if (~error)
check = object.PVS.pvs_check;
if (check == 1)
msgbox('table is valid')
end
object.pvs_checked = check;
object.update_Statusbar;
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
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 eml_handle = save_call(object,src,event)
if object.mode == 0
model = gcs;
%make sure we are not looking at the library model
%if (strcmp(model,'eml_lib') || strcmp(model,'simulink'))
%create a new model
found = any(ismember(find_system('type', 'block_diagram'),'Table'))
if found == 0
new_system('Table','Model')
end
model = 'Table'
%end
open_system(model);
load_system('TableLibrary');
new_block = add_block('TableLibrary/Tabular Expression',[model '/' get(object.function_name_control,'String')]);
set_param(new_block,'UserData',object.Data)
set_param(new_block, 'UserDataPersistent', 'on');
object.mode = 1;
object.block_handle = new_block;
object.save_call([],[]);
elseif object.mode == 1
load_system('simulink')
% generate the code
code = [];
%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)) ','];
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);
% 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);
% 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))
code_blocks = add_block('simulink/User-Defined Functions/Embedded MATLAB Function',code_block);
% 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);
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
% 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;
if (~found)
% old inport no longer exists
delete_block(inports(i));
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
% 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
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;
if (~found)
% old inport no longer exists
delete_block(outports(i));
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
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
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
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
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
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)
if ( strcmp(string,'') || isempty(string)) && i == 1 && isempty(grid.parent_grid) && size(grid.cells,2) == 1
break
end
% 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
if ~isempty(error)
% generate the message string
msg = [msg sprintf('\n')];
msg = [msg 'Condtion -> ' char(string) sprintf('\n')];
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
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');
error = object.check_matlab_syntax_condition(char(string),1);
if isempty(error)
if (strcmp(string,'') || isempty(string))
error = 'Cell is empty';
if ~isempty(error)
msg = [msg sprintf('\n')];
msg = [msg 'Result -> ' char(string) sprintf('\n')];
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
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');
% initialize inputs to zero
% functions are assumed to be total, so 0 is just for
% convienence
for i=1:size(parsed_input,2)
check_string = [check_string sprintf('%s=0;\n',char(parsed_input{i}(1)))];
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');
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
% 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');
elsecell = g2.cells(i);