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;
Colin Eles
committed
end
function [] = set_block_display(object)
%if object.pvs_checked == 1
mask_string = [];
code_block = sprintf('%s/code',getfullname(object.block_handle));
in_handles=find_system(code_block, 'SearchDepth',1,'FindAll','On','FollowLinks','On','LookUnderMasks','All','BlockType','Inport');
for i = 1:size(in_handles,1)
mask_string = [mask_string 'port_label(''input'',' int2str(i) ',''' get_param(in_handles(i),'Name') ''');' ];
end
mask_string = [mask_string 'text(0.5, 0.6, ''Tabular Expression'', ''horizontalAlignment'', ''center'')'];
if object.pvs_checked == 0
mask_string = [mask_string 'color(''red'')text(0.5, 0.4, ''Not Checked'', ''horizontalAlignment'', ''center'')'];
else
mask_string = [mask_string 'color(''green'')text(0.5, 0.4, ''Checked'', ''horizontalAlignment'', ''center'')'];
end
set_param(getfullname(object.block_handle),'MaskDisplay',mask_string);
%end
Colin Eles
committed
function [] = update_Statusbar(object)
warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame
% statusbar depends on JavaFrame which may be obsolete in
% future versions of Matlab, can still use in old versions
try
if (object.pvs_checked == 0)
sb = statusbar(object.fig, 'Status: Not Typechecked');
set(sb.TextPanel,'Foreground',[1,0,0]);
elseif (object.pvs_checked == 1)
sb = statusbar(object.fig, 'Status: Typechecked');
set(sb.TextPanel,'Foreground',[0,1,0]);
end
catch exception
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])
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
360
361
362
363
364
365
366
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;
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
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
Colin Eles
committed
function type = output_data_type(object)
if (object.mode == 1)
S = sfroot;
code_block = sprintf('%s/code',getfullname(object.block_handle));
code_blocks = find_system(getfullname(object.block_handle),'BlockType','SubSystem','Name','code');
if ~isempty(code_blocks)
myState = S.find('-isa','Stateflow.EMChart', '-and', 'Path', code_block); % find which one we want to edit
if strncmp(myState.Outputs.DataType,'Inherit',7);
type = ''
else
type = myState.Outputs.DataType;
end
else
type = '';
end
Colin Eles
committed
else
type = ''
Colin Eles
committed
end
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)
Colin Eles
committed
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.
Colin Eles
committed
code = [code sprintf('output=%s(%s);\n',object.output_data_type,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);
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
% 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));
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
% 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
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
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');
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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')];
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
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')];
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
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');
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
% 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
Colin Eles
committed
code = [code sprintf('%soutput = %s(%s);\n',space,obj.output_data_type,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)];