Skip to content
...@@ -26,5 +26,8 @@ set(object.function_inputs_control,'Position',[object.pb_offset*2+object.pb_widt ...@@ -26,5 +26,8 @@ set(object.function_inputs_control,'Position',[object.pb_offset*2+object.pb_widt
set(object.name_label,'Position',[object.pb_offset*2+object.pb_width+object.text_width l_fig_height-object.pb_offset*3-object.pb_height-object.htx_height object.pb_width object.htx_height]); set(object.name_label,'Position',[object.pb_offset*2+object.pb_width+object.text_width l_fig_height-object.pb_offset*3-object.pb_height-object.htx_height object.pb_width object.htx_height]);
set(object.function_name_control,'Position',[object.pb_offset*3+object.pb_width*2+object.text_width l_fig_height-object.pb_offset*3-object.pb_height-object.htx_height object.text_width object.htx_height]); set(object.function_name_control,'Position',[object.pb_offset*3+object.pb_width*2+object.text_width l_fig_height-object.pb_offset*3-object.pb_height-object.htx_height object.text_width object.htx_height]);
[~, by] = object.vbox_layout.get_bounding_box;
setpixelposition(object.vbox_layout_panel, [object.pb_offset, l_fig_height-object.pb_offset*3-object.htx_height-object.pb_height-by-20, 1, 1]);
end end
classdef GUIBase < handle
%GUIBASE Summary of this class goes here
% Detailed explanation goes here
properties
phandle = -1
end
methods
function draw(object, parent_handle)
%TODO delete old controls
object.phandle = parent_handle;
object.redraw();
end
function redraw(object)
draw_onto(object, object.phandle);
end
function redraw_and_update_bb(object, src, event)
object.redraw();
object.notify('BoundingBoxChanged');
end
end
methods(Abstract)
draw_onto(object, parent_handle);
[x, y] = get_bounding_box( object );
end
events
BoundingBoxChanged
end
end
classdef GUIParameters
%GUIPARAMETERS Summary of this class goes here
% Detailed explanation goes here
properties
edit_width = 250
edit_height = 60
layout_margin_x = 20
layout_margin_y = 20
end
methods
function object = GUIParameters()
end
end
end
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
classdef Grid < handle
properties
parent_cell = [];
parent_grid = [];
cells = [];
split_pb = [];
num_cells = 0;
grid_index = 0;
rGrid = [];
new_cell_pb = [];
delete_cell_pb = [];
end
methods
%% Grid
% constructor
% inputs:
% index:integer - Grid's index
% p_cell:Cell - Parent cell
% outputs:
% n:Cell - created cell
function n = Grid(index,p_cell)
n.grid_index = index;
n.parent_cell = p_cell;
end
end
end
%% clone
% function will create a copy of the current grid and store it
% in dest_grid, since grid is a recursive datatype this is a
% recursive function in order to do a deep clone.
% inputs:
% object:Grid - current Grid object
% dest_grid:Grid - grid to copy contents to
% index:int - index of the current grid
% p_cell:Cell - parent cell of the current grid.
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = clone(object,dest_grid,index,p_cell)
for i=1:size(object.cells,2)
dest_grid.new_Cell();
dest_grid.cells(i).cond_text = object.cells(i).cond_text;
if (~isempty(object.cells(i).subgrid))
dest_grid.cells(i).subgrid = Grid(dest_grid.cells(i).cell_index,dest_grid.cells(i));
dest_grid.cells(i).subgrid.set_rGrid(dest_grid.cells(i).parent_grid.rGrid);
object.cells(i).subgrid.clone(dest_grid.cells(i).subgrid,object.cells(i).subgrid.grid_index,dest_grid.cells(i));
else
end
end
end
\ No newline at end of file
%% deep_delete
% deletes an entire grid as well as all the subgrids associated
% with it.
% inputs:
% object:Grid - current Grid object
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = deep_delete(object)
% loop through each cell and delete the associated result
% cells and call delete_Cell on each of the cells, which will
% then call deep_delete on its subgrids.
for i=size(object.cells,2):-1:1
object.rGrid.delete_g2s(object.cells(i));
object.cells(i).delete_Cell;
%object.cells(i) = [];
end
delete(object.new_cell_pb);
delete(object.delete_cell_pb);
object.new_cell_pb = [];
object.delete_cell_pb = [];
end
%% delete_Cell
% deletes the last cell in the grid, also deletes an associated
% new grid push button,
% TODO, need to implement the case where last cell is deleted.
% inputs:
% object:Grid - current Grid object
% outputs
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = delete_Cell(object)
last_cell = object.num_cells;
object.rGrid.delete_g2s(object.cells(end));
object.cells(end).cond = [];
object.cells(end).grid_pb = [];
object.cells(end) = [];
if(~isempty(object.rGrid))
object.rGrid.refresh;
end
end
%% new_Cell
% creates a new cell in the current grid.
% inputs:
% object:Grid - current Grid object
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = new_Cell(object)
cell = Cell(object.num_cells+1,object);
object.num_cells = object.num_cells + 1;
object.cells = [object.cells cell];
% refresh the rGrid so that a new results cell is created
if(~isempty(object.rGrid))
object.rGrid.refresh;
end
end
%% pb_delete_call
% callback function for when user clicks on the delete cell
% button.
% inputs:
% object:Grid - current Grid object
% src:double - source of the callback calling
% event:eventdata - event that triggered the callback
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = pb_delete_call(object,src,event)
gui = get(src,'userdata');
gui.save_data;
deleted_cell = object.cells(end);
% deleted last cell in grid
if size(object.cells,2) == 1
if (~isempty(object.parent_cell))
if isempty(event) || event ~= 1
undo_data.action = 5;
undo_data.grid = object;
undo_data.cell = object.parent_cell;
undo_data.text = deleted_cell.cond;
undo_data.subgrid = deleted_cell;
gui.undo_man.new_state(undo_data);
end
end
else
if isempty(event) || event ~= 1
undo_data.action = 3;
undo_data.grid = object;
undo_data.cell = deleted_cell;
undo_data.text = deleted_cell.cond_text;
undo_data.subgrid = deleted_cell.cond;
gui.undo_man.new_state(undo_data);
end
end
% button could be pressed in the left or top grid so we need to
% try to remove the result cell associated with either case.
object.rGrid.delete_g2s(deleted_cell);
object.rGrid.delete_g1s(deleted_cell);
deleted_cell.delete_Cell;
object.cells(end) = [];
% deleted last cell in grid
if size(object.cells,2) == 0
if (~isempty(object.parent_cell))
object.parent_cell.subgrid = [];
object.parent_cell.pb_flag = 1;
delete(object.new_cell_pb);
delete(object.delete_cell_pb);
object.rGrid.refresh;
end
end
if size(object.cells,2) == 1 && isempty(object.parent_cell)
set(object.delete_cell_pb,'Enable','off');
end
gui.reset_wh();
gui.draw_allgrids(0);
gui.update_undoredo;
end
%% pb_new_call
% call back function for the new cell push button. When button
% is pressed a new cell object is created in the current grid
% and the table is redrawn
% inputs:
% object:Grid - current Grid object
% src:double - source of the callback calling
% event:eventdata - event that triggered the callback
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = pb_new_call(object,src,event)
gui = get(src,'userdata');
object.new_Cell;
gui.reset_wh();
gui.draw_allgrids(0);
if size(object.cells,2) > 1
set(object.delete_cell_pb,'Enable','on');
else
set(object.delete_cell_pb,'Enable','off');
end
if isempty(event) || event ~= 1
undo_data.action = 2;
undo_data.grid = object;
undo_data.cell = [];
undo_data.text = [];
undo_data.subgrid = [];
gui.undo_man.new_state(undo_data);
end
gui.update_undoredo;
end
%% set_delete_pb
% create the delete cell push button
% inputs:
% object:Grid - current Grid object
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = set_delete_pb(object,fig,pos)
if(isempty(object.delete_cell_pb) || ~ishghandle(object.delete_cell_pb))
object.delete_cell_pb = uicontrol('style','push',...
'units','pix',...
'string','delete',...
'HorizontalAlign','left',...
'Parent',fig,...
'position',pos,...
'callback',@(src,event)pb_delete_call(object,src,event));
else
set(object.delete_cell_pb,'position',pos);
end
end
%% set_heights
% sets the heights for each of the cells and subcells of a grid,
% uses the cells cal_height method to determine what the heights
% should be.
% inputs:
% object:Grid - current Grid object
% edit:boolean - current value of the edit toggle.
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = set_heights(object,edit)
for i = 1:size(object.cells,2)
if (~isempty(object.cells(i).subgrid))
object.cells(i).subgrid.set_heights(edit);
end
object.cells(i).height = object.cells(i).cal_height(edit);
end
end
%% set_pb
% create the new cell push button
% inputs:
% object:Grid - current Grid object
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = set_pb(object,fig,pos)
if(isempty(object.new_cell_pb) || ~ishghandle(object.new_cell_pb))
object.new_cell_pb = uicontrol('style','push',...
'units','pix',...
'string','new',...
'HorizontalAlign','left',...
'Parent',fig,...
'position',pos,...
'callback',@(src,event)pb_new_call(object,src,event));
else
set(object.new_cell_pb,'position',pos);
end
end
%% set_rGrid
% set the reference to the Results grid
% inputs:
% object:Grid - current Grid objectect
% r:RGrid - result Grid
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = set_rGrid(object,r)
object.rGrid = r;
end
%% set_widths
% sets the widths for each of the cells and subcells in a grid.
% the width of a cell is equal to the max width of the previous
% level - 1 if the cell has no subgrids, or 1 if the cell has a
% subgrid.
% inputs:
% object:Grid - current Grid object
% outputs:
% none
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function [] = set_widths(object,max_width)
for i=1:size(object.cells,2)
if (~isempty(object.cells(i).subgrid))
object.cells(i).subgrid.set_widths(max_width-1);
object.cells(i).width = 1;
else
object.cells(i).width = max_width;
end
end
end
classdef GridLayout < GUIBase
%GRIDLAYOUT Draw a grid of other drawable elements.
% Draws a bunch of drawables using panels to make life simple.
properties
drawables = {}
controls = []
column_sizes = []
row_sizes = []
end
methods
function object = GridLayout()
end
function insert_drawable(object, drawable, y, x)
object.drawables{y, x} = drawable;
relayout(object);
drawable.addlistener('BoundingBoxChanged', @(srv, event)changed_bounding_box(object));
end
function changed_bounding_box(object, src, event)
relayout(object);
redraw(object);
notify(object, 'BoundingBoxChanged');
end
end
end
function draw_onto( object, parent_handle )
%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.
[x, y] = object.get_bounding_box();
if size(object.controls, 2) ~= size(object.drawables, 2) || size(object.controls, 1) ~= size(object.drawables, 1)
object.controls(size(object.drawables, 1), size(object.drawables, 2)) = 0;
end
for i = 1:size(object.drawables, 2)
for j = 1:size(object.drawables, 1)
if ~isempty( object.drawables{j, i} )
[~, yi] = object.drawables{j, i}.get_bounding_box();
if object.controls(j, i) == 0 || ~ishandle(object.controls(j, i))
p = uipanel('Parent', parent_handle, 'Units', 'pixels', 'Position', [sum(object.column_sizes(1:j-1))+(j-1)*20, y - sum(object.row_sizes(1:i)) - (i-1)*20, x, y]);
object.controls(j, i) = p;
else
p = object.controls(j, i);
set(p, 'Position', [sum(object.column_sizes(1:j-1))+(j-1)*20, y - sum(object.row_sizes(1:i-1)) - (i-1)*20 - yi, x, y]);
end
object.drawables{j, i}.draw(p);
end
end
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 = sum(object.column_sizes) + (size(object.column_sizes, 2) - 1)*20;
y = sum(object.row_sizes) + (size(object.row_sizes, 2) - 1)*20;
end
function relayout( object )
%RELAYOUT Summary of this function goes here
% Detailed explanation goes here
object.row_sizes = [];
object.column_sizes = [];
for i = 1:size(object.drawables, 2)
for j = 1:size(object.drawables, 1)
if ~isempty( object.drawables{j, i} )
[x, y] = object.drawables{j, i}.get_bounding_box();
object.row_sizes(j, i) = y;
object.column_sizes(j, i) = x;
end
end
end
object.row_sizes = max(object.row_sizes, [], 1);
object.column_sizes = max(object.column_sizes, [], 2)';
end
% Author: Matthew Dawson matthew@mjdsystems.ca
% Organization: McMaster Centre for Software Certification
classdef GridSingleCellEventDetails < event.EventData
properties
changed_cell = [];
end
methods
function eventData = GridSingleCellEventDetails(changed_cell_in)
eventData.changed_cell = changed_cell_in;
end
end
end
\ No newline at end of file