classdef TextUIQuestionnaire < handle
% This source file is subject to version 3 of the GPL license,
% that is bundled with this package in the file LICENSE, and is
% available online at http://www.gnu.org/licenses/gpl.txt
%
% This source file can be linked to GPL-incompatible facilities,
% produced or made available by MathWorks, Inc.
properties (GetAccess = public, SetAccess = private)
Title;
Items;
end
methods (Access = public)
function TQobj = TextUIQuestionnaire(Title, Props)
TQobj.Title = Title;
if (nargin == 2)
for t=1:size(Props,2) / 2,
TQobj.(Props{t*2-1}) = Props{t*2};
end
end
end
function ret = DeleteItem(TQobj, id)
ret = false;
if ((id < 1) || (id > size(TQobj.Items,1)))
return;
end
TQobj.Items(id) = [];
ret = true;
end
function InsertItem(TQobj, item, pos)
if (size(TQobj.Items,1) == 0 )
TQobj.Items = { item };
else
switch upper(pos)
case 'BGN'
TQobj.Items = [ { item }; TQobj.Items ];
case 'END'
TQobj.Items = [ TQobj.Items; { item } ];
otherwise
TQobj.Items = [ TQobj.Items(1:pos-1,1); { item }; TQobj.Items(pos:end,1)];
end
end
end
function ret = SetItemProperty(TQobj, itemTag, itemProperty, value)
ret = false;
question = TQobj.getItemByTag(itemTag);
if ~isempty(question)
TQobj.getItemByTag(itemTag).(itemProperty) = value;
ret = true;
end
end
function ret = Ask(TQobj)
while (true)
jumpto = 0;
ret = false;
t = 1;
while (t <= size(TQobj.Items, 1))
options = '';
% Handle list questions
if (TQobj.Items{t}.List)
if ~strcmpi(TQobj.Items{t}.ListSelect, 'one')
fprintf('WARNING: Only ListSelect one is currently supported\n');
% At some point will have to deal with
% 'many'. The trickest part is to handle
% DefaultAnswer.
return;
end
for s=1:size(TQobj.Items{t}.ListItems, 1),
if ~isempty(options)
options = sprintf('%s / ', options);
end
if strcmpi(TQobj.Items{t}.DefaultAnswer, TQobj.Items{t}.ListItems{s})
options = sprintf('%s%s', options, upper(TQobj.Items{t}.ListItems{s}));
else
options = sprintf('%s%s', options, TQobj.Items{t}.ListItems{s});
end
end
if (TQobj.Items{t}.Cancelable)
options = sprintf('%s / Cancel', options);
end
if ~isempty(TQobj.Items{t}.HelpMessage)
prompt = sprintf('%s (%s or help) : ', TQobj.Items{t}.Question, options);
else
prompt = sprintf('%s (%s) : ', TQobj.Items{t}.Question, options);
end
while (true)
if (~isempty(TQobj.Items{t}.Details))
fprintf('\n%s\n\n', TQobj.Items{t}.Details);
end
answer = input(prompt, 's');
if strcmpi(answer, 'help') && ~isempty(TQobj.Items{t}.HelpMessage)
fprintf('\nHELP: %s\n\n', TQobj.Items{t}.HelpMessage);
continue;
elseif (strcmpi(answer, 'cancel') && (TQobj.Items{t}.Cancelable == true))
return;
elseif (isempty(answer) && ~isempty(TQobj.Items{t}.DefaultAnswer))
answer = TQobj.Items{t}.DefaultAnswer;
elseif (isempty(answer) && isempty(TQobj.Items{t}.DefaultAnswer) && TQobj.Items{t}.EmptyAnswer == false)
continue;
end
if (isa(TQobj.Items{t}.ValidateCallback, 'function_handle'))
retVal = TQobj.Items{t}.ValidateCallback(answer);
if (~isnumeric(retVal))
nextQuestion = TQobj.getItemIDByTag(retVal);
if ((nextQuestion) ~= 0)
jumpto = nextQuestion;
break;
else
jumpto = size(TQobj.Items, 1) + 1;
break;
end
end
if (retVal == 1)
break;
elseif (retVal == 2)
return;
else
continue;
end
else
break;
end
end
else
% Handle non-list questions
if ~isempty(TQobj.Items{t}.HelpMessage) && ~isempty(TQobj.Items{t}.DefaultAnswer)
prompt = sprintf('%s ([%s] or help) : ', TQobj.Items{t}.Question, TQobj.Items{t}.DefaultAnswer);
elseif ~isempty(TQobj.Items{t}.DefaultAnswer)
prompt = sprintf('%s ([%s]) : ', TQobj.Items{t}.Question, TQobj.Items{t}.DefaultAnswer);
elseif ~isempty(TQobj.Items{t}.HelpMessage)
prompt = sprintf('%s (enter value or help) : ', TQobj.Items{t}.Question);
else
prompt = sprintf('%s : ', TQobj.Items{t}.Question);
end
while (true)
if (~isempty(TQobj.Items{t}.Details))
fprintf('\n%s\n\n', TQobj.Items{t}.Details)
end
answer = input(prompt, 's');
if strcmpi(answer, 'help') && ~isempty(TQobj.Items{t}.HelpMessage)
fprintf('\nHELP: %s\n\n', TQobj.Items{t}.HelpMessage);
continue;
elseif (strcmpi(answer, 'cancel') && (TQobj.Items{t}.Cancelable == true))
return;
elseif (isempty(answer) && ~isempty(TQobj.Items{t}.DefaultAnswer))
answer = TQobj.Items{t}.DefaultAnswer;
elseif (isempty(answer) && isempty(TQobj.Items{t}.DefaultAnswer) && TQobj.Items{t}.EmptyAnswer == false)
continue;
end
if (isa(TQobj.Items{t}.ValidateCallback, 'function_handle'))
retVal = TQobj.Items{t}.ValidateCallback(answer);
if (~isnumeric(retVal))
nextQuestion = TQobj.getItemIDByTag(retVal);
if ((nextQuestion) ~= 0)
jumpto = nextQuestion;
break;
else
jumpto = size(TQobj.Items, 1) + 1;
break;
end
end
if (retVal == 1)
break;
elseif (retVal == 2)
return;
else
continue;
end
else
break;
end
end
end
if (isa(TQobj.Items{t}.AnswerOverrideCallback, 'function_handle'))
TQobj.Items{t}.DefaultAnswer = TQobj.Items{t}.AnswerOverrideCallback(answer);
else
TQobj.Items{t}.DefaultAnswer = answer;
end
if (jumpto ~= 0)
t = jumpto;
jumpto = 0;
else
t=t+1;
end
end
if (TQobj.reviewQuestionnaire() == 0)
ret = 1;
return;
end
end
end
function ret = GetItemByTag(TQobj, itemTag)
ret = {};
for t=1:size(TQobj.Items,1),
if (strcmp(TQobj.Items{t}.Tag,itemTag))
ret = TQobj.Items{t};
return;
end
end
end
end
methods (Access = private)
function ret = getItemByTag(TQobj, itemTag)
ret = {};
for t=1:size(TQobj.Items,1),
if (strcmp(TQobj.Items{t}.Tag,itemTag))
ret = TQobj.Items{t};
return;
end
end
end
function ret = getItemIDByTag(TQobj, itemTag)
ret = 0;
for t=1:size(TQobj.Items,1),
if (strcmp(TQobj.Items{t}.Tag,itemTag))
ret = t;
return;
end
end
end
function ret = reviewQuestionnaire(TQobj)
fprintf('\nPLEASE REVIEW YOUR INPUT\n-----------------------------\n');
for t=1:size(TQobj.Items, 1),
if (TQobj.Items{t}.DisplayInReview)
fprintf('%s : %s\n', TQobj.Items{t}.Question, TQobj.Items{t}.DefaultAnswer);
end
end
fprintf('\n');
prompt = 'Do you want repeat the questionnaire (yes/NO) : ';
while (true)
answer = input(prompt, 's');
if (strcmpi(answer, 'yes'))
ret = true;
break;
elseif ((strcmpi(answer, 'no')) || isempty(answer))
ret = false;
break;
end
end
end
end
end