File: TwoStateQuery.m

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (175 lines) | stat: -rw-r--r-- 7,260 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
function UserResponse = TwoStateQuery(TheQuestion,TheChoices)
% Syntax: UserResponse = TwoStateQuery(TheQuestion,[TheChoices])
% 
% Purpose: Create simple dialog box asking user an either/or question.
% On non-GUI setups it will ask a question in the command window instead
% of showing a GUI dialog box.
%
% History:  5/5/04   mpr   decided whether or not to celebrate cinco de mayo
%           10/13/04 mpr   set Yes Button automatically to be enlarged for large
%                          strings 
%           1/21/05  mpr   allowed fontsize to shrink for longer questions
%           1/27/05  mpr   allowed question to break at file separator instead of
%                          just spaces 
%           6/30/05  mpr   orced underscores to remain as underscores instead of
%                          indicating subscript
%           3/27/06  mpr   changed returned value to -1 when user deletes window;
%                          note that this is dangerous because how a closed
%                          window affects subsequent program behavior is not
%                          implemented the same way in all code calling this
%                          function... 
%           5/3/06   mpr   set menubar to none for Version 2006a
%           8/25/06  mpr   resized No Button as needed; could be done better, but  
%                          the plan is to keep the 'Yes' and 'No' strings short
%                          so that the code doesn't need to be pushed hard
%           9/29/06  mpr   repainted buttons in version 7
%           1/14/07  mpr   undid previoius fix because button color bug is almost
%                          fixed
%           5/20/13  mk    Add text only fallback for Octave and non-GUI.
%          11/05/15  mk    Add GUI dialog for Octave in GUI mode. White-space cleanup.
%           7/20/17  mk    Use text only fallback on Matlab R2014b and later.
%           7/11/19  dn    GUI version now works on Matlab R2014b and later.
%           8/28/20  mk    Always use questdlg() instead of Matlab specific
%                          figure contraption. Nicer look.

if nargin < 2 || isempty(TheChoices)
  TheChoices{1} = 'Yes';
  TheChoices{2} = 'No';
elseif length(TheChoices) ~= 2 || ~iscell(TheChoices)
  warning('I don''t like the choices I received.  Am substituting unadulterated originals.');
  disp('But for kicks, this is what I was passed:');
  TheChoices
  TheChoices{1} = 'Yes';
  TheChoices{2} = 'No';
end	

