% INPUTGUI - A comprehensive gui automatic builder. This function helps
% to create GUI very quickly without bothering about the
% positions of the elements. After creating a geometry,
% elements just place themselves in the predefined
% locations. It is especially useful for figures in which
% you intend to put text buttons and descriptions.
%
% Usage:
% >> [ outparam ] = inputgui( 'key1', 'val1', 'key2', 'val2', ... );
% >> [ outparam userdat strhalt outstruct tags] = ...
% inputgui( 'key1', 'val1', 'key2', 'val2', ... );
%
% Inputs:
% 'geom' - cell array of cell array of integer vector. Each cell
% array defines the coordinate of a given input in the
% following manner: { nb_row nb_col [x_topcorner y_topcorner]
% [x_bottomcorner y_bottomcorner] };
% 'geometry' - cell array describing horizontal geometry. This corresponds
% to the supergui function input 'geomhoriz'
% 'geomvert' - vertical geometry argument, this argument is passed on to
% the supergui function
% 'uilist' - list of uicontrol lists describing elements properties
% { { ui1 }, { ui2 }... }, { 'uiX' } being GUI matlab
% uicontrol arguments such as { 'style', 'radiobutton',
% 'String', 'hello' }. See Matlab function UICONTROL for details.
% 'helpcom' - optional help command
% 'helpbut' - text for help button (default is "Help")
% 'okbut' - text for OK button (default is "OK")
% 'title' - optional figure title
% 'userdata' - optional userdata input for the figure
% 'mode' - ['normal'|'noclose'|'plot' fignumber]. Either wait for
% user to press OK or CANCEL ('normal'), return without
% closing window input ('noclose'), only draw the gui ('plot')
% or process an existing window which number is given as
% input (fignumber). Default is 'normal'.
% 'eval' - [string] command to evaluate at the end of the creation
% of the GUI but before waiting for user input.
% 'screenpos' - see supergui.m help message.
% 'skipline' - ['on'|'off'] skip a row before the "OK" and "Cancel"
% button. Default is 'on'.
%
% Output:
% outparam - list of outputs. The function scans all lines and
% add up an output for each interactive uicontrol, i.e
% edit box, radio button, checkbox and listbox.
% userdat - 'userdata' value of the figure.
% strhalt - the function returns when the 'userdata' field of the
% button with the tag for OK button is modified. This returns the
% new value of this field.
% outstruct - returns outputs as a structure (only tagged ui controls
% are considered). The field name of the structure is
% the tag of the ui and contain the ui value or string.
% instruct - returns inputs provided in the same format as 'outstruct'
% This allow to compare in/outputs more easy.
% tags - uicontrols by tags
%
% Note: the function also adds three buttons at the bottom of each
% interactive windows: 'CANCEL', 'HELP' (if callback command
% is provided) and 'OK'.
%
% Example:
% res = inputgui('geometry', { 1 1 }, 'uilist', ...
% { { 'style' 'text' 'string' 'Enter a value' } ...
% { 'style' 'edit' 'string' '' } });
%
% res = inputgui('geom', { {2 1 [0 0] [1 1]} {2 1 [1 0] [1 1]} }, 'uilist', ...
% { { 'style' 'text' 'string' 'Enter a value' } ...
% { 'style' 'edit' 'string' '' } });
%
% Author: Arnaud Delorme, CNL / Salk Institute, La Jolla, 1 Feb 2002
%
% See also: SUPERGUI, EEGLAB
% Copyright (C) Arnaud Delorme, CNL/Salk Institute, 27 Jan 2002, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.
function [result, userdat, strhalt, resstruct, instruct, alltags] = inputgui( varargin);
result = [];
userdat = [];
strhalt = [];
resstruct = [];
if nargin < 2
help inputgui;
return;
end
% decoding input and backward compatibility
% -----------------------------------------
if ischar(varargin{1})
options = varargin;
else
options = { 'geometry' 'uilist' 'helpcom' 'title' 'userdata' 'mode' 'geomvert' };
options = { options{1:length(varargin)}; varargin{:} };
options = options(:)';
end
% checking inputs
% ---------------
g = finputcheck(options, { 'geom' 'cell' [] {}; ...
'geometry' {'cell','integer'} [] []; ...
'uilist' 'cell' [] {}; ...
'cancel' 'string' [] 'Cancel'; ...
'helpcom' { 'string','cell' } { [] [] } ''; ...
'title' 'string' [] ''; ...
'eval' 'string' [] ''; ...
'helpbut' 'string' [] 'Help'; ...
'okbut' 'string' [] 'OK'; ...
'skipline' 'string' { 'on' 'off' } 'on'; ...
'addbuttons' 'string' { 'on' 'off' } 'on'; ...
'userdata' '' [] []; ...
'getresult' 'real' [] []; ...
'minwidth' 'real' [] 200; ...
'screenpos' '' [] []; ...
'mode' '' [] 'normal'; ...
'geomvert' 'real' [] [] ...
}, 'inputgui');
if ischar(g), error(g); end
if isempty(g.getresult)
if ischar(g.mode)
fig = figure('visible', 'off');
set(fig, 'name', g.title);
set(fig, 'userdata', g.userdata);
if ~iscell( g.geometry )
oldgeom = g.geometry;
g.geometry = {};
for row = 1:length(oldgeom)
g.geometry = { g.geometry{:} ones(1, oldgeom(row)) };
end
end
% skip a line
if strcmpi(g.skipline, 'on')
g.geometry = { g.geometry{:} [1] };
if ~isempty(g.geom)
for ind = 1:length(g.geom)
g.geom{ind}{2} = g.geom{ind}{2}+1; % add one row
end
g.geom = { g.geom{:} {1 g.geom{1}{2} [0 g.geom{1}{2}-2] [1 1] } };
end
g.uilist = { g.uilist{:}, {} };
end
% add buttons
if strcmpi(g.addbuttons, 'on')
g.geometry = { g.geometry{:} [1 1 1 1] };
if ~isempty(g.geom)
for ind = 1:length(g.geom)
g.geom{ind}{2} = g.geom{ind}{2}+1; % add one row
end
g.geom = { g.geom{:} ...
{4 g.geom{1}{2} [0 g.geom{1}{2}-1] [1 1] }, ...
{4 g.geom{1}{2} [1 g.geom{1}{2}-1] [1 1] }, ...
{4 g.geom{1}{2} [2 g.geom{1}{2}-1] [1 1] }, ...
{4 g.geom{1}{2} [3 g.geom{1}{2}-1] [1 1] } };
end
if ~isempty(g.helpcom)
if ~iscell(g.helpcom)
g.uilist = { g.uilist{:}, { 'width' 80 'align' 'left' 'Style', 'pushbutton', 'string', g.helpbut, 'tag', 'help', 'callback', g.helpcom } {} };
else
g.uilist = { g.uilist{:}, { 'width' 80 'align' 'left' 'Style', 'pushbutton', 'string', 'Help gui', 'callback', g.helpcom{1} } };
g.uilist = { g.uilist{:}, { 'width' 80 'align' 'left' 'Style', 'pushbutton', 'string', 'More help', 'callback', g.helpcom{2} } };
end
else
g.uilist = { g.uilist{:}, {} {} };
end
g.uilist = { g.uilist{:}, { 'width' 80 'align' 'right' 'Style', 'pushbutton', 'string', g.cancel, 'tag' 'cancel' 'callback', 'close(gcbf)' } };
g.uilist = { g.uilist{:}, { 'width' 80 'align' 'right' 'stickto' 'on' 'Style', 'pushbutton', 'tag', 'ok', 'string', g.okbut, 'callback', 'set(gcbo, ''userdata'', ''retuninginputui'');' } };
end
% add the three buttons (CANCEL HELP OK) at the bottom of the GUI
% ---------------------------------------------------------------
if ~isempty(g.geom)
[~, ~, allobj, alltags] = supergui( 'fig', fig, 'minwidth', g.minwidth, 'geom', g.geom, 'uilist', g.uilist, 'screenpos', g.screenpos);
elseif isempty(g.geomvert)
[~, ~, allobj, alltags] = supergui( 'fig', fig, 'minwidth', g.minwidth, 'geomhoriz', g.geometry, 'uilist', g.uilist, 'screenpos', g.screenpos);
else
if strcmpi(g.skipline, 'on'), g.geomvert = [g.geomvert(:)' 1]; end
if strcmpi(g.addbuttons, 'on'),g.geomvert = [g.geomvert(:)' 1]; end
[~, ~, allobj, alltags] = supergui( 'fig', fig, 'minwidth', g.minwidth, 'geomhoriz', g.geometry, 'uilist', g.uilist, 'screenpos', g.screenpos, 'geomvert', g.geomvert(:)' );
end
else
fig = g.mode;
set(findobj('parent', fig, 'tag', 'ok'), 'userdata', []);
allobj = findobj('parent',fig);
allobj = allobj(end:-1:1);
end
% evaluate command before waiting?
% --------------------------------
if ~isempty(g.eval), eval(g.eval); end
instruct = outstruct(allobj); % Getting default values in the GUI.
% create figure and wait for return
% ---------------------------------
if ischar(g.mode) && (strcmpi(g.mode, 'plot') || strcmpi(g.mode, 'return') )
if strcmpi(g.mode, 'plot')
return; % only plot and returns
end
else
waitfor( findobj('parent', fig, 'tag', 'ok'), 'userdata');
end
else
fig = g.getresult;
allobj = findobj('parent',fig);
allobj = allobj(end:-1:1);
end
result = {};
userdat = [];
strhalt = '';
resstruct = [];
if ~(ishandle(fig)), return; end % Check if figure still exist
% output parameters
% -----------------
strhalt = get(findobj('parent', fig, 'tag', 'ok'), 'userdata');
[resstruct,result] = outstruct(allobj); % Output parameters
userdat = get(fig, 'userdata');
if isempty(g.getresult) && ischar(g.mode) && ( strcmp(g.mode, 'normal') || strcmp(g.mode, 'return') )
close(fig);
end
drawnow; % for windows
% function for gui res (deprecated)
% --------------------
% function g = myguihandles(fig, g)
% h = findobj('parent', fig);
% if ~isempty(get(h(index), 'tag'))
% try,
% switch get(h(index), 'style')
% case 'edit', g = setfield(g, get(h(index), 'tag'), get(h(index), 'string'));
% case { 'value' 'radio' 'checkbox' 'listbox' 'popupmenu' 'radiobutton' }, ...
% g = setfield(g, get(h(index), 'tag'), get(h(index), 'value'));
% end
% catch, end
% end
function [resstructout, resultout] = outstruct(allobj)
counter = 1;
resultout = {};
resstructout = [];
for index=1:length(allobj)
if iscell(allobj), currentobj = allobj{index};
else currentobj = allobj(index);
end
if isnumeric(currentobj) || ~isprop(currentobj,'GetPropertySpecification') % To allow new object handles
try
objstyle = get(currentobj, 'style');
switch lower( objstyle )
case { 'listbox', 'checkbox', 'radiobutton' 'popupmenu' 'radio' }
resultout{counter} = get( currentobj, 'value');
if ~isempty(get(currentobj, 'tag'))
try
resstructout = setfield(resstructout, get(currentobj, 'tag'), resultout{counter});
catch
fprintf('Warning: tag "%" may not be use as field in output structure', get(currentobj, 'tag'));
end
end
counter = counter+1;
case 'edit'
resultout{counter} = get( currentobj, 'string');
if ~isempty(get(currentobj, 'tag'))
try
resstructout = setfield(resstructout, get(currentobj, 'tag'), resultout{counter});
catch
fprintf('Warning: tag "%" may not be use as field in output structure', get(currentobj, 'tag'));
end
end
counter = counter+1;
end
catch, end
else
ps = currentobj.GetPropertySpecification;
resultout{counter} = arg_tovals(ps,false);
count = 1;
while isfield(resstructout, ['propgrid' int2str(count)])
count = count + 1;
end
resstructout = setfield(resstructout, ['propgrid' int2str(count)], arg_tovals(ps,false));
end
end