From 2cc17cdb43a8f209ca6e661a3541ce738784e8ec Mon Sep 17 00:00:00 2001 From: Alvalunasan Date: Mon, 6 Apr 2020 10:40:27 -0400 Subject: [PATCH] GUI to add lab users to database --- .../DataJointLabUserTable.m | 49 +++++ .../get_GUI_table_info.m | 172 ++++++++++++++++++ .../get_values_table_field.m | 29 +++ .../@DataJointLabUserTable/insert_user.m | 24 +++ .../AddLabUsers/@NewRecordsGUI/GUI_add_user.m | 66 +++++++ .../@NewRecordsGUI/NewRecordsGUI.m | 132 ++++++++++++++ .../AddLabUsers/@NewRecordsGUI/close_figure.m | 13 ++ .../@NewRecordsGUI/create_GUI_input.m | 39 ++++ .../@NewRecordsGUI/create_buttons.m | 27 +++ .../AddLabUsers/@NewRecordsGUI/create_gui.m | 62 +++++++ .../AddLabUsers/@NewRecordsGUI/create_label.m | 23 +++ .../@NewRecordsGUI/create_table_grid.m | 40 ++++ .../AddLabUsers/@NewRecordsGUI/create_title.m | 21 +++ .../@NewRecordsGUI/define_figure_position.m | 31 ++++ database/AddLabUsers/GUI_Inputs/GUI_Input.m | 47 +++++ .../AddLabUsers/GUI_Inputs/GUI_Input_Edit.m | 137 ++++++++++++++ .../AddLabUsers/GUI_Inputs/GUI_Input_HBox.m | 172 ++++++++++++++++++ .../AddLabUsers/GUI_Inputs/GUI_Input_Popup.m | 148 +++++++++++++++ database/AddLabUsers/ScreenProperties.m | 23 +++ database/AnimalDatabase.m | 34 +++- 20 files changed, 1281 insertions(+), 8 deletions(-) create mode 100644 database/AddLabUsers/@DataJointLabUserTable/DataJointLabUserTable.m create mode 100644 database/AddLabUsers/@DataJointLabUserTable/get_GUI_table_info.m create mode 100644 database/AddLabUsers/@DataJointLabUserTable/get_values_table_field.m create mode 100644 database/AddLabUsers/@DataJointLabUserTable/insert_user.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/GUI_add_user.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/NewRecordsGUI.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/close_figure.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/create_GUI_input.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/create_buttons.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/create_gui.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/create_label.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/create_table_grid.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/create_title.m create mode 100644 database/AddLabUsers/@NewRecordsGUI/define_figure_position.m create mode 100644 database/AddLabUsers/GUI_Inputs/GUI_Input.m create mode 100644 database/AddLabUsers/GUI_Inputs/GUI_Input_Edit.m create mode 100644 database/AddLabUsers/GUI_Inputs/GUI_Input_HBox.m create mode 100644 database/AddLabUsers/GUI_Inputs/GUI_Input_Popup.m create mode 100644 database/AddLabUsers/ScreenProperties.m diff --git a/database/AddLabUsers/@DataJointLabUserTable/DataJointLabUserTable.m b/database/AddLabUsers/@DataJointLabUserTable/DataJointLabUserTable.m new file mode 100644 index 0000000..1b272c3 --- /dev/null +++ b/database/AddLabUsers/@DataJointLabUserTable/DataJointLabUserTable.m @@ -0,0 +1,49 @@ +classdef DataJointLabUserTable + % DataJointLabUserTable Summary of DataJointLabUserTable + % Define a simple interface to define records to be added for specific + % tables + % + % DataJointLabUserTable main Properties: + % GUI_info - structure with information for each field of the tables + % that will update for defining the GUI + % tables_info - reference for all the tables that will be updated + % + % DataJointLabUserTable Methods: + % get_GUI_table_info(obj,parent) - Function that defines two structures with information about tables that + % will be updated + % insert_user(obj, all_values_insert) - Function that calls database to insert record in tables referenced in + % table_info structure + % get_values_table_field(~, table, field, sort_limit) -Function to get specific fields from table + properties (Constant) + + %dj_conn = getdjconnection('u19_', 'datajoint00.pni.princeton.edu'); + + end + + %_________________________________________________________________________________________________ + properties (SetAccess = protected) + + GUI_info + tables_info + + end + + %_________________________________________________________________________________________________ + methods + + [GUI_info, tables_update] = get_GUI_table_info(obj); + example_value = get_values_table_field(obj, table, field, sort_limit); + insert_user(obj, all_values_insert); + + function obj = DataJointLabUserTable() + %----- Class constructor, defining structures + + [obj.GUI_info, obj.tables_info] = obj.get_GUI_table_info(); + + + end + + end + + +end diff --git a/database/AddLabUsers/@DataJointLabUserTable/get_GUI_table_info.m b/database/AddLabUsers/@DataJointLabUserTable/get_GUI_table_info.m new file mode 100644 index 0000000..dd451b6 --- /dev/null +++ b/database/AddLabUsers/@DataJointLabUserTable/get_GUI_table_info.m @@ -0,0 +1,172 @@ +function [GUI_info, tables_update] = get_GUI_table_info(obj) +% Function that defines two structures with information about tables that +% will be updated +% correct +% Inputs: +% obj = DataJointLabUserTable object +% +% Outputs +% GUI_info = structure with information for each field of the tables +% that will update for defining the GUI +% tables_update = reference for all the tables that will be updated + + +%Create GUI_info structure with information for all fields +GUI_info(1).name = 'user_id'; +GUI_info(1).gui_type = 'edit'; +GUI_info(1).datatype = 'string'; +GUI_info(1).default = ''; +GUI_info(1).list_values = {}; +GUI_info(1).example_value = ''; +GUI_info(1).tooltip = 'username'; + +GUI_info(2).name = 'user_nickname'; +GUI_info(2).gui_type = 'edit'; +GUI_info(2).datatype = 'string'; +GUI_info(2).default = ''; +GUI_info(2).list_values = {}; +GUI_info(2).example_value = ''; +GUI_info(2).tooltip = 'same as netID for new users, for old users, this is used in the folder name etc'; + +GUI_info(3).name = 'full_name'; +GUI_info(3).gui_type = 'edit'; +GUI_info(3).datatype = 'string'; +GUI_info(3).default = ''; +GUI_info(3).list_values = {}; +GUI_info(3).example_value = ''; +GUI_info(3).tooltip = 'first name'; + +GUI_info(4).name = 'email'; +GUI_info(4).gui_type = 'edit'; +GUI_info(4).datatype = 'string'; +GUI_info(4).default = ''; +GUI_info(4).list_values = {}; +GUI_info(4).example_value = ''; +GUI_info(4).tooltip = 'email address'; + +GUI_info(5).name = 'phone'; +GUI_info(5).gui_type = 'edit'; +GUI_info(5).datatype = 'string'; +GUI_info(5).default = ''; +GUI_info(5).list_values = {}; +GUI_info(5).example_value = ''; +GUI_info(5).tooltip = 'phone number'; + +GUI_info(6).name = 'mobile_carrier'; +GUI_info(6).gui_type = 'popupmenu'; +GUI_info(6).datatype = 'string'; +GUI_info(6).default = ''; +GUI_info(6).list_values = obj.get_values_table_field(lab.MobileCarrier(), 'mobile_carrier'); +GUI_info(6).example_value = ''; +GUI_info(6).tooltip = 'allowed mobile carrier'; + +GUI_info(7).name = 'slack'; +GUI_info(7).gui_type = 'edit'; +GUI_info(7).datatype = 'string'; +GUI_info(7).default = ''; +GUI_info(7).list_values = {}; +GUI_info(7).example_value = ''; +GUI_info(7).tooltip = 'slack username'; + +GUI_info(8).name = 'contact_via'; +GUI_info(8).gui_type = 'popupmenu'; +GUI_info(8).datatype = 'string'; +GUI_info(8).default = ''; +GUI_info(8).list_values = {'Slack','text','Email'}; +GUI_info(8).example_value = ''; +GUI_info(8).tooltip = 'Preferred method of contact'; + +GUI_info(9).name = 'presence'; +GUI_info(9).gui_type = 'popupmenu'; +GUI_info(9).datatype = 'string'; +GUI_info(9).default = ''; +GUI_info(9).list_values = {'Available','Away'}; +GUI_info(9).example_value = ''; +GUI_info(9).tooltip = ''; + +GUI_info(10).name = 'primary_tech'; +GUI_info(10).gui_type = 'popupmenu'; +GUI_info(10).datatype = 'string'; +GUI_info(10).default = 'N/A'; +GUI_info(10).list_values = {'yes','no','N/A'}; +GUI_info(10).example_value = ''; +GUI_info(10).tooltip = ''; + +GUI_info(11).name = 'tech_responsibility'; +GUI_info(11).gui_type = 'popupmenu'; +GUI_info(11).datatype = 'string'; +GUI_info(11).default = 'N/A'; +GUI_info(11).list_values = {'yes','no','N/A'}; +GUI_info(11).example_value = ''; +GUI_info(11).tooltip = ''; + +GUI_info(12).name = 'day_cutoff_time'; +GUI_info(12).gui_type = 'blob'; +GUI_info(12).datatype = 'numeric array'; +GUI_info(12).default = ''; +GUI_info(12).list_values = {}; +GUI_info(12).example_value = obj.get_values_table_field(lab.User(), 'day_cutoff_time', 'LIMIT 1'); +GUI_info(12).tooltip = ''; + +GUI_info(13).name = 'slack_webhook'; +GUI_info(13).gui_type = 'edit'; +GUI_info(13).datatype = 'string'; +GUI_info(13).default = ''; +GUI_info(13).list_values = {}; +GUI_info(13).example_value = ''; +GUI_info(13).tooltip = ''; + +GUI_info(14).name = 'watering_logs'; +GUI_info(14).gui_type = 'edit'; +GUI_info(14).datatype = 'string'; +GUI_info(14).default = ''; +GUI_info(14).list_values = {}; +GUI_info(14).example_value = ''; +GUI_info(14).tooltip = ''; + +GUI_info(15).name = 'lab'; +GUI_info(15).gui_type = 'popupmenu'; +GUI_info(15).datatype = 'string'; +GUI_info(15).default = ''; +GUI_info(15).list_values = obj.get_values_table_field(lab.Lab(), 'lab'); +GUI_info(15).example_value = ''; +GUI_info(15).tooltip = ''; + +GUI_info(16).name = 'secondary_contact'; +GUI_info(16).gui_type = 'popupmenu'; +GUI_info(16).datatype = 'string'; +GUI_info(16).default = ''; +GUI_info(16).list_values = obj.get_values_table_field(lab.User(), 'user_id'); +GUI_info(16).example_value = ''; +GUI_info(16).tooltip = ''; + +GUI_info(17).name = 'project'; +GUI_info(17).gui_type = 'popupmenu'; +GUI_info(17).datatype = 'string'; +GUI_info(17).default = ''; +GUI_info(17).list_values = obj.get_values_table_field(lab.Project(), 'project'); +GUI_info(17).example_value = ''; +GUI_info(17).tooltip = ''; + +GUI_info(18).name = 'protocol'; +GUI_info(18).gui_type = 'popupmenu'; +GUI_info(18).datatype = 'string'; +GUI_info(18).default = ''; +GUI_info(18).list_values = obj.get_values_table_field(lab.Protocol(), 'protocol'); +GUI_info(18).example_value = ''; +GUI_info(18).tooltip = ''; + + +%Create tables_update structure with references for all tables +tables_update(1).table = lab.User(); +tables_update(2).table = lab.UserLab(); +tables_update(3).table = lab.UserSecondaryContact(); +tables_update(4).table = lab.ProjectUser(); +tables_update(5).table = lab.UserProtocol(); + +for i=1:length(tables_update) + tables_update(i).fields = tables_update(i).table.header.names; +end + +end + diff --git a/database/AddLabUsers/@DataJointLabUserTable/get_values_table_field.m b/database/AddLabUsers/@DataJointLabUserTable/get_values_table_field.m new file mode 100644 index 0000000..638458a --- /dev/null +++ b/database/AddLabUsers/@DataJointLabUserTable/get_values_table_field.m @@ -0,0 +1,29 @@ +function example_value = get_values_table_field(~, table, field, sort_limit) +% Function to get specific fields from table +% Inputs: +% obj = DataJointLabUserTable object +% table = Reference to table in the database +% field = Name of the field to read +% sort_limit = Optional argument for sorting or limiting query +% +% Outputs +% example_value = Result from the query + + +%If sort_limit argument is not present, will be defined as empty string +if nargin <= 3 + sort_limit = ''; +end + +if ~isempty(sort_limit) + example_value = fetchn(table, field, sort_limit); + %If only one record needed for the query extract cell value + if strcmp(sort_limit,'LIMIT 1') + example_value = example_value{:}; + end +else + example_value = fetchn(table, field); + example_value = example_value(:); +end + +end \ No newline at end of file diff --git a/database/AddLabUsers/@DataJointLabUserTable/insert_user.m b/database/AddLabUsers/@DataJointLabUserTable/insert_user.m new file mode 100644 index 0000000..826e898 --- /dev/null +++ b/database/AddLabUsers/@DataJointLabUserTable/insert_user.m @@ -0,0 +1,24 @@ +function insert_user(obj, all_values_insert) +% Function that calls database to insert record in tables referenced in +% table_info structure +% Inputs: +% obj = DataJointLabUserTable object +% all_values_insert = structure with values to insert in table +% + +% for each table of the tables_info structure +for table_info = obj.tables_info + + table = table_info.table; + values_insert_table = struct; + %Select the fields to be written + for field = table_info.fields + field_str = field{:}; + values_insert_table.(field_str) = all_values_insert.(field_str); + + end + %Call datajoint database and insert data + insert(table, values_insert_table); + +end + diff --git a/database/AddLabUsers/@NewRecordsGUI/GUI_add_user.m b/database/AddLabUsers/@NewRecordsGUI/GUI_add_user.m new file mode 100644 index 0000000..9c70d95 --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/GUI_add_user.m @@ -0,0 +1,66 @@ +function GUI_add_user(obj, hobject, event) +% Function called when add user button is pressed +% Reads and check input by the user and insert record if everything is +% correct +% Inputs: +% obj = AddRecordsGUI object +% +% Outputs +% title = GUI object for the title + +% Disable buttons while processing data +for i=1:length(obj.button) + set(obj.button, 'Enable', 'off'); +end + +% Initialize status and error message +status = true; +error_msg = {'Error: Data could not be inserted'}; +error_msg(end+1) = {''}; +struct_insert = struct; + +% For each input +for i = 1:length(obj.GUI_inputs) + + GUI_input = obj.GUI_inputs{i}; + %Read value written by user + struct_insert.(GUI_input.name) = GUI_input.get_value(); + %Check if value is something accepted for the database + [ac_status, ac_error] = GUI_input.check_input(struct_insert.(GUI_input.name)); + + %Update status and possible error messages + status = and(status, ac_status); + if ~ac_status + error_msg(end+1) = {ac_error}; + end + +end + +% If there is at least one mistake in inputs +if ~status + %Show error message for each mistaken input + msgbox(error_msg, 'Error','error'); + +% If there is no error in input +else + + + try + %Try to insert record to database + obj.DatabaseTable.insert_user(struct_insert); + msgbox({'Record added succesfully'}); + %And close GUI + obj.close_figure(); + + catch e + %If there is a problem adding the record it shows corresponding error + error_msg = {sprintf('The identifier was:\n%s',e.identifier)}; + error_msg(end+1) = {sprintf('There was an error! The message was:\n%s',e.message)}; + msgbox(error_msg, 'Error','error'); + end + +end + + +end + diff --git a/database/AddLabUsers/@NewRecordsGUI/NewRecordsGUI.m b/database/AddLabUsers/@NewRecordsGUI/NewRecordsGUI.m new file mode 100644 index 0000000..f1cad8c --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/NewRecordsGUI.m @@ -0,0 +1,132 @@ +classdef NewRecordsGUI < handle + % NewRecordsGUI Summary of NewRecordsGUI + % Define a simple GUI for adding records to a table + % Table and fields info is defined and a GUI is created with + % correspondent inputs + % (Edits, Popupmenu and HBox inputs depending of fields in database) + % + % NewRecordsGUI main Properties: + % DatabaseTable - Reference to the tables to add records + % GUI_inputs_info - Information of each input of the GUI + % figGUI - main figure of the GUI + % panel - main panel of the GUI + % vbox - box to separate in three the GUI + % (title/input grid/button box) + % title - title part of the GUI + % grid - Grid input part of the GUI + % GUI_inputs - Individual inputs for the GUI + % hbox - Box in the lower part to insert the buttons + % button - Buttons for actions of the GUI + % + % NewRecordsGUI Methods: + % set_uicontrol(obj,parent) - define GUI object for the input + % set_default(obj, default) - write default value ("if applicable") + % get_value(obj) - read value written by user + % check_input(obj, input) - check if input is correct + + %_________________________________________________________________________________________________ + properties (Constant) + + %Images for buttons in GUI + DIR_IMAGE = fullfile(fileparts(mfilename('fullpath')), 'Images') + + % General GUI Properties + GUI_NAME = 'Add user to lab' + GUI_IS_SMALLSCREEN = ScreenProperties.checkMonitorSize() + GUI_POSITION = [0 45 -1 -45] + GUI_POSITION_MODE = 'OuterPosition' + GUI_FONT = conditional(AnimalDatabase.GUI_IS_SMALLSCREEN, 9, 14) + + % Title part Properties + TITLE_FONTSIZE = 15 + TITLE_MESSAGE = 'Add new users to the database: ' + TITLE_BKG_CLR = [1 1 1]*0.97; + TITLE_CLR = [0 0 0]; + + % Grid Properties + GRID_NUM_COLUMNS = 2 + + % Labels Properties + LABEL_FONTSIZE = conditional(ScreenProperties.IS_SMALL_SCREEN, 10, 14) + LABEL_BKG_CLR = [1 1 1]*0.97; + LABEL_TOOL_TIP_START = '
' + LABEL_TOOL_TIP_END = '
' + LABEL_CLR = [0 0 0]; + + % Vbox Properties + VBOX_SPACING = 10 + VBOX_HEIGHTS = [30 -1 60] + + % Hbox Properties + HBOX_SPACING = 10 + HBOX_WIDTHS = [-1 60] + + % Buttons Properties + BUTTON_SIZE = [50 50] + BUTTON_IMAGE = fullfile(NewRecordsGUI.DIR_IMAGE, 'add_button_image.png') + + end + + %_________________________________________________________________________________________________ + properties (Access = protected, Transient) + + figGUI + panel + vbox + title + grid + GUI_inputs + GUI_inputs_info + hbox + button + + end + + %_________________________________________________________________________________________________ + properties (SetAccess = protected) + + DatabaseTable + GUI_info + + end + + methods + + function delete_previous(~) + % Close opened GUI if we have to open it again + + %Get all open figures + figHandles = findobj('Type', 'figure'); + + % If we find a figure with the same name we close it + for i=1:length(figHandles) + if strcmp(figHandles(i).Name,NewRecordsGUI.GUI_NAME) + delete(figHandles(i)) + end + end + + end + + function obj = NewRecordsGUI() + % Class constructor, define initial object properties + % + % Outputs: + % obj = NewRecordsGUI object + + %Delete previous opened figures + obj.delete_previous(); + + %Get reference from tables to update + obj.DatabaseTable = DataJointLabUserTable(); + %Set useful information for the GUI inputs in order to create + %the GUI + obj.GUI_inputs_info = obj.DatabaseTable.GUI_info; + %Actually create the GUI + obj.create_gui(); + + end + + end + + +end diff --git a/database/AddLabUsers/@NewRecordsGUI/close_figure.m b/database/AddLabUsers/@NewRecordsGUI/close_figure.m new file mode 100644 index 0000000..e5275dc --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/close_figure.m @@ -0,0 +1,13 @@ +function close_figure(obj, handle, event) +%Simple function to handle close event +% +% Inputs: +% obj = AddRecordsGUI object + +% Delete object if needed +if ishghandle(obj.figGUI) + delete(obj.figGUI); +end +obj.figGUI = gobjects(0); + +end \ No newline at end of file diff --git a/database/AddLabUsers/@NewRecordsGUI/create_GUI_input.m b/database/AddLabUsers/@NewRecordsGUI/create_GUI_input.m new file mode 100644 index 0000000..8882368 --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/create_GUI_input.m @@ -0,0 +1,39 @@ +function GUI_input = create_GUI_input(obj, parent, field_info) +% Create a corresponding GUI input object for each field input +% +% Inputs: +% obj = AddRecordsGUI object +% parent = Parent GUI object for the GUI_input object +% field_info = structure with information about each field +% tooltip = string tooltip for the field +% +% Outputs +% GUI_input = GUI_input object for the field + + +%Create correspondin GUI_input depending of gui_type +if strcmp(field_info.gui_type, 'blob') + %Blob is normally an array of entries + %So the corresponding GUI_input is a hbox with multiple edits + GUI_input = GUI_Input_HBox(parent, ... + field_info.name, ... + field_info.example_value, ... + field_info.datatype); + +elseif strcmp(field_info.gui_type, 'popupmenu') + %Popumenu is normally for inserting foreign keys inputs + GUI_input = GUI_Input_Popup(parent, ... + field_info.name, ... + field_info.list_values, ... + field_info.default, ... + field_info.datatype); + +else + %With other inputs a simple edit would be enough + GUI_input = GUI_Input_Edit(parent, ... + field_info.name, ... + field_info.default, ... + field_info.datatype); +end + +end \ No newline at end of file diff --git a/database/AddLabUsers/@NewRecordsGUI/create_buttons.m b/database/AddLabUsers/@NewRecordsGUI/create_buttons.m new file mode 100644 index 0000000..dbb2c19 --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/create_buttons.m @@ -0,0 +1,27 @@ +function button = create_buttons(obj, parent) +% Create a simple add record button for the GUI +% +% Inputs: +% obj = AddRecordsGUI object +% parent = Parent GUI object for the button +% +% Outputs +% button = GUI object for the button + + +%Read and resize image for the button +img = imread(obj.BUTTON_IMAGE); +img = imresize(img, obj.BUTTON_SIZE); +img = image(img); +img = img.CData; + +%Create button +button = uicontrol ( ... + 'Parent' , parent, ... + 'Style' , 'pushbutton', ... + 'String' , '', ... + 'cdata' , img, ... + 'Callback', @obj.GUI_add_user ... + ); + +end \ No newline at end of file diff --git a/database/AddLabUsers/@NewRecordsGUI/create_gui.m b/database/AddLabUsers/@NewRecordsGUI/create_gui.m new file mode 100644 index 0000000..50e6c34 --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/create_gui.m @@ -0,0 +1,62 @@ +function create_gui(obj) +%Define all graphic objects for the AddRecordsGUI +% +% Inputs: +% obj = AddRecordsGUI object + + +%% Define a figure +obj.figGUI = figure( ... + 'Name' , obj.GUI_NAME, ... + 'ToolBar' , 'none', ... + 'MenuBar' , 'none', ... + 'NumberTitle' , 'off', ... + 'Visible' , 'off', ... + 'Tag' , 'persist', ... + 'CloseRequestFcn' , @obj.close_figure ... + ); +% Define figure position and size +figure_position = obj.define_figure_position(NewRecordsGUI.GUI_POSITION); +set(obj.figGUI, NewRecordsGUI.GUI_POSITION_MODE, figure_position) + + +%% Define a panel +obj.panel = uix.Panel( ... + 'Parent', obj.figGUI, ... + 'Padding', 5 ); + + +%% Define the vbox to separate the GUI in three (title, inputs and buttons) +obj.vbox = uix.VBox( ... + 'Parent', obj.panel, ... + 'Spacing', obj.VBOX_SPACING); + + +%% Define the title +obj.title = obj.create_title(obj.vbox, obj.TITLE_MESSAGE); + + +%% Define the grid GUI input +[obj.grid, obj.GUI_inputs] = obj.create_table_grid(obj.vbox); + + +%% Define an hbox to insert the buttons of the GUI +obj.hbox = uix.HBox( ... + 'Parent', obj.vbox, ... + 'Spacing', obj.HBOX_SPACING); + + +%% All space not used by buttons will be occupied by an empty object +uix.Empty( 'Parent', obj.hbox ); + + +%% Create all buttons for the GUI +obj.button = obj.create_buttons(obj.hbox); + + +%% Adjust width and height for hbox and vbox +set(obj.hbox, 'Widths', obj.HBOX_WIDTHS); +set(obj.vbox, 'Heights', obj.VBOX_HEIGHTS); +set(obj.figGUI, 'Visible', 'on'); + +end \ No newline at end of file diff --git a/database/AddLabUsers/@NewRecordsGUI/create_label.m b/database/AddLabUsers/@NewRecordsGUI/create_label.m new file mode 100644 index 0000000..124e2fa --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/create_label.m @@ -0,0 +1,23 @@ +function label = create_label(obj, parent, name, tooltip) +% Create a simple label object for the GUI +% +% Inputs: +% obj = AddRecordsGUI object +% parent = Parent GUI object for the label +% name = string Label for the field +% tooltip = string tooltip for the field +% +% Outputs +% title = GUI object for the label + +label = uicontrol ( ... + 'Parent', parent, ... + 'Style', 'text', ... + 'String', name, ... + 'FontSize', obj.LABEL_FONTSIZE, ... ... + 'BackgroundColor', obj.LABEL_BKG_CLR, ... + 'TooltipString', [obj.LABEL_TOOL_TIP_START tooltip obj.LABEL_TOOL_TIP_END], ... + 'ForegroundColor', obj.LABEL_CLR, ... + 'FontWeight', 'bold'); + +end diff --git a/database/AddLabUsers/@NewRecordsGUI/create_table_grid.m b/database/AddLabUsers/@NewRecordsGUI/create_table_grid.m new file mode 100644 index 0000000..c634583 --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/create_table_grid.m @@ -0,0 +1,40 @@ +function [grid, gui_input_objects] = create_table_grid(obj, parent) +% Create a input Grid for the GUI +% +% Inputs: +% obj = AddRecordsGUI object +% parent = Parent GUI object for the grid +% +% Outputs +% grid = GUI object for the grid +% gui_input_objects = array of objects to recieve input from user + + +% Get how many inputs the GUI would have +num_inputs = length(obj.GUI_inputs_info); +grid = uix.Grid( 'Parent', parent, 'Spacing', 5 ); + +%Initialize labels and input objects +field_labels = cell(num_inputs, 1); +gui_input_objects = cell(num_inputs, 1); + + +%Define labels with name for each field +for i = 1:num_inputs + field_info = obj.GUI_inputs_info(i); + field_labels{i} = obj.create_label(grid, ... + field_info.name, field_info.tooltip); +end + +%Define GUI input objects +for i = 1:num_inputs + field_info = obj.GUI_inputs_info(i); + gui_input_objects{i} = obj.create_GUI_input(grid, field_info); +end + +%Set widths and heights for the grid +grid_widths = -1*ones(NewRecordsGUI.GRID_NUM_COLUMNS,1); +grid_heights = -1*ones(num_inputs,1); +set(grid, 'Widths', grid_widths, 'Heights', grid_heights); + +end diff --git a/database/AddLabUsers/@NewRecordsGUI/create_title.m b/database/AddLabUsers/@NewRecordsGUI/create_title.m new file mode 100644 index 0000000..75eb2ff --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/create_title.m @@ -0,0 +1,21 @@ +function title = create_title(obj, parent, title_str) +% Create a simple title object for the GUI +% +% Inputs: +% obj = AddRecordsGUI object +% parent = Parent GUI object for the title +% title_str = String for the title +% +% Outputs +% title = GUI object for the title + +title = uicontrol ( ... + 'Parent', parent, ... + 'Style', 'text', ... + 'String', title_str, ... + 'FontSize', obj.TITLE_FONTSIZE, ... + 'BackgroundColor', obj.TITLE_BKG_CLR, ... + 'ForegroundColor', obj.TITLE_CLR, ... + 'FontWeight', 'bold'); + +end diff --git a/database/AddLabUsers/@NewRecordsGUI/define_figure_position.m b/database/AddLabUsers/@NewRecordsGUI/define_figure_position.m new file mode 100644 index 0000000..09d3b10 --- /dev/null +++ b/database/AddLabUsers/@NewRecordsGUI/define_figure_position.m @@ -0,0 +1,31 @@ +function [position] = define_figure_position(~, position) +%Define the figure position and make correspondant transformation +% +% Inputs: +% position = Initial position coordentates for GUI figure +% Outputs: +% position = Final position coordentates after doing transformations + + % Get the screen coordinates to reference the figure position against + screenSize = get(0, 'MonitorPosition'); + + % Convert position to relative coordinate if necessary + position(1:2) = standardCoordinate(position(1:2), screenSize(3:4)) + screenSize(1:2); + position(3:4) = standardCoordinate(position(3:4), screenSize(3:4)); + +end + +function coordinate = standardCoordinate(coordinate, range) +% Convert position to relative coordinate if necessary + + + for iCoord = 1:numel(coordinate) + if coordinate(iCoord) < 0 + coordinate(iCoord) = range(iCoord) + coordinate(iCoord)+1; + elseif abs(coordinate(iCoord)) <= 1 + coordinate(iCoord) = range(iCoord) * coordinate(iCoord); + end + end + coordinate(isnan(coordinate)) = min(coordinate, [], 'omitnan'); + +end diff --git a/database/AddLabUsers/GUI_Inputs/GUI_Input.m b/database/AddLabUsers/GUI_Inputs/GUI_Input.m new file mode 100644 index 0000000..5225971 --- /dev/null +++ b/database/AddLabUsers/GUI_Inputs/GUI_Input.m @@ -0,0 +1,47 @@ +classdef (Abstract) GUI_Input + % GUI_Input Summary of GUI_Input + % Abstract class that defines an interface for different types of + % inputs in a GUI. (Edits, Popupmenu and HBox or list of edits) + % + % GUI_Input Properties: + % GUI_INPUT_FONTSIZE - Fontsize of the input + % GUI_INPUT_BKG_CLR - Background color of the input + % GUI_INPUT_FOR_CLR - Foreground color of the input + % name - Field name that input is attached to + % uicontrolable - GUI object for the input + % datatype - Field datatype for database + % + % GUI_Input Methods: + % set_uicontrol(obj,parent) - define GUI object for the input + % set_default(obj, default) - write default value ("if applicable") + % get_value(obj) - read value written by user + % check_input(obj, input) - check if input is correct + + properties + + GUI_INPUT_FONTSIZE = conditional(ScreenProperties.IS_SMALL_SCREEN, 9, 14) + GUI_INPUT_BKG_CLR = [1 1 1]; + GUI_INPUT_FOR_CLR = [0 0 0]; + + end + + properties (Abstract) + + name + uicontrolable + datatype + + end + + methods(Abstract) + + set_uicontrol(obj,parent) + set_default(obj, default) + + get_value(obj) + check_input(obj, input) + + end + +end + diff --git a/database/AddLabUsers/GUI_Inputs/GUI_Input_Edit.m b/database/AddLabUsers/GUI_Inputs/GUI_Input_Edit.m new file mode 100644 index 0000000..dede933 --- /dev/null +++ b/database/AddLabUsers/GUI_Inputs/GUI_Input_Edit.m @@ -0,0 +1,137 @@ +classdef GUI_Input_Edit < GUI_Input + % GUI_Input_Edit Summary of GUI_Input_Edit + % GUI_Input implementarion with functions for a edit uicontrol + % + % GUI_Input_Edit Properties: + % GUI_INPUT_FONTSIZE - Fontsize of the input + % GUI_INPUT_BKG_CLR - Background color of the input + % GUI_INPUT_FOR_CLR - Foreground color of the input + % name - Field name that input is attached to + % uicontrolable - GUI object for the input + % datatype - Field datatype for database + % + % GUI_Input_Edit Methods: + % set_uicontrol(obj,parent) - define GUI object for the input + % set_default(obj, default) - write default value ("if applicable") + % get_value(obj) - read value written by user + % check_input(obj, input) - check if input is correct + + properties (Constant) + end + + properties + name + uicontrolable + datatype + end + + methods + + function uicontrolable = set_uicontrol(obj, parent) + %Define uicontrol (edit) for the input + % + % Inputs: + % obj = GUI_input_Edit object + % parent = uicontrol parent of the GUI_input + % + % Outputs: + % uicontrolable = uicontrol edit object for the input + + uicontrolable = uicontrol ( ... + 'Parent', parent, ... + 'Style', 'edit', ... + 'FontSize', obj.GUI_INPUT_FONTSIZE, ... ... + 'BackgroundColor', obj.GUI_INPUT_BKG_CLR, ... + 'ForegroundColor', obj.GUI_INPUT_FOR_CLR); + + + end + + function value = get_value(obj) + % Read value written by user + % + % Inputs: + % obj = GUI_input_Edit object + % + % Outputs: + % value = value written by user (transformed if needed by GUI) + + value = get(obj.uicontrolable, 'String'); + %If datatype for the object is numeric, try to convert it + if strcmp(obj.datatype,'numeric') + try + value = str2double(value); + catch + end + end + + end + + + function set_default(obj, default) + % Write default value for the input + % + % Inputs: + % obj = GUI_input_Edit object + % default = default value to write + + if ~isempty(default) + set(obj.uicontrolable, 'String', default); + end + + end + + function [status, error] = check_input(obj, input) + % Check fot data compliance (w/datatype defined by object) + % + % Inputs: + % obj = GUI_input_Edit object + % input = Value written (and transformed) + % + % Outputs: + % status = true if input is correct, false otherwise + % error = error message to inform user why input is incorrect + + status = true; + error = ''; + %Check if value is numeric + if strcmp(obj.datatype,'numeric') + status = isnumeric(input); + error_msg = ': Input is not numeric'; + %Check if value is string + elseif strcmp(obj.datatype,'string') + status = ischar(input); + error_msg = ': Input is not string'; + end + + %If value is incorrect append field name + % and correspondent error message + if ~status + error = strcat([obj.name error_msg]); + end + + end + + function obj = GUI_Input_Edit(parent, name, default, datatype) + % Class constructor, define initial object properties + % + % Inputs: + % parent = parent uiobject for the GUI_input_Edit object + % name = name of the input field (for database) + % default = default value for input + % datatype = intended datatype for input + % + % Outputs: + % obj = input object + + obj.name = name; + obj.datatype = datatype; + obj.uicontrolable = obj.set_uicontrol(parent); + obj.set_default(default) + + + end + end + +end + diff --git a/database/AddLabUsers/GUI_Inputs/GUI_Input_HBox.m b/database/AddLabUsers/GUI_Inputs/GUI_Input_HBox.m new file mode 100644 index 0000000..b5db138 --- /dev/null +++ b/database/AddLabUsers/GUI_Inputs/GUI_Input_HBox.m @@ -0,0 +1,172 @@ +classdef GUI_Input_HBox < GUI_Input + % GUI_Input_HBox Summary of GUI_Input_Edit + % GUI_Input implementarion with functions for a hbox (edit array) uicontrol + % This object is intended for blob values in the database + % + % GUI_Input_HBox Properties: + % GUI_INPUT_FONTSIZE - Fontsize of the input + % GUI_INPUT_BKG_CLR - Background color of the input + % GUI_INPUT_FOR_CLR - Foreground color of the input + % GUI_INPUT_SPACING - Spacing between edits + % name - Field name that input is attached to + % uicontrolable - GUI object for the input + % uiedits - uiobject edits cell array + % datatype - Field datatype for database + % + % GUI_Input_HBox Methods: + % create_edit(obj, parent) - define 1 uiobject edit for the array + % set_uicontrol(obj,parent) - define GUI object for the input + % set_default(obj, default) - write default value ("if applicable") + % get_value(obj) - read value written by user + % check_input(obj, input) - check if input is correct + + properties (Constant) + GUI_INPUT_SPACING = 20 + end + + properties + name + uicontrolable + uiedits + datatype + size + end + + methods + + function uiedit = create_edit(obj, parent) + %Define uicontrol (edit) for the input array + % + % Inputs: + % obj = GUI_Input_HBox object + % parent = uicontrol parent of the GUI_input + % + % Outputs: + % uicontrolable = uicontrol edit object for the input + + uiedit = uicontrol ( ... + 'Parent', parent, ... + 'Style', 'edit', ... + 'FontSize', obj.GUI_INPUT_FONTSIZE, ... ... + 'BackgroundColor', obj.GUI_INPUT_BKG_CLR, ... + 'ForegroundColor', obj.GUI_INPUT_FOR_CLR); + + + end + + function [uicontrolable, uiedits] = set_uicontrol(obj, parent) + %Define uicontrol (hbox) for the input + % + % Inputs: + % obj = GUI_Input_HBox object + % parent = uicontrol parent of the GUI_input + % + % Outputs: + % uicontrolable = uicontrol edit object for the input + + uicontrolable = uix.HBox ( ... + 'Parent', parent, .... + 'Spacing', obj.GUI_INPUT_SPACING, ...... + 'BackgroundColor', obj.GUI_INPUT_BKG_CLR); + + uiedits = cell(obj.size, 1); + for i = 1:obj.size + + uiedits{i} = obj.create_edit(uicontrolable); + + end + + + end + + function values = get_value(obj) + % Read value written by user + % + % Inputs: + % obj = GUI_Input_HBox object + % + % Outputs: + % values = values written by user (transformed if needed by GUI) + + %Create cell for writting all edit values + values = cell(1,obj.size); + for i=1:obj.size + %Read each one of the edits + values{i} = get(obj.uiedits{i}, 'String'); + %Transform if applicable + if strcmp(obj.datatype,'numeric array') + transform = str2double(values{i}); + if ~isnan(transform) + values{i} = transform; + end + end + end + + %Transform from cell to array if applicable + %Normally blob inputs in database are numeric arrays + if strcmp(obj.datatype,'numeric array') + if all(cellfun(@isnumeric,values,'UniformOutput',true)) + values = cell2mat(values); + end + end + + end + + function [status, error] = check_input(obj, input) + % Check fot data compliance (w/datatype defined by object) + % + % Inputs: + % obj = GUI_Input_HBox object + % input = Value written (and transformed) + % + % Outputs: + % status = true if input is correct, false otherwise + % error = error message to inform user why input is incorrect + + status = true; + error = ''; + %Check if value is string cell + if strcmp(obj.datatype,'cell string') + status = iscellstr(input); + error_msg = ': Input is not conformed of only strings'; + %Check if value is numeric array + elseif strcmp(obj.datatype,'numeric array') + status = isnumeric(input) & ~iscell(input); + error_msg = ': Input is not conformed of only numbers'; + end + + %If value is incorrect append field name + % and correspondent error message + if ~status + error = strcat([obj.name error_msg]); + end + + end + + function set_default(obj, default) + %Not defined + end + + function obj = GUI_Input_HBox(parent, name, example_value, datatype) + % Class constructor, define initial object properties + % + % Inputs: + % parent = parent object for the GUI_Input_HBox object + % name = name of the input field (for database) + % example_value = example value for this input + % datatype = intended datatype for input + % + % Outputs: + % obj = input object + + obj.name = name; + obj.datatype = datatype; + obj.size = length(example_value); + [obj.uicontrolable, obj.uiedits] = obj.set_uicontrol(parent); + + + end + end + +end + diff --git a/database/AddLabUsers/GUI_Inputs/GUI_Input_Popup.m b/database/AddLabUsers/GUI_Inputs/GUI_Input_Popup.m new file mode 100644 index 0000000..6f1ad43 --- /dev/null +++ b/database/AddLabUsers/GUI_Inputs/GUI_Input_Popup.m @@ -0,0 +1,148 @@ +classdef GUI_Input_Popup < GUI_Input + % GUI_Input_Popup Summary of GUI_Input_Edit + % GUI_Input implementarion with functions for a popmenu uicontrol + % + % GUI_Input_Popup Properties: + % GUI_INPUT_FONTSIZE - Fontsize of the input + % GUI_INPUT_BKG_CLR - Background color of the input + % GUI_INPUT_FOR_CLR - Foreground color of the input + % name - Field name that input is attached to + % uicontrolable - GUI object for the input + % datatype - Field datatype for database + % value_list - List of possible values for input + % + % GUI_Input_Popup Methods: + % set_uicontrol(obj,parent) - define GUI object for the input + % set_default(obj, default) - write default value ("if applicable") + % get_value(obj) - read value written by user + % check_input(obj, input) - check if input is correct + % set_value_list(obj, value_list) - + + properties + name + uicontrolable + datatype + value_list + end + + methods + + function uicontrolable = set_uicontrol(obj, parent) + %Define uicontrol (popupmenu) for the input + % + % Inputs: + % obj = GUI_input_Popup object + % parent = uicontrol parent of the GUI_input + % + % Outputs: + % uicontrolable = uicontrol edit object for the input + + uicontrolable = uicontrol ( ... + 'Parent', parent, ... + 'Style', 'popupmenu', ... + 'String', {''}, ... + 'Value', 1, ... + 'FontSize', obj.GUI_INPUT_FONTSIZE, ... ... + 'BackgroundColor', obj.GUI_INPUT_BKG_CLR, ... + 'ForegroundColor', obj.GUI_INPUT_FOR_CLR); + + end + + function value = get_value(obj) + % Read value written by user + % + % Inputs: + % obj = GUI_input_Popup object + % + % Outputs: + % value = value written by user + + list = get(obj.uicontrolable, 'String'); + idx = get(obj.uicontrolable, 'Value'); + value = list{idx}; + + end + + function values = set_value_list(obj, values) + % Write all possible values for input + % + % Inputs: + % obj = GUI_input_Popup object + % values = value list to write for the popupmenu + + set (obj.uicontrolable, 'String', values); + + end + + function set_default(obj, default) + % Write default value for the input + % + % Inputs: + % obj = GUI_input_Popup object + % default = default value to write + + if ~isempty(default) + index = find(strcmpi(get(obj.uicontrolable, 'String'), default), 1); + if isempty(index) + error('Default not found'); + end + set( obj.uicontrolable, 'Value', index ); + end + + end + + function [status, error] = check_input(obj, input) + % Check fot data compliance (w/datatype defined by object) + % + % Inputs: + % obj = GUI_input_Popup object + % input = Value written (and transformed) + % + % Outputs: + % status = true if input is correct, false otherwise + % error = error message to inform user why input is incorrect + + status = true; + error = ''; + %Check if numeric value is in cell of accepted values + if strcmp(obj.datatype,'numeric') + status = any(cellfun(@(x) x==input,obj.value_list)); + error_msg = ': Input is not in accepted values'; + %Check if string value is in cell of accepted values + elseif strcmp(obj.datatype,'string') + status = any(find(strcmp(obj.value_list, input),1)); + error_msg = ': Input is not in accepted values'; + end + + %If value is incorrect append field name + % and correspondent error message + if ~status + error = strcat([obj.name error_msg]); + end + + end + + function obj = GUI_Input_Popup(parent, name, list_values, default, datatype) + % Class constructor, define initial object properties + % + % Inputs: + % parent = parent uiobject for the GUI_input_Popup object + % name = name of the input field (for database) + % list_values = value of accepted values for input + % default = default value for input + % datatype = intended datatype for input + % + % Outputs: + % obj = input object + + obj.name = name; + obj.datatype = datatype; + obj.uicontrolable = obj.set_uicontrol(parent); + obj.value_list = obj.set_value_list(list_values); + obj.set_default(default); + + end + end + +end + diff --git a/database/AddLabUsers/ScreenProperties.m b/database/AddLabUsers/ScreenProperties.m new file mode 100644 index 0000000..2c8a301 --- /dev/null +++ b/database/AddLabUsers/ScreenProperties.m @@ -0,0 +1,23 @@ +classdef ScreenProperties + %ScreenProperties Summary of this class goes here + % Detailed explanation goes here + + properties (Constant) + + LARGE_WIDTH = 1920 + LARGE_HEIGHT = 1080 + IS_SMALL_SCREEN = ScreenProperties.checkMonitorSize() + end + + methods (Static) + + %----- Returns true if the screen size is smaller than a given area in pixels + function isSmall = checkMonitorSize() + monitors = get(0,'ScreenSize'); + screenArea = prod(monitors(1,3:end)); + isSmall = screenArea < ScreenProperties.LARGE_WIDTH*ScreenProperties.LARGE_HEIGHT; + end + end + +end + diff --git a/database/AnimalDatabase.m b/database/AnimalDatabase.m index 8af07f9..7e4f0b6 100644 --- a/database/AnimalDatabase.m +++ b/database/AnimalDatabase.m @@ -1570,9 +1570,14 @@ function layoutGUI(obj) , 'XColor', [1 1 1]*0.7, 'YColor', [1 1 1]*0.7, 'XTick', [], 'YTick', [], 'Visible', 'off', 'Clipping', 'off' ); obj.btn.weighMode = uicontrol( 'Parent', obj.cnt.controls, 'FontSize', AnimalDatabase.GUI_FONT, 'Interruptible', 'off', 'BusyAction', 'cancel', 'UserData', 0 ); uix.Empty( 'Parent', obj.cnt.controls ); - obj.btn.checkInOut = uicontrol( 'Parent', obj.cnt.controls, 'Style', 'pushbutton', 'String', 'Check In/Out' ... - , 'TooltipString', '
Selection screen to check in/out cages
' ... - , 'FontSize', AnimalDatabase.GUI_FONT, 'Enable', 'off', 'Interruptible', 'off', 'BusyAction', 'cancel' ); +% obj.btn.checkInOut = uicontrol( 'Parent', obj.cnt.controls, 'Style', 'pushbutton', 'String', 'Check In/Out' ... +% , 'TooltipString', '
Selection screen to check in/out cages
' ... +% , 'FontSize', AnimalDatabase.GUI_FONT, 'Enable', 'off', 'Interruptible', 'off', 'BusyAction', 'cancel' ); + + obj.btn.addUser = uicontrol( 'Parent', obj.cnt.controls, 'Style', 'pushbutton', 'String', 'AddUser' ... + , 'TooltipString', '
Screen to input information about new users
' ... + , 'FontSize', AnimalDatabase.GUI_FONT, 'Enable', 'off', 'Interruptible', 'off', 'BusyAction', 'cancel' ); + obj.btn.finalize = uicontrol( 'Parent', obj.cnt.controls, 'Style', 'pushbutton', 'String', 'FINALIZE' ... , 'TooltipString', '
Check that all animals you''re responsible for have been handled
' ... , 'FontSize', AnimalDatabase.GUI_FONT, 'Interruptible', 'off', 'BusyAction', 'cancel' ); @@ -1605,7 +1610,7 @@ function layoutGUI(obj) set(obj.cnt.main , 'Heights', [1.2*AnimalDatabase.GUI_BTNSIZE + 2*AnimalDatabase.GUI_BORDER, -1]); set(obj.cnt.config , 'Widths' , [10*AnimalDatabase.GUI_BTNSIZE, -1]); set(obj.cnt.person , 'Widths' , [4*AnimalDatabase.GUI_BTNSIZE, -1]); - set(obj.cnt.controls , 'Widths' , [AnimalDatabase.GUI_BTNSIZE, -1, 7*AnimalDatabase.GUI_BTNSIZE, AnimalDatabase.GUI_BTNSIZE, 0, 9.5*AnimalDatabase.GUI_BTNSIZE]); + set(obj.cnt.controls , 'Widths' , [AnimalDatabase.GUI_BTNSIZE, -1, 7*AnimalDatabase.GUI_BTNSIZE, AnimalDatabase.GUI_BTNSIZE, 4*AnimalDatabase.GUI_BTNSIZE, 9.5*AnimalDatabase.GUI_BTNSIZE]); set(obj.cnt.data , 'Widths' , [3*(1 + AnimalDatabase.MAX_ANI_GROUP)*elemSize + 0.5*AnimalDatabase.GUI_BTNSIZE, -1]); set(obj.cnt.overview , 'Heights', [2*AnimalDatabase.GUI_BTNSIZE, -1]); @@ -1722,6 +1727,7 @@ function showResponsible(obj, hObject, event, showNextAni) %% Restore non-busy cursor %set(obj.btn.checkInOut, 'Enable', 'on', 'Callback', {@obj.checkoutGUI, personID}); + set(obj.btn.addUser, 'Enable', 'on', 'Callback', {@obj.callAddUser}); set(obj.btn.finalize, 'Callback', {@obj.areWeThereYet, personID}); obj.checkUpdateTimer([], [], true); @@ -3517,9 +3523,15 @@ function performanceGUI(obj) , 'XColor', [1 1 1]*0.7, 'YColor', [1 1 1]*0.7, 'XTick', [], 'YTick', [], 'Visible', 'off', 'Clipping', 'off' ); obj.btn.weighMode = uicontrol( 'Parent', obj.cnt.controls, 'FontSize', AnimalDatabase.GUI_FONT, 'Interruptible', 'off', 'BusyAction', 'cancel', 'UserData', 0 ); uix.Empty( 'Parent', obj.cnt.controls ); - obj.btn.checkInOut = uicontrol( 'Parent', obj.cnt.controls, 'Style', 'pushbutton', 'String', 'Check In/Out' ... - , 'TooltipString', '
Selection screen to check in/out cages
' ... - , 'FontSize', AnimalDatabase.GUI_FONT, 'Enable', 'off', 'Interruptible', 'off', 'BusyAction', 'cancel' ); + + %obj.btn.checkInOut = uicontrol( 'Parent', obj.cnt.controls, 'Style', 'pushbutton', 'String', 'Check In/Out' ... + % , 'TooltipString', '
Selection screen to check in/out cages
' ... + % , 'FontSize', AnimalDatabase.GUI_FONT, 'Enable', 'off', 'Interruptible', 'off', 'BusyAction', 'cancel' ); + + obj.btn.addUser = uicontrol( 'Parent', obj.cnt.controls, 'Style', 'pushbutton', 'String', 'AddUser' ... + , 'TooltipString', '
Screen to input information about new users
' ... + , 'FontSize', AnimalDatabase.GUI_FONT, 'Enable', 'off', 'Interruptible', 'off', 'BusyAction', 'cancel' ); + obj.btn.finalize = uicontrol( 'Parent', obj.cnt.controls, 'Style', 'pushbutton', 'String', 'FINALIZE' ... , 'TooltipString', '
Check that all animals you''re responsible for have been handled
' ... , 'FontSize', AnimalDatabase.GUI_FONT, 'Interruptible', 'off', 'BusyAction', 'cancel' ); @@ -3552,7 +3564,7 @@ function performanceGUI(obj) set(obj.cnt.main , 'Heights', [1.2*AnimalDatabase.GUI_BTNSIZE + 2*AnimalDatabase.GUI_BORDER, -1]); set(obj.cnt.config , 'Widths' , [10*AnimalDatabase.GUI_BTNSIZE, -1]); set(obj.cnt.person , 'Widths' , [4*AnimalDatabase.GUI_BTNSIZE, -1]); - set(obj.cnt.controls , 'Widths' , [AnimalDatabase.GUI_BTNSIZE, -1, 7*AnimalDatabase.GUI_BTNSIZE, AnimalDatabase.GUI_BTNSIZE, 0, 9.5*AnimalDatabase.GUI_BTNSIZE]); + set(obj.cnt.controls , 'Widths' , [AnimalDatabase.GUI_BTNSIZE, -1, 7*AnimalDatabase.GUI_BTNSIZE, AnimalDatabase.GUI_BTNSIZE, 4*AnimalDatabase.GUI_BTNSIZE, 9.5*AnimalDatabase.GUI_BTNSIZE]); set(obj.cnt.data , 'Widths' , [3*(1 + AnimalDatabase.MAX_ANI_GROUP)*elemSize + 0.5*AnimalDatabase.GUI_BTNSIZE, -1]); set(obj.cnt.overview , 'Heights', [2*AnimalDatabase.GUI_BTNSIZE, -1]); @@ -6084,6 +6096,12 @@ function updateAnimalSummary(obj, handle, event, ignoreBusy) end + function callAddUser(obj, hObject, event) + + NewRecordsGUI(); + + end + end end