UnderScoreSpots = find(TheQuestion == '_');
for k=length(UnderScoreSpots):-1:1
  TheQuestion = [TheQuestion(1:(UnderScoreSpots(k)-1)) '\' TheQuestion(UnderScoreSpots(k):end)];
end

% Provide text fallback for non-GUI mode:
if ~IsGUI
  fprintf('%s\n', TheQuestion);
  fprintf('0 = %s\n', TheChoices{2});
  fprintf('1 = %s\n', TheChoices{1});
  answer = input('Choose your answer: ','s');
  if isempty(answer) || (answer~='0' && answer~='1')
    UserResponse = -1;
  else
      UserResponse = sscanf(answer, '%i');
  end
  
  return;
end

% questdlg builtin dialog box for Octave with GUI:
% MK: Always use this one, even on Matlab. I can not see the advantage of
% the Matlab specific contraption below? It seems to provide the same
% functionality, but with way more ugly formatting?
% Except on Matlab for macOS on Apple Silicon, where questdlg() is broken
% as of R2024a - Half of the time it works, the other half clicking on a
% button causes Matlab to hang with the spinning beach ball of death.
if IsOctave || ~(IsOSX && IsARM)
  button = questdlg(TheQuestion, 'Question', TheChoices{1}, TheChoices{2}, 'Cancel', 'Cancel');
  if ~isempty(strfind(button, TheChoices{1}))
    UserResponse = 1;
  elseif ~isempty(strfind(button, TheChoices{2}))
    UserResponse = 0;
  else
    UserResponse = -1;
  end
  return;
end

% NOT reached in current implementation!
FigPos = [300 600];
FigWidth = 500;
FigHeight = 200;
YesBPos = [125 30];
YesBWidth = 80;
YesBHeight = 50;
NoBPos = [295 30];

PrimeFontSize = 36;

QueryFigh = figure('Position',[FigPos FigWidth FigHeight],'Resize','off','NumberTitle','off', ...
                  'Name','Question','MenuBar','none','Color','k');
QueryFighNr = QueryFigh;
if ~isnumeric(QueryFighNr)
    QueryFighNr = QueryFigh.Number;
end
set(QueryFigh,'Tag',['Questionable Figure ' int2str(QueryFighNr)]);
axes('Position',[0 0 1 1],'XLim',[0 FigWidth],'YLim',[0 FigHeight],'XColor','k','YColor','k');
th=text(FigWidth/2,0.65*FigHeight,TheQuestion,'FontSize',36,'Color',get_color('hot pink'), ...
        'HorizontalAlignment','Center');
TextExt = get(th,'Extent');
if TextExt(1) < 0
  SpaceLocs = find(TheQuestion == 32 | TheQuestion == abs(filesep));
  [MinDist, MinInd] = min(abs(floor(length(TheQuestion)/2)-SpaceLocs));
  if TheQuestion(SpaceLocs(MinInd)) == abs(filesep)
    set(th,'String',sprintf('%s\n%s',TheQuestion(1:SpaceLocs(MinInd)),TheQuestion((SpaceLocs(MinInd)+1):end)));
  else
    set(th,'String',sprintf('%s\n%s',TheQuestion(1:(SpaceLocs(MinInd)-1)),TheQuestion((SpaceLocs(MinInd)+1):end)));
  end
  while TextExt(1) < 0 && get(th,'FontSize') > 8
    set(th,'FontSize',get(th,'FontSize')-1);
    TextExt = get(th,'Extent');
    % I should create an error if font size does get down to 8, but I don't expect it ever to happen, so I'm not
    % going to deal with it.
  end
end
YesBh = uicontrol('Style','PushButton','Position',[YesBPos YesBWidth YesBHeight],'String',TheChoices{1}, ...
                  'ForeGroundColor',get_color('midnight blue'),'BackgroundColor', ...
                  get_color('wheat'),'FontSize',36,'Tag','YesButton','UserData',-1);
set(YesBh,'CallBack',['set(findobj(' int2str(QueryFighNr) ',''Tag'',''YesButton''),''UserData'',1);']);
NoBWidth = YesBWidth;
NoBHeight = YesBHeight; 
NoBh = uicontrol('Style','PushButton','Position',[NoBPos YesBWidth YesBHeight],'String',TheChoices{2}, ...
                'ForeGroundColor',get_color('midnight blue'),'BackgroundColor', ...
                get_color('wheat'),'FontSize',36,'CallBack', ...
                ['set(findobj(' int2str(QueryFighNr) ',''Tag'',''YesButton''),''UserData'',0);']);
YesBSSize = get(YesBh,'Extent');
while YesBSSize(3) > YesBWidth
  if YesBPos(1)+YesBWidth > NoBPos(1) - YesBWidth/2
    set(YesBh,'FontSize',get(YesBh,'FontSize')-12);
    if ~get(uih,'FontSize')
      error('Yes string is too big!');
    end
  else
    YesBPos(1) = YesBPos(1) - (YesBSSize(3)-YesBWidth)/2;
    YesBWidth = 1.1*YesBSSize(3);
    set(YesBh,'Position',[YesBPos YesBWidth YesBHeight]);
  end
  YesBSSize = get(YesBh,'Extent');
end

NoBSSize = get(NoBh,'Extent');
while NoBSSize(3) > NoBWidth
  if NoBWidth < YesBWidth
    NoBWidth = YesBWidth;
    set(NoBh,'Position',[NoBPos NoBWidth NoBHeight]);
  elseif NoBPos(1)+NoBWidth < 0.9*FigWidth
    NoBWidth = NoBWidth*1.1;
    set(NoBh,'Position',[NoBPos NoBWidth NoBHeight]);
  else
    set(NoBh,'FontSize',get(NoBh,'FontSize')-12);
    if ~get(NoBh,'FontSize')
      error('No string is too big!');
    end
  end
  NoBSSize = get(NoBh,'Extent');
end

drawnow;
waitfor(YesBh,'UserData');

% just in case user deletes figure rather than clicking button
if isempty(findobj('Tag',['Questionable Figure ' int2str(QueryFighNr) ]))
  UserResponse = -1;
else
  UserResponse = get(YesBh,'UserData');
  delete(QueryFigh);
end

return;