Skip to content
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
classdef GridSingleColumnEventDetails < event.EventData
properties
changed_cell = [];
end
methods
function eventData = GridSingleColumnEventDetails(changed_cell_in)
eventData.changed_cell = changed_cell_in;
end
end
end
\ No newline at end of file
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
classdef GridSingleRowEventDetails < event.EventData
properties
changed_row = [];
end
methods
function eventData = GridSingleRowEventDetails(changed_row_in)
eventData.changed_row = changed_row_in;
end
end
end
\ No newline at end of file
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
classdef HierarchicalGrid < handle
% This class stores a grid containing conditions for the table.
% It can be used either for the left of top grid.
properties
grid = {}
right_most_grid_cells = {}
end
events
AddedOuterCell
RemovedOuterCell
StructureChanged
end
methods
%% Data
% constructor
% inputs:
% none
% outputs:
% object:Data - created object
function object = HierarchicalGrid()
end
function width = max_width(object)
width = object.max_width_impl(object.grid, 1);
end
function length = get_children_count(object, cell)
if isempty(cell)
grid = object.grid;
else
grid = cell.grid;
end
length = size(grid, 2);
end
function count = subgrid_count(object)
count = object.subgrid_count_impl(object.grid);
end
function count = subgrid_count_impl(object, grid)
count = 0;
for i = 1:size(grid, 2)
ecount = object.subgrid_count_impl(grid{i}.grid);
count = count + ecount;
end
if size(grid, 2) ~= 0
count = count + 1;
end
end
function cell = get_cell(object, cell_index)
cell = object.get_child_cell([], cell_index);
end
function cell = get_child_cell(object, parent, cell_index)
if isempty(parent)
grid = object.grid
else
grid = parent.grid
end
cell = grid{cell_index}
end
function cell = recurse_top_cell(object, the_cell)
cell = the_cell
while size(cell.grid, 2) ~= 0
cell = cell.grid{1};
end
end
function count = children_count(object, parent)
if isempty(parent)
parent = object
end
count = size(parent.grid, 2);
end
function cell = recurse_bottom_cell(object, the_cell)
cell = the_cell
while size(cell.grid, 2) ~= 0
cell = cell.grid{size(cell.grid, 2)};
end
end
end
end
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
function [] = add_cell( object, beneath_cell, after_cell )
%% ADD_CELL Add a cell to the grid.
% Adds a new cell to the grid, updates relevant information throughout,
% and sends appropriate update signals.
%% Find Subgrid
if isempty(beneath_cell)
subgrid = object;
else
subgrid = beneath_cell;
end
NewCell = HierarchicalGridCell();
if isempty(after_cell)
%% Append cell to grid
% Append the cell to the current grid.
% Find new index for right_most_grid_cells
if isempty(subgrid.grid)
% No cells at this level. If we are base, just use 1.
% Otherwise use its current index.
if isempty(beneath_cell)
rmgi = 1;
else
rmgi = object.find_cell_in_list(object.right_most_grid_cells, beneath_cell);
end
%Ok, this is a replacement operation.
object.right_most_grid_cells{ rmgi } = NewCell;
if isempty(beneath_cell)
%Only notify if a new cell was added.
notify(object, 'AddedOuterCell', GridSingleCellEventDetails(rmgi))
end
else
cell_in_rmg = subgrid.grid{ size(subgrid.grid, 2) };
while size(cell_in_rmg.grid, 2) ~= 0
cell_in_rmg = cell_in_rmg.grid{ size(cell_in_rmg.grid, 2) };
end
rmgi = object.find_cell_in_list(object.right_most_grid_cells, cell_in_rmg);
%Since this is now an addition to the right most list, append.
object.right_most_grid_cells = {object.right_most_grid_cells{1:rmgi} NewCell object.right_most_grid_cells{(rmgi+1):size(object.right_most_grid_cells, 2)}};
rmgi = rmgi + 1;
%This is always an addition. So notify.
notify(object, 'AddedOuterCell', GridSingleCellEventDetails(rmgi))
end
subgrid.grid{ size(subgrid.grid, 2)+1 } = NewCell;
else
assert(false, 'Add support for non-appending action');
end
notify(object, 'StructureChanged');
end
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
function delete_cell( object, beneath_cell, the_cell )
%% ADD_CELL Add a cell to the grid.
% Adds a new cell to the grid, updates relevant information throughout,
% and sends appropriate update signals.
%assert(false, 'BREAK');
%% Find Subgrid
if isempty(beneath_cell)
subgrid = object;
else
subgrid = beneath_cell;
end
if true || isempty(beneath_cell) && isempty(the_cell.grid)
cur_index = object.find_cell_in_list(subgrid.grid, the_cell);
top_rmg = object.recurse_top_cell(the_cell);
top_rmgi = object.find_cell_in_list(object.right_most_grid_cells, top_rmg);
bottom_rmg = object.recurse_bottom_cell(the_cell);
bottom_rmgi = object.find_cell_in_list(object.right_most_grid_cells, bottom_rmg);
subgrid.grid = [subgrid.grid(1:cur_index-1) subgrid.grid(cur_index+1:size(subgrid.grid, 2))];
%For readability, use rmgc.
rmgc = object.right_most_grid_cells;
object.right_most_grid_cells = [rmgc(1:top_rmgi-1) rmgc(bottom_rmgi+1:size(rmgc, 2))];
if ~isempty(beneath_cell) && size(beneath_cell.grid, 2) == 0
rmgc = object.right_most_grid_cells
object.right_most_grid_cells = [rmgc(1:top_rmgi-1) {beneath_cell} rmgc(top_rmgi:size(rmgc, 2))];
top_rmgi = top_rmgi + 1;
end
for i = 0:bottom_rmgi-top_rmgi
notify(object, 'RemovedOuterCell', GridSingleCellEventDetails(top_rmgi))
end
else
assert(false, 'Deal with sub-sub* grids');
end
notify(object, 'StructureChanged');
end
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
function [ gi ] = find_cell_in_list( object, grid, find_cell )
gi = -1;
for i = 1:size(grid, 2)
if grid{i} == find_cell
gi = i;
break;
end
end
assert(gi ~= -1, 'Failed to find looked for cell!')
end
function length = length( object )
%LENGTH Get ths length of the current grid
% Gets the number of cells under the parent cell. It doesn't include
% children.
length = size(object.grid, 2);
end
%% max_width
%% max_width_impl
% determines the maximum width from a current grid, the maximum
% widht represents the number of levels of subgrids from a given
% grid.
......@@ -9,14 +9,13 @@
% m:integer - value representing the maximum width from the
% current grid.
% Author: Colin Eles elesc@mcmaster.ca
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
function m = max_width(object,width)
temp = [];
for i=1:size(object.cells,2)
if (~isempty(object.cells(i).subgrid))
temp = [temp object.cells(i).subgrid.max_width(width+1)];
else
temp = [temp width];
function m = max_width_impl(object,grid,width)
temp = [width];
for i=1:size(grid,2)
if (~isempty(grid{i}.grid))
temp = [temp object.max_width_impl(grid{i}.grid, width+1)];
end
end
......
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
classdef HierarchicalGridCell < Cell
% This class will store a single cell of data. It contains its string,
% and it contains a subgrid if appropriate.
properties
grid = {};
end
methods
%% Data
% constructor
% inputs:
% none
% outputs:
% object:Data - created object
function object = HierarchicalGridCell()
end
function cell = get_cell(object, cell_index)
cell = object.grid{cell_index};
end
end
end
classdef HorizontalLineGridDraw < GUIBase
%TABLEGRIDDRAW Draw a TableGrid into a uipanel
% Draws a 2D Grid inside a uipanel (Yay!)
properties
my_grid = []
controls = {}
pb_delete = -1
pb_new = -1
gui_params = []
end
methods
function object = HorizontalLineGridDraw(my_grid, gui_params)
if nargin == 1
gui_params = GUIParameters();
end
object.my_grid = my_grid;
object.gui_params = gui_params;
my_grid.addlistener('StructureChanged', @(src, event) restructure(object));
end
function restructure(object)
object.notify('BoundingBoxChanged');
redraw(object);
end
end
end
function [ output_args ] = delete_right_cell( input_args )
%DELETE_RIGHT_CELL Summary of this function goes here
% Detailed explanation goes here
end
function grid_controls = draw_onto( object, parent_handle, grid, grid_controls)
%DRAW_ONTO Draws the controls onto the parent_handle. This function needs to be called everytime an update happens.
% This function draws the entire handle onto the handle. This function
% needs to be called everytime the back table is updated. The class will
% notify when its necessary.
if nargin == 2
%Need to invert y, so need total size
[x, y] = object.get_bounding_box();
object.controls = draw_onto(object, parent_handle, object.my_grid, object.controls);
if ishandle(object.pb_delete)
pb_delete = object.pb_delete;
else
pb_delete = uicontrol(parent_handle, 'Style', 'pushbutton', 'String', 'Remove', 'Callback', @(src, event)object.my_grid.delete_cell([], object.my_grid.get_cell(object.my_grid.length) ) );
object.pb_delete = pb_delete;
end
if ishandle(object.pb_new)
pb_new = object.pb_new;
else
pb_new = uicontrol(parent_handle, 'Style', 'pushbutton', 'String', 'Add', 'Callback', @(src, event)object.my_grid.add_cell([], []));
object.pb_new = pb_new;
end
set(pb_delete, 'Position', [x-80, 0, 80, 20]);
set(pb_new, 'Position', [x-80, 20, 80, 20]);
return ;
end
% First delete an extra controls
for i = grid.length()+1:size(grid_controls, 2)
delete(grid_controls{i});
grid_controls(i) = [];
end
assert( ~(size(grid_controls, 2) > grid.length()), 'Delete failed to shrink things appropriately.');
for i = 1:grid.length()
if size(grid_controls, 2) >= i && ishandle(grid_controls{i})
delete(grid_controls{i});
end
grid_controls{i} = uicontrol(parent_handle, 'Style', 'edit', 'Position', [(i-1)*object.gui_params.edit_width, 0, object.gui_params.edit_width, object.gui_params.edit_height], 'String', grid.get_cell(i).get_user_string(), 'Callback', @(src,event)GUIHelpers.update_cell(src, event, grid.get_cell(i)) );
end
end
function [x, y] = get_bounding_box( object )
%GET_BOUNDING_BOX Gets the size in pixels of the grid.
%Returns the size of the grid (as a box) for layout purposes.
x = size(object.my_grid.grid, 2); %Store maximum width
x = object.gui_params.edit_width*x + 80; %Then calculate the pixels.
y = 1; %We have one row.
y = object.gui_params.edit_height*y; %Same here.
end
function save_cell_callback( object, src, event, cell_index)
%SAVE_CELL_CALLBACK Saves the cell contents on tab change
% When the cell's callback is called, this gets called to save its
% contents back into cell.
object.my_grid.get_cell(cell_index).set_string(get(src, 'String'));
end
classdef LayoutBase < GUIBase
%LAYOUTBASE Summary of this class goes here
% Detailed explanation goes here
methods(Abstract)
relayout(object);
end
end
classdef LetStatments < handle
%LETSTATMENTS Summary of this class goes here
% Detailed explanation goes here
properties(Access = private)
statements = {}
end
methods
function object = LetStatments()
end
function count = size(object)
count = size(object.statements, 2);
end
function [name, assignment] = get_statement(object, index)
name = object.statements{index}.name;
assignment = object.statements{index}.assignment;
end
function insert_space(object)
p = struct();
p.name = '';
p.assignment = '';
object.statements(size(object.statements, 2)+1) = {p};
notify(object, 'StructureChanged');
end
function delete_end(object)
object.statements(size(object.statements, 2)) = [];
notify(object, 'StructureChanged');
end
function set_statement_name(object, index, name)
object.statements{index}.name = name;
end
function set_statement_assignment(object, index, assignment)
object.statements{index}.assignment = assignment;
end
end
events
StructureChanged
end
end
classdef LetStatmentsDraw < GUIBase
%LETSTATEMENTSDRAW Summary of this function goes here
% Detailed explanation goes here
properties
my_data = [];
my_controls = {};
gui_params = [];
pb_delete = -1;
pb_new = -1;
end
methods
function object = LetStatmentsDraw(data, gui_params)
if nargin == 1
gui_params = GUIParameters();
end
object.my_data = data;
object.gui_params = gui_params;
data.addlistener('StructureChanged', @(src, event)redraw_and_update_bb(object, src, event));
end
function draw_onto(object, parent_handle)
[~, y] = object.get_bounding_box();
for i = object.my_data.size()+1:size(object.my_controls, 2)
delete(object.my_controls{object.my_data.size()+1}.n);
delete(object.my_controls{object.my_data.size()+1}.a);
object.my_controls(object.my_data.size()+1) = []
end
for i = 1:object.my_data.size()
if size(object.my_controls, 2) < i
object.my_controls{i} = struct();
object.my_controls{i}.n = uicontrol(object.phandle, 'Style', 'edit');
object.my_controls{i}.a = uicontrol(object.phandle, 'Style', 'edit');
elseif ~ishandle(object.my_controls{i}.n)
object.my_controls{i}.n = uicontrol(object.phandle, 'Style', 'edit');
object.my_controls{i}.a = uicontrol(object.phandle, 'Style', 'edit');
end
[n, a] = object.my_data.get_statement(i);
c = object.my_controls{i}.n;
set(c, 'Parent', object.phandle);
set(c, 'String', n);
set(c, 'Position', [0, y-((i)*object.gui_params.edit_height), object.gui_params.edit_width, object.gui_params.edit_height]);
set(c, 'Callback', @(src, event)object.my_data.set_statement_name(i, get(src, 'String')));
c = object.my_controls{i}.a
set(c, 'Parent', object.phandle);
set(c, 'String', a);
set(c, 'Position', [object.gui_params.edit_width+20, y-((i)*object.gui_params.edit_height), object.gui_params.edit_width*2, object.gui_params.edit_height]);
set(c, 'Callback', @(src, event)object.my_data.set_statement_assignment(i, get(src, 'String')));
end
if ishandle(object.pb_delete)
pb_delete = object.pb_delete;
else
pb_delete = uicontrol(parent_handle, 'Style', 'pushbutton', 'String', 'Remove', 'Callback', @(src, event)object.my_data.delete_end());
object.pb_delete = pb_delete;
end
if ishandle(object.pb_new)
pb_new = object.pb_new;
else
pb_new = uicontrol(parent_handle, 'Style', 'pushbutton', 'String', 'Add', 'Callback', @(src, event)object.my_data.insert_space());
object.pb_new = pb_new;
end
set(pb_delete, 'Position', [80, 0, 80, 20]);
set(pb_new, 'Position', [0, 0, 80, 20]);
end
function [x, y] = get_bounding_box(object)
x = object.gui_params.edit_width+20+object.gui_params.edit_width*2;
y = object.gui_params.edit_height*object.my_data.size() + 20;
end
end
end
classdef LinearLayoutBase < LayoutBase
%LINEARLAYOUTBASE Summary of this class goes here
% Detailed explanation goes here
properties
children = {}
children_controls = {}
end
methods
function add_child(object, child)
object.children{end+1} = child;
child.addlistener('BoundingBoxChanged', @(src, event)object.relayout());
end
%NOTE REMOVAL IS NOT SUPPORTED!!!!
function draw_onto(object, phandle)
assert(size(object.children, 2) >= size(object.children_controls, 2), 'DONT DO THAT!');
for i=1:size(object.children, 2)
if size(object.children_controls, 2) < i
object.children_controls{i} = uipanel(phandle, 'Units', 'pixels');
end
cc = object.children_controls{i};
object.children{i}.draw(cc);
end
relayout(object);
end
end
end
......@@ -24,11 +24,13 @@ for i=1:size(grid.cells,2)
end
text = char(grid.cells(i).cond_text);
if size(text) > 0
s = [text(1,:)];
for j = 2:size(text,1)
s = [s ' ' text(j,:)];
end
text = s;
end
vars = regexp(text,'([a-zA-Z][a-zA-Z0-9_]*)','match');
......
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
classdef RCell < handle
%UNTITLED2 Summary of this class goes here
% Detailed explanation goes here
properties
Cell1 = [];
Cell2 = [];
result = [];
result_text = [];
color = [];
end
methods
%% RCell
% Constructor
% inputs:
% cell1:Cell - cell reference in top grid
% cell2:Cell - Cell reference in left grid
% outputs;
% n:RCell - created RCell
function n = RCell(cell1,cell2)
n.Cell1 = cell1;
n.Cell2 = cell2;
end
end
end