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 = [];
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
Colin Eles
committed
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;
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',...
87
88
89
90
91
92
93
94
95
96
97
98
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
'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));
% 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));
159
160
161
162
163
164
165
166
167
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
% 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.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;
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])
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
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
%%
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
%% pvs_ext_call
function [] = pvs_ext_call(object,src,event)
error = object.check_call;
if (~error)
object.PVS.pvs_check;
end
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
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
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 = [];
%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)) ','];
end
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);
end
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');
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
% 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'));
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
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');
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
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')];
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
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')];
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
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;
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
% 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');
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
% 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);
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');
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)